From 1202e11491a23ed166f22ebf8a4566f570fd6efb Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Sat, 27 Jun 2026 11:03:34 -0500 Subject: [PATCH 01/16] First pass at adding versions to games --- ...20260627014632_AddGameVersions.Designer.cs | 3418 +++++++++++++++++ .../20260627014632_AddGameVersions.cs | 202 + .../DatabaseContextModelSnapshot.cs | 129 + ...20260627014314_AddGameVersions.Designer.cs | 3418 +++++++++++++++++ .../20260627014314_AddGameVersions.cs | 195 + .../DatabaseContextModelSnapshot.cs | 129 + ...20260627014005_AddGameVersions.Designer.cs | 3409 ++++++++++++++++ .../20260627014005_AddGameVersions.cs | 195 + .../DatabaseContextModelSnapshot.cs | 129 + LANCommander.Server.Data/DatabaseContext.cs | 40 + LANCommander.Server.Data/Models/Action.cs | 6 + LANCommander.Server.Data/Models/Archive.cs | 6 + LANCommander.Server.Data/Models/Game.cs | 1 + .../Models/GameVersion.cs | 29 + LANCommander.Server.Data/Models/SavePath.cs | 6 + LANCommander.Server.Data/Models/Script.cs | 6 + .../IServiceCollectionExtensions.cs | 1 + LANCommander.Server.Services/GameService.cs | 66 +- .../GameVersionBackfill.cs | 111 + .../GameVersionService.cs | 183 + .../Mappers/MappingProfile.cs | 8 +- .../ApplicationFixture.cs | 4 +- LANCommander.Server.Tests/BaseTest.cs | 1 - .../Client/AuthenticationTests.cs | 10 +- .../Data/VersioningTests.cs | 312 +- .../Mocks/GitHubServiceMockFactory.cs | 1 + .../Mocks/VersionProviderMock.cs | 1 + .../Services/ImporterTests.cs | 8 +- .../Services/SaveClientTests.cs | 29 +- .../Services/UpdateServiceTests.cs | 1 + .../Models/ScriptEditorOptions.cs | 1 + LANCommander.Server/Startup/Database.cs | 6 + .../UI/Components/ActionEditor.razor | 19 +- .../UI/Components/ArchiveUploader.razor | 34 +- .../UI/Components/ScriptEditor.razor | 15 +- .../UI/Components/ScriptEditorDialog.razor | 1 + .../UI/Components/VersionEditor.razor | 79 + .../Pages/Games/Components/GameEditView.razor | 1 + .../Games/Components/SavePathEditor.razor | 10 +- .../UI/Pages/Games/Edit/Versions.razor | 10 + .../UI/Pages/Settings/Archives.razor | 4 - 41 files changed, 12165 insertions(+), 69 deletions(-) create mode 100644 LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.Designer.cs create mode 100644 LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.cs create mode 100644 LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.Designer.cs create mode 100644 LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.cs create mode 100644 LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.Designer.cs create mode 100644 LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.cs create mode 100644 LANCommander.Server.Data/Models/GameVersion.cs create mode 100644 LANCommander.Server.Services/GameVersionBackfill.cs create mode 100644 LANCommander.Server.Services/GameVersionService.cs create mode 100644 LANCommander.Server/UI/Components/VersionEditor.razor create mode 100644 LANCommander.Server/UI/Pages/Games/Edit/Versions.razor diff --git a/LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.Designer.cs b/LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.Designer.cs new file mode 100644 index 00000000..ead97f99 --- /dev/null +++ b/LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.Designer.cs @@ -0,0 +1,3418 @@ +// +using System; +using LANCommander.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace LANCommander.Server.Data.MySQL.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20260627014632_AddGameVersions")] + partial class AddGameVersions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("CategoryGame", b => + { + b.Property("CategoriesId") + .HasColumnType("char(36)"); + + b.Property("GamesId") + .HasColumnType("char(36)"); + + b.HasKey("CategoriesId", "GamesId"); + + b.HasIndex("GamesId"); + + b.ToTable("CategoryGame"); + }); + + modelBuilder.Entity("ChatThreadUser", b => + { + b.Property("ChatThreadsId") + .HasColumnType("char(36)"); + + b.Property("ParticipantsId") + .HasColumnType("char(36)"); + + b.HasKey("ChatThreadsId", "ParticipantsId"); + + b.HasIndex("ParticipantsId"); + + b.ToTable("ChatThreadUser"); + }); + + modelBuilder.Entity("CollectionGame", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.HasKey("CollectionId", "GameId"); + + b.HasIndex("GameId"); + + b.ToTable("CollectionGame"); + }); + + modelBuilder.Entity("GameDeveloper", b => + { + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("DeveloperId") + .HasColumnType("char(36)"); + + b.HasKey("GameId", "DeveloperId"); + + b.HasIndex("DeveloperId"); + + b.ToTable("GameDeveloper"); + }); + + modelBuilder.Entity("GameGenre", b => + { + b.Property("GamesId") + .HasColumnType("char(36)"); + + b.Property("GenresId") + .HasColumnType("char(36)"); + + b.HasKey("GamesId", "GenresId"); + + b.HasIndex("GenresId"); + + b.ToTable("GameGenre"); + }); + + modelBuilder.Entity("GamePlatform", b => + { + b.Property("GamesId") + .HasColumnType("char(36)"); + + b.Property("PlatformsId") + .HasColumnType("char(36)"); + + b.HasKey("GamesId", "PlatformsId"); + + b.HasIndex("PlatformsId"); + + b.ToTable("GamePlatform"); + }); + + modelBuilder.Entity("GamePublisher", b => + { + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("PublisherId") + .HasColumnType("char(36)"); + + b.HasKey("GameId", "PublisherId"); + + b.HasIndex("PublisherId"); + + b.ToTable("GamePublisher"); + }); + + modelBuilder.Entity("GameRedistributable", b => + { + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("RedistributableId") + .HasColumnType("char(36)"); + + b.Property("Options") + .HasColumnType("longtext"); + + b.HasKey("GameId", "RedistributableId"); + + b.HasIndex("RedistributableId"); + + b.ToTable("GameRedistributable"); + }); + + modelBuilder.Entity("GameTag", b => + { + b.Property("GamesId") + .HasColumnType("char(36)"); + + b.Property("TagsId") + .HasColumnType("char(36)"); + + b.HasKey("GamesId", "TagsId"); + + b.HasIndex("TagsId"); + + b.ToTable("GameTag"); + }); + + modelBuilder.Entity("GameTool", b => + { + b.Property("GamesId") + .HasColumnType("char(36)"); + + b.Property("ToolsId") + .HasColumnType("char(36)"); + + b.HasKey("GamesId", "ToolsId"); + + b.HasIndex("ToolsId"); + + b.ToTable("GameTool"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Action", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Arguments") + .HasColumnType("longtext"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("GameVersionId") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OptionOverrides") + .HasColumnType("longtext"); + + b.Property("Path") + .HasColumnType("longtext"); + + b.Property("PrimaryAction") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("char(36)"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("ToolId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("WorkingDirectory") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Actions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Archive", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Changelog") + .HasColumnType("longtext"); + + b.Property("CompressedSize") + .HasColumnType("bigint"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("GameVersionId") + .HasColumnType("char(36)"); + + b.Property("LastVersionId") + .HasColumnType("char(36)"); + + b.Property("ObjectKey") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RedistributableId") + .HasColumnType("char(36)"); + + b.Property("StorageLocationId") + .HasColumnType("char(36)"); + + b.Property("ToolId") + .HasColumnType("char(36)"); + + b.Property("UncompressedSize") + .HasColumnType("bigint"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Version") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId") + .IsUnique(); + + b.HasIndex("LastVersionId"); + + b.HasIndex("RedistributableId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Archive"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ParentId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ParentId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("varchar(2000)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("ThreadId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ThreadId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ChatMessages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ChatThreads"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThreadReadStatus", b => + { + b.Property("ThreadId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LastReadMessageId") + .HasColumnType("char(36)"); + + b.HasKey("ThreadId", "UserId"); + + b.HasIndex("LastReadMessageId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatThreadReadStatuses"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Collection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Collections"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Engines"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BaseGameId") + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("DirectoryName") + .HasColumnType("longtext"); + + b.Property("EngineId") + .HasColumnType("char(36)"); + + b.Property("KeyAllocationMethod") + .HasColumnType("int"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("ReleasedOn") + .HasColumnType("datetime(6)"); + + b.Property("Singleplayer") + .HasColumnType("tinyint(1)"); + + b.Property("SortTitle") + .HasColumnType("longtext"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("ValidKeyRegex") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("BaseGameId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("EngineId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Games"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameCustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameCustomField"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameExternalId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("ExternalId") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameExternalIds"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameSave", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("StorageLocationId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("GameSaves"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Changelog") + .HasColumnType("longtext"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Version") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameVersions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Genres"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Issue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("ResolvedById") + .HasColumnType("char(36)"); + + b.Property("ResolvedOn") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("ResolvedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Key", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllocationMethod") + .HasColumnType("int"); + + b.Property("ClaimedByComputerName") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("ClaimedByIpv4Address") + .HasMaxLength(15) + .HasColumnType("varchar(15)"); + + b.Property("ClaimedByMacAddress") + .HasMaxLength(17) + .HasColumnType("varchar(17)"); + + b.Property("ClaimedByUserId") + .HasColumnType("char(36)"); + + b.Property("ClaimedOn") + .HasColumnType("datetime(6)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("ClaimedByUserId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Keys"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Library", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Libraries"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Crc32") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("varchar(8)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("FileId") + .HasColumnType("char(36)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("MimeType") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("SourceUrl") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("StorageLocationId") + .HasColumnType("char(36)"); + + b.Property("ThumbnailId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("ThumbnailId") + .IsUnique(); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.MultiplayerMode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("MaxPlayers") + .HasColumnType("int"); + + b.Property("MinPlayers") + .HasColumnType("int"); + + b.Property("NetworkProtocol") + .HasColumnType("int"); + + b.Property("Spectators") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("MultiplayerModes"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Contents") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("ParentId") + .HasColumnType("char(36)"); + + b.Property("Route") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ToolId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ParentId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Pages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Platform", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Platforms"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.PlaySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("End") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("Start") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("PlaySessions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Rating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("Source") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Ratings"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OptionSchema") + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Redistributables"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("GameVersionId") + .HasColumnType("char(36)"); + + b.Property("IsRegex") + .HasColumnType("tinyint(1)"); + + b.Property("Path") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("WorkingDirectory") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("SavePaths"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Script", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Contents") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("GameVersionId") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RedistributableId") + .HasColumnType("char(36)"); + + b.Property("RequiresAdmin") + .HasColumnType("tinyint(1)"); + + b.Property("ServerId") + .HasColumnType("char(36)"); + + b.Property("ToolId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("RedistributableId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Arguments") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Autostart") + .HasColumnType("tinyint(1)"); + + b.Property("AutostartDelay") + .HasColumnType("int"); + + b.Property("AutostartMethod") + .HasColumnType("int"); + + b.Property("ContainerId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("DockerHostId") + .HasColumnType("char(36)"); + + b.Property("Engine") + .HasColumnType("int"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("Host") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OnStartScriptPath") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OnStopScriptPath") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Path") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Port") + .HasColumnType("int"); + + b.Property("ProcessTerminationMethod") + .HasColumnType("int"); + + b.Property("RemoteHostId") + .HasColumnType("char(36)"); + + b.Property("RemoteServerId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UseShellExecute") + .HasColumnType("tinyint(1)"); + + b.Property("WorkingDirectory") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Servers"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerConsole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Host") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("Port") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ServerConsoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerHttpPath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("LocalPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ServerId") + .HasColumnType("char(36)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ServerHttpPath"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Default") + .HasColumnType("tinyint(1)"); + + b.Property("Path") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("StorageLocations"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Tools"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ApprovedOn") + .HasColumnType("datetime(6)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("RefreshToken") + .HasColumnType("longtext"); + + b.Property("RefreshTokenExpiration") + .HasColumnType("datetime(6)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("UserCustomField"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("LibraryGame", b => + { + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("LibraryId") + .HasColumnType("char(36)"); + + b.HasKey("GameId", "LibraryId"); + + b.HasIndex("LibraryId"); + + b.ToTable("LibraryGame"); + }); + + modelBuilder.Entity("PageGame", b => + { + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("PageId") + .HasColumnType("char(36)"); + + b.HasKey("GameId", "PageId"); + + b.HasIndex("PageId"); + + b.ToTable("PageGame"); + }); + + modelBuilder.Entity("PageRedistributable", b => + { + b.Property("PageId") + .HasColumnType("char(36)"); + + b.Property("RedistributableId") + .HasColumnType("char(36)"); + + b.HasKey("PageId", "RedistributableId"); + + b.HasIndex("RedistributableId"); + + b.ToTable("PageRedistributable"); + }); + + modelBuilder.Entity("PageServer", b => + { + b.Property("PageId") + .HasColumnType("char(36)"); + + b.Property("ServerId") + .HasColumnType("char(36)"); + + b.HasKey("PageId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("PageServer"); + }); + + modelBuilder.Entity("RoleCollection", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("CollectionId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleCollection"); + }); + + modelBuilder.Entity("CategoryGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Category", null) + .WithMany() + .HasForeignKey("CategoriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ChatThreadUser", b => + { + b.HasOne("LANCommander.Server.Data.Models.ChatThread", null) + .WithMany() + .HasForeignKey("ChatThreadsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("ParticipantsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("CollectionGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Collection", null) + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameDeveloper", b => + { + b.HasOne("LANCommander.Server.Data.Models.Company", null) + .WithMany() + .HasForeignKey("DeveloperId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameGenre", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Genre", null) + .WithMany() + .HasForeignKey("GenresId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GamePlatform", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Platform", null) + .WithMany() + .HasForeignKey("PlatformsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GamePublisher", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Company", null) + .WithMany() + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameRedistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", null) + .WithMany() + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameTag", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tag", null) + .WithMany() + .HasForeignKey("TagsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameTool", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tool", null) + .WithMany() + .HasForeignKey("ToolsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Action", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Actions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Actions") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("Actions") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Actions") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("Server"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Archive", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Archives") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithOne("Archive") + .HasForeignKey("LANCommander.Server.Data.Models.Archive", "GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Archive", "LastVersion") + .WithMany() + .HasForeignKey("LastVersionId"); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") + .WithMany("Archives") + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("Archives") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Archives") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("LastVersion"); + + b.Navigation("Redistributable"); + + b.Navigation("StorageLocation"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Category", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Parent"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatMessage", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.ChatThread", "Thread") + .WithMany("Messages") + .HasForeignKey("ThreadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Thread"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThreadReadStatus", b => + { + b.HasOne("LANCommander.Server.Data.Models.ChatMessage", "LastReadMessage") + .WithMany() + .HasForeignKey("LastReadMessageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.ChatThread", "Thread") + .WithMany() + .HasForeignKey("ThreadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LastReadMessage"); + + b.Navigation("Thread"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Collection", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Company", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", "BaseGame") + .WithMany("DependentGames") + .HasForeignKey("BaseGameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Engine", "Engine") + .WithMany("Games") + .HasForeignKey("EngineId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("BaseGame"); + + b.Navigation("CreatedBy"); + + b.Navigation("Engine"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameCustomField", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("CustomFields") + .HasForeignKey("GameId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameExternalId", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("ExternalIds") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameSave", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("GameSaves") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("GameSaves") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("GameSaves") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("StorageLocation"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Versions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Issue", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Issues") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "ResolvedBy") + .WithMany() + .HasForeignKey("ResolvedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("ResolvedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Key", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "ClaimedByUser") + .WithMany() + .HasForeignKey("ClaimedByUserId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Keys") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("ClaimedByUser"); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Library", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithOne("Library") + .HasForeignKey("LANCommander.Server.Data.Models.Library", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Media") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("Media") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Media", "Thumbnail") + .WithOne("Parent") + .HasForeignKey("LANCommander.Server.Data.Models.Media", "ThumbnailId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("Media") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("StorageLocation"); + + b.Navigation("Thumbnail"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.MultiplayerMode", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("MultiplayerModes") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Page", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", null) + .WithMany("Pages") + .HasForeignKey("ToolId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Parent"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Platform", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.PlaySession", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("PlaySessions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("PlaySessions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Rating", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Ratings") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("SavePaths") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("SavePaths") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Script", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Scripts") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Scripts") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") + .WithMany("Scripts") + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("Scripts") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Scripts") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("Redistributable"); + + b.Navigation("Server"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Servers") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerConsole", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("ServerConsoles") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Server"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerHttpPath", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("HttpPaths") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Server"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tag", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("CustomFields") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("UserRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LibraryGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Library", null) + .WithMany() + .HasForeignKey("LibraryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageRedistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", null) + .WithMany() + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageServer", b => + { + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Server", null) + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleCollection", b => + { + b.HasOne("LANCommander.Server.Data.Models.Collection", null) + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.Navigation("Games"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.Navigation("Actions"); + + b.Navigation("Archives"); + + b.Navigation("CustomFields"); + + b.Navigation("DependentGames"); + + b.Navigation("ExternalIds"); + + b.Navigation("GameSaves"); + + b.Navigation("Issues"); + + b.Navigation("Keys"); + + b.Navigation("Media"); + + b.Navigation("MultiplayerModes"); + + b.Navigation("PlaySessions"); + + b.Navigation("Ratings"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); + + b.Navigation("Servers"); + + b.Navigation("Versions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Navigation("Actions"); + + b.Navigation("Archive"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.Navigation("Archives"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.Navigation("Actions"); + + b.Navigation("HttpPaths"); + + b.Navigation("Scripts"); + + b.Navigation("ServerConsoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.Navigation("Archives"); + + b.Navigation("GameSaves"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.Navigation("Actions"); + + b.Navigation("Archives"); + + b.Navigation("Pages"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.Navigation("CustomFields"); + + b.Navigation("GameSaves"); + + b.Navigation("Library") + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("PlaySessions"); + + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.cs b/LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.cs new file mode 100644 index 00000000..fad2cd90 --- /dev/null +++ b/LANCommander.Server.Data.MySQL/Migrations/20260627014632_AddGameVersions.cs @@ -0,0 +1,202 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Server.Data.MySQL.Migrations +{ + /// + public partial class AddGameVersions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Scripts", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "SavePaths", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Archive", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Actions", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.CreateTable( + name: "GameVersions", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Version = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Changelog = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + SortOrder = table.Column(type: "int", nullable: false), + GameId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedOn = table.Column(type: "datetime(6)", nullable: false), + CreatedById = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + UpdatedOn = table.Column(type: "datetime(6)", nullable: false), + UpdatedById = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_GameVersions", x => x.Id); + table.ForeignKey( + name: "FK_GameVersions_Games_GameId", + column: x => x.GameId, + principalTable: "Games", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_GameVersions_Users_CreatedById", + column: x => x.CreatedById, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + table.ForeignKey( + name: "FK_GameVersions_Users_UpdatedById", + column: x => x.UpdatedById, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Scripts_GameVersionId", + table: "Scripts", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_SavePaths_GameVersionId", + table: "SavePaths", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_Archive_GameVersionId", + table: "Archive", + column: "GameVersionId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Actions_GameVersionId", + table: "Actions", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_CreatedById", + table: "GameVersions", + column: "CreatedById"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_GameId", + table: "GameVersions", + column: "GameId"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_UpdatedById", + table: "GameVersions", + column: "UpdatedById"); + + migrationBuilder.AddForeignKey( + name: "FK_Actions_GameVersions_GameVersionId", + table: "Actions", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Archive_GameVersions_GameVersionId", + table: "Archive", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_SavePaths_GameVersions_GameVersionId", + table: "SavePaths", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Scripts_GameVersions_GameVersionId", + table: "Scripts", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Actions_GameVersions_GameVersionId", + table: "Actions"); + + migrationBuilder.DropForeignKey( + name: "FK_Archive_GameVersions_GameVersionId", + table: "Archive"); + + migrationBuilder.DropForeignKey( + name: "FK_SavePaths_GameVersions_GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropForeignKey( + name: "FK_Scripts_GameVersions_GameVersionId", + table: "Scripts"); + + migrationBuilder.DropTable( + name: "GameVersions"); + + migrationBuilder.DropIndex( + name: "IX_Scripts_GameVersionId", + table: "Scripts"); + + migrationBuilder.DropIndex( + name: "IX_SavePaths_GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropIndex( + name: "IX_Archive_GameVersionId", + table: "Archive"); + + migrationBuilder.DropIndex( + name: "IX_Actions_GameVersionId", + table: "Actions"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Scripts"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Archive"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Actions"); + } + } +} diff --git a/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs b/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs index 022d02b3..2131708a 100644 --- a/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs +++ b/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs @@ -193,6 +193,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("GameId") .HasColumnType("char(36)"); + b.Property("GameVersionId") + .HasColumnType("char(36)"); + b.Property("Name") .IsRequired() .HasColumnType("longtext"); @@ -230,6 +233,8 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("ServerId"); b.HasIndex("ToolId"); @@ -260,6 +265,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("GameId") .HasColumnType("char(36)"); + b.Property("GameVersionId") + .HasColumnType("char(36)"); + b.Property("LastVersionId") .HasColumnType("char(36)"); @@ -295,6 +303,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId") + .IsUnique(); + b.HasIndex("LastVersionId"); b.HasIndex("RedistributableId"); @@ -722,6 +733,48 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.ToTable("GameSaves"); }); + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Changelog") + .HasColumnType("longtext"); + + b.Property("CreatedById") + .HasColumnType("char(36)"); + + b.Property("CreatedOn") + .HasColumnType("datetime(6)"); + + b.Property("GameId") + .HasColumnType("char(36)"); + + b.Property("SortOrder") + .HasColumnType("int"); + + b.Property("UpdatedById") + .HasColumnType("char(36)"); + + b.Property("UpdatedOn") + .HasColumnType("datetime(6)"); + + b.Property("Version") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameVersions"); + }); + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => { b.Property("Id") @@ -1308,6 +1361,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("GameId") .HasColumnType("char(36)"); + b.Property("GameVersionId") + .HasColumnType("char(36)"); + b.Property("IsRegex") .HasColumnType("tinyint(1)"); @@ -1333,6 +1389,8 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("UpdatedById"); b.ToTable("SavePaths"); @@ -1360,6 +1418,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("GameId") .HasColumnType("char(36)"); + b.Property("GameVersionId") + .HasColumnType("char(36)"); + b.Property("Name") .IsRequired() .HasColumnType("longtext"); @@ -1391,6 +1452,8 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("RedistributableId"); b.HasIndex("ServerId"); @@ -2156,6 +2219,11 @@ namespace LANCommander.Server.Data.MySQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Actions") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") .WithMany("Actions") .HasForeignKey("ServerId") @@ -2175,6 +2243,8 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("Server"); b.Navigation("Tool"); @@ -2194,6 +2264,11 @@ namespace LANCommander.Server.Data.MySQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithOne("Archive") + .HasForeignKey("LANCommander.Server.Data.Models.Archive", "GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Archive", "LastVersion") .WithMany() .HasForeignKey("LastVersionId"); @@ -2223,6 +2298,8 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("LastVersion"); b.Navigation("Redistributable"); @@ -2490,6 +2567,31 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Navigation("User"); }); + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Versions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => { b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") @@ -2821,6 +2923,11 @@ namespace LANCommander.Server.Data.MySQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("SavePaths") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") .WithMany() .HasForeignKey("UpdatedById") @@ -2830,6 +2937,8 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("UpdatedBy"); }); @@ -2845,6 +2954,11 @@ namespace LANCommander.Server.Data.MySQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Scripts") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") .WithMany("Scripts") .HasForeignKey("RedistributableId") @@ -2869,6 +2983,8 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("Redistributable"); b.Navigation("Server"); @@ -3210,6 +3326,19 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Navigation("Scripts"); b.Navigation("Servers"); + + b.Navigation("Versions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Navigation("Actions"); + + b.Navigation("Archive"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); }); modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => diff --git a/LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.Designer.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.Designer.cs new file mode 100644 index 00000000..d5f30687 --- /dev/null +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.Designer.cs @@ -0,0 +1,3418 @@ +// +using System; +using LANCommander.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LANCommander.Server.Data.PostgreSQL.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20260627014314_AddGameVersions")] + partial class AddGameVersions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("CategoryGame", b => + { + b.Property("CategoriesId") + .HasColumnType("uuid"); + + b.Property("GamesId") + .HasColumnType("uuid"); + + b.HasKey("CategoriesId", "GamesId"); + + b.HasIndex("GamesId"); + + b.ToTable("CategoryGame"); + }); + + modelBuilder.Entity("ChatThreadUser", b => + { + b.Property("ChatThreadsId") + .HasColumnType("uuid"); + + b.Property("ParticipantsId") + .HasColumnType("uuid"); + + b.HasKey("ChatThreadsId", "ParticipantsId"); + + b.HasIndex("ParticipantsId"); + + b.ToTable("ChatThreadUser"); + }); + + modelBuilder.Entity("CollectionGame", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.HasKey("CollectionId", "GameId"); + + b.HasIndex("GameId"); + + b.ToTable("CollectionGame"); + }); + + modelBuilder.Entity("GameDeveloper", b => + { + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("DeveloperId") + .HasColumnType("uuid"); + + b.HasKey("GameId", "DeveloperId"); + + b.HasIndex("DeveloperId"); + + b.ToTable("GameDeveloper"); + }); + + modelBuilder.Entity("GameGenre", b => + { + b.Property("GamesId") + .HasColumnType("uuid"); + + b.Property("GenresId") + .HasColumnType("uuid"); + + b.HasKey("GamesId", "GenresId"); + + b.HasIndex("GenresId"); + + b.ToTable("GameGenre"); + }); + + modelBuilder.Entity("GamePlatform", b => + { + b.Property("GamesId") + .HasColumnType("uuid"); + + b.Property("PlatformsId") + .HasColumnType("uuid"); + + b.HasKey("GamesId", "PlatformsId"); + + b.HasIndex("PlatformsId"); + + b.ToTable("GamePlatform"); + }); + + modelBuilder.Entity("GamePublisher", b => + { + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("PublisherId") + .HasColumnType("uuid"); + + b.HasKey("GameId", "PublisherId"); + + b.HasIndex("PublisherId"); + + b.ToTable("GamePublisher"); + }); + + modelBuilder.Entity("GameRedistributable", b => + { + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("RedistributableId") + .HasColumnType("uuid"); + + b.Property("Options") + .HasColumnType("text"); + + b.HasKey("GameId", "RedistributableId"); + + b.HasIndex("RedistributableId"); + + b.ToTable("GameRedistributable"); + }); + + modelBuilder.Entity("GameTag", b => + { + b.Property("GamesId") + .HasColumnType("uuid"); + + b.Property("TagsId") + .HasColumnType("uuid"); + + b.HasKey("GamesId", "TagsId"); + + b.HasIndex("TagsId"); + + b.ToTable("GameTag"); + }); + + modelBuilder.Entity("GameTool", b => + { + b.Property("GamesId") + .HasColumnType("uuid"); + + b.Property("ToolsId") + .HasColumnType("uuid"); + + b.HasKey("GamesId", "ToolsId"); + + b.HasIndex("ToolsId"); + + b.ToTable("GameTool"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Action", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Arguments") + .HasColumnType("text"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("GameVersionId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OptionOverrides") + .HasColumnType("text"); + + b.Property("Path") + .HasColumnType("text"); + + b.Property("PrimaryAction") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("ToolId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDirectory") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Actions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Archive", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Changelog") + .HasColumnType("text"); + + b.Property("CompressedSize") + .HasColumnType("bigint"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("GameVersionId") + .HasColumnType("uuid"); + + b.Property("LastVersionId") + .HasColumnType("uuid"); + + b.Property("ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("RedistributableId") + .HasColumnType("uuid"); + + b.Property("StorageLocationId") + .HasColumnType("uuid"); + + b.Property("ToolId") + .HasColumnType("uuid"); + + b.Property("UncompressedSize") + .HasColumnType("bigint"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId") + .IsUnique(); + + b.HasIndex("LastVersionId"); + + b.HasIndex("RedistributableId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Archive"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ParentId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("ThreadId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ThreadId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ChatMessages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ChatThreads"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThreadReadStatus", b => + { + b.Property("ThreadId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LastReadMessageId") + .HasColumnType("uuid"); + + b.HasKey("ThreadId", "UserId"); + + b.HasIndex("LastReadMessageId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatThreadReadStatuses"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Collection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Collections"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Engines"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BaseGameId") + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DirectoryName") + .HasColumnType("text"); + + b.Property("EngineId") + .HasColumnType("uuid"); + + b.Property("KeyAllocationMethod") + .HasColumnType("integer"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("ReleasedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Singleplayer") + .HasColumnType("boolean"); + + b.Property("SortTitle") + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("ValidKeyRegex") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BaseGameId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("EngineId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Games"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameCustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameCustomField"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameExternalId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("ExternalId") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameExternalIds"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameSave", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("StorageLocationId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("GameSaves"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Changelog") + .HasColumnType("text"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameVersions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Genres"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Issue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("ResolvedById") + .HasColumnType("uuid"); + + b.Property("ResolvedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("ResolvedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Key", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllocationMethod") + .HasColumnType("integer"); + + b.Property("ClaimedByComputerName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ClaimedByIpv4Address") + .HasMaxLength(15) + .HasColumnType("character varying(15)"); + + b.Property("ClaimedByMacAddress") + .HasMaxLength(17) + .HasColumnType("character varying(17)"); + + b.Property("ClaimedByUserId") + .HasColumnType("uuid"); + + b.Property("ClaimedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("ClaimedByUserId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Keys"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Library", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Libraries"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Crc32") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("character varying(8)"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("FileId") + .HasColumnType("uuid"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("MimeType") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("SourceUrl") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("StorageLocationId") + .HasColumnType("uuid"); + + b.Property("ThumbnailId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("ThumbnailId") + .IsUnique(); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.MultiplayerMode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("MaxPlayers") + .HasColumnType("integer"); + + b.Property("MinPlayers") + .HasColumnType("integer"); + + b.Property("NetworkProtocol") + .HasColumnType("integer"); + + b.Property("Spectators") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("MultiplayerModes"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Contents") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("Route") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ToolId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ParentId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Pages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Platform", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Platforms"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.PlaySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("End") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("Start") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("PlaySessions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Rating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("Source") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Ratings"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("OptionSchema") + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Redistributables"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", 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") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("GameVersionId") + .HasColumnType("uuid"); + + b.Property("IsRegex") + .HasColumnType("boolean"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDirectory") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("SavePaths"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Script", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Contents") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("GameVersionId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("RedistributableId") + .HasColumnType("uuid"); + + b.Property("RequiresAdmin") + .HasColumnType("boolean"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.Property("ToolId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("RedistributableId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Arguments") + .IsRequired() + .HasColumnType("text"); + + b.Property("Autostart") + .HasColumnType("boolean"); + + b.Property("AutostartDelay") + .HasColumnType("integer"); + + b.Property("AutostartMethod") + .HasColumnType("integer"); + + b.Property("ContainerId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("DockerHostId") + .HasColumnType("uuid"); + + b.Property("Engine") + .HasColumnType("integer"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("Host") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OnStartScriptPath") + .IsRequired() + .HasColumnType("text"); + + b.Property("OnStopScriptPath") + .IsRequired() + .HasColumnType("text"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Port") + .HasColumnType("integer"); + + b.Property("ProcessTerminationMethod") + .HasColumnType("integer"); + + b.Property("RemoteHostId") + .HasColumnType("uuid"); + + b.Property("RemoteServerId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UseShellExecute") + .HasColumnType("boolean"); + + b.Property("WorkingDirectory") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Servers"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerConsole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Host") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Port") + .HasColumnType("integer"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ServerConsoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerHttpPath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("LocalPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ServerHttpPath"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Default") + .HasColumnType("boolean"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("StorageLocations"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Tools"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("Alias") + .HasColumnType("text"); + + b.Property("Approved") + .HasColumnType("boolean"); + + b.Property("ApprovedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + 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("RefreshToken") + .HasColumnType("text"); + + b.Property("RefreshTokenExpiration") + .HasColumnType("timestamp with time zone"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", 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") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("UserCustomField"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("LibraryGame", b => + { + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("LibraryId") + .HasColumnType("uuid"); + + b.HasKey("GameId", "LibraryId"); + + b.HasIndex("LibraryId"); + + b.ToTable("LibraryGame"); + }); + + modelBuilder.Entity("PageGame", b => + { + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("PageId") + .HasColumnType("uuid"); + + b.HasKey("GameId", "PageId"); + + b.HasIndex("PageId"); + + b.ToTable("PageGame"); + }); + + modelBuilder.Entity("PageRedistributable", b => + { + b.Property("PageId") + .HasColumnType("uuid"); + + b.Property("RedistributableId") + .HasColumnType("uuid"); + + b.HasKey("PageId", "RedistributableId"); + + b.HasIndex("RedistributableId"); + + b.ToTable("PageRedistributable"); + }); + + modelBuilder.Entity("PageServer", b => + { + b.Property("PageId") + .HasColumnType("uuid"); + + b.Property("ServerId") + .HasColumnType("uuid"); + + b.HasKey("PageId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("PageServer"); + }); + + modelBuilder.Entity("RoleCollection", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("CollectionId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleCollection"); + }); + + modelBuilder.Entity("CategoryGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Category", null) + .WithMany() + .HasForeignKey("CategoriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ChatThreadUser", b => + { + b.HasOne("LANCommander.Server.Data.Models.ChatThread", null) + .WithMany() + .HasForeignKey("ChatThreadsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("ParticipantsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("CollectionGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Collection", null) + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameDeveloper", b => + { + b.HasOne("LANCommander.Server.Data.Models.Company", null) + .WithMany() + .HasForeignKey("DeveloperId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameGenre", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Genre", null) + .WithMany() + .HasForeignKey("GenresId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GamePlatform", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Platform", null) + .WithMany() + .HasForeignKey("PlatformsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GamePublisher", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Company", null) + .WithMany() + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameRedistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", null) + .WithMany() + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameTag", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tag", null) + .WithMany() + .HasForeignKey("TagsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameTool", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tool", null) + .WithMany() + .HasForeignKey("ToolsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Action", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Actions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Actions") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("Actions") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Actions") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("Server"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Archive", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Archives") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithOne("Archive") + .HasForeignKey("LANCommander.Server.Data.Models.Archive", "GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Archive", "LastVersion") + .WithMany() + .HasForeignKey("LastVersionId"); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") + .WithMany("Archives") + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("Archives") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Archives") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("LastVersion"); + + b.Navigation("Redistributable"); + + b.Navigation("StorageLocation"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Category", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Parent"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatMessage", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.ChatThread", "Thread") + .WithMany("Messages") + .HasForeignKey("ThreadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Thread"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThreadReadStatus", b => + { + b.HasOne("LANCommander.Server.Data.Models.ChatMessage", "LastReadMessage") + .WithMany() + .HasForeignKey("LastReadMessageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.ChatThread", "Thread") + .WithMany() + .HasForeignKey("ThreadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LastReadMessage"); + + b.Navigation("Thread"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Collection", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Company", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", "BaseGame") + .WithMany("DependentGames") + .HasForeignKey("BaseGameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Engine", "Engine") + .WithMany("Games") + .HasForeignKey("EngineId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("BaseGame"); + + b.Navigation("CreatedBy"); + + b.Navigation("Engine"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameCustomField", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("CustomFields") + .HasForeignKey("GameId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameExternalId", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("ExternalIds") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameSave", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("GameSaves") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("GameSaves") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("GameSaves") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("StorageLocation"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Versions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Issue", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Issues") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "ResolvedBy") + .WithMany() + .HasForeignKey("ResolvedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("ResolvedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Key", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "ClaimedByUser") + .WithMany() + .HasForeignKey("ClaimedByUserId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Keys") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("ClaimedByUser"); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Library", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithOne("Library") + .HasForeignKey("LANCommander.Server.Data.Models.Library", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Media") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("Media") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Media", "Thumbnail") + .WithOne("Parent") + .HasForeignKey("LANCommander.Server.Data.Models.Media", "ThumbnailId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("Media") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("StorageLocation"); + + b.Navigation("Thumbnail"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.MultiplayerMode", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("MultiplayerModes") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Page", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", null) + .WithMany("Pages") + .HasForeignKey("ToolId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Parent"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Platform", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.PlaySession", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("PlaySessions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("PlaySessions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Rating", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Ratings") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("SavePaths") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("SavePaths") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Script", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Scripts") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Scripts") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") + .WithMany("Scripts") + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("Scripts") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Scripts") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("Redistributable"); + + b.Navigation("Server"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Servers") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerConsole", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("ServerConsoles") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Server"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerHttpPath", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("HttpPaths") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Server"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tag", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("CustomFields") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("UserRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LibraryGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Library", null) + .WithMany() + .HasForeignKey("LibraryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageRedistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", null) + .WithMany() + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageServer", b => + { + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Server", null) + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleCollection", b => + { + b.HasOne("LANCommander.Server.Data.Models.Collection", null) + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.Navigation("Games"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.Navigation("Actions"); + + b.Navigation("Archives"); + + b.Navigation("CustomFields"); + + b.Navigation("DependentGames"); + + b.Navigation("ExternalIds"); + + b.Navigation("GameSaves"); + + b.Navigation("Issues"); + + b.Navigation("Keys"); + + b.Navigation("Media"); + + b.Navigation("MultiplayerModes"); + + b.Navigation("PlaySessions"); + + b.Navigation("Ratings"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); + + b.Navigation("Servers"); + + b.Navigation("Versions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Navigation("Actions"); + + b.Navigation("Archive"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.Navigation("Archives"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.Navigation("Actions"); + + b.Navigation("HttpPaths"); + + b.Navigation("Scripts"); + + b.Navigation("ServerConsoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.Navigation("Archives"); + + b.Navigation("GameSaves"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.Navigation("Actions"); + + b.Navigation("Archives"); + + b.Navigation("Pages"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.Navigation("CustomFields"); + + b.Navigation("GameSaves"); + + b.Navigation("Library") + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("PlaySessions"); + + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.cs new file mode 100644 index 00000000..6ff5fcf5 --- /dev/null +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/20260627014314_AddGameVersions.cs @@ -0,0 +1,195 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Server.Data.PostgreSQL.Migrations +{ + /// + public partial class AddGameVersions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Scripts", + type: "uuid", + nullable: true); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "SavePaths", + type: "uuid", + nullable: true); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Archive", + type: "uuid", + nullable: true); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Actions", + type: "uuid", + nullable: true); + + migrationBuilder.CreateTable( + name: "GameVersions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Version = table.Column(type: "text", nullable: false), + Changelog = table.Column(type: "text", nullable: true), + SortOrder = table.Column(type: "integer", nullable: false), + GameId = table.Column(type: "uuid", nullable: false), + CreatedOn = table.Column(type: "timestamp with time zone", nullable: false), + CreatedById = table.Column(type: "uuid", nullable: true), + UpdatedOn = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedById = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_GameVersions", x => x.Id); + table.ForeignKey( + name: "FK_GameVersions_Games_GameId", + column: x => x.GameId, + principalTable: "Games", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_GameVersions_Users_CreatedById", + column: x => x.CreatedById, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + table.ForeignKey( + name: "FK_GameVersions_Users_UpdatedById", + column: x => x.UpdatedById, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + }); + + migrationBuilder.CreateIndex( + name: "IX_Scripts_GameVersionId", + table: "Scripts", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_SavePaths_GameVersionId", + table: "SavePaths", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_Archive_GameVersionId", + table: "Archive", + column: "GameVersionId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Actions_GameVersionId", + table: "Actions", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_CreatedById", + table: "GameVersions", + column: "CreatedById"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_GameId", + table: "GameVersions", + column: "GameId"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_UpdatedById", + table: "GameVersions", + column: "UpdatedById"); + + migrationBuilder.AddForeignKey( + name: "FK_Actions_GameVersions_GameVersionId", + table: "Actions", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Archive_GameVersions_GameVersionId", + table: "Archive", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_SavePaths_GameVersions_GameVersionId", + table: "SavePaths", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Scripts_GameVersions_GameVersionId", + table: "Scripts", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Actions_GameVersions_GameVersionId", + table: "Actions"); + + migrationBuilder.DropForeignKey( + name: "FK_Archive_GameVersions_GameVersionId", + table: "Archive"); + + migrationBuilder.DropForeignKey( + name: "FK_SavePaths_GameVersions_GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropForeignKey( + name: "FK_Scripts_GameVersions_GameVersionId", + table: "Scripts"); + + migrationBuilder.DropTable( + name: "GameVersions"); + + migrationBuilder.DropIndex( + name: "IX_Scripts_GameVersionId", + table: "Scripts"); + + migrationBuilder.DropIndex( + name: "IX_SavePaths_GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropIndex( + name: "IX_Archive_GameVersionId", + table: "Archive"); + + migrationBuilder.DropIndex( + name: "IX_Actions_GameVersionId", + table: "Actions"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Scripts"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Archive"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Actions"); + } + } +} diff --git a/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs index 648ce24e..13742f9d 100644 --- a/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs @@ -193,6 +193,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("GameId") .HasColumnType("uuid"); + b.Property("GameVersionId") + .HasColumnType("uuid"); + b.Property("Name") .IsRequired() .HasColumnType("text"); @@ -230,6 +233,8 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("ServerId"); b.HasIndex("ToolId"); @@ -260,6 +265,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("GameId") .HasColumnType("uuid"); + b.Property("GameVersionId") + .HasColumnType("uuid"); + b.Property("LastVersionId") .HasColumnType("uuid"); @@ -295,6 +303,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId") + .IsUnique(); + b.HasIndex("LastVersionId"); b.HasIndex("RedistributableId"); @@ -722,6 +733,48 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.ToTable("GameSaves"); }); + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Changelog") + .HasColumnType("text"); + + b.Property("CreatedById") + .HasColumnType("uuid"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("GameId") + .HasColumnType("uuid"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedById") + .HasColumnType("uuid"); + + b.Property("UpdatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameVersions"); + }); + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => { b.Property("Id") @@ -1308,6 +1361,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("GameId") .HasColumnType("uuid"); + b.Property("GameVersionId") + .HasColumnType("uuid"); + b.Property("IsRegex") .HasColumnType("boolean"); @@ -1333,6 +1389,8 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("UpdatedById"); b.ToTable("SavePaths"); @@ -1360,6 +1418,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("GameId") .HasColumnType("uuid"); + b.Property("GameVersionId") + .HasColumnType("uuid"); + b.Property("Name") .IsRequired() .HasColumnType("text"); @@ -1391,6 +1452,8 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("RedistributableId"); b.HasIndex("ServerId"); @@ -2156,6 +2219,11 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Actions") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") .WithMany("Actions") .HasForeignKey("ServerId") @@ -2175,6 +2243,8 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("Server"); b.Navigation("Tool"); @@ -2194,6 +2264,11 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithOne("Archive") + .HasForeignKey("LANCommander.Server.Data.Models.Archive", "GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Archive", "LastVersion") .WithMany() .HasForeignKey("LastVersionId"); @@ -2223,6 +2298,8 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("LastVersion"); b.Navigation("Redistributable"); @@ -2490,6 +2567,31 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Navigation("User"); }); + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Versions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => { b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") @@ -2821,6 +2923,11 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("SavePaths") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") .WithMany() .HasForeignKey("UpdatedById") @@ -2830,6 +2937,8 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("UpdatedBy"); }); @@ -2845,6 +2954,11 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Scripts") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") .WithMany("Scripts") .HasForeignKey("RedistributableId") @@ -2869,6 +2983,8 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("Redistributable"); b.Navigation("Server"); @@ -3210,6 +3326,19 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Navigation("Scripts"); b.Navigation("Servers"); + + b.Navigation("Versions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Navigation("Actions"); + + b.Navigation("Archive"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); }); modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => diff --git a/LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.Designer.cs b/LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.Designer.cs new file mode 100644 index 00000000..cf2217e1 --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.Designer.cs @@ -0,0 +1,3409 @@ +// +using System; +using LANCommander.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace LANCommander.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20260627014005_AddGameVersions")] + partial class AddGameVersions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.9"); + + modelBuilder.Entity("CategoryGame", b => + { + b.Property("CategoriesId") + .HasColumnType("TEXT"); + + b.Property("GamesId") + .HasColumnType("TEXT"); + + b.HasKey("CategoriesId", "GamesId"); + + b.HasIndex("GamesId"); + + b.ToTable("CategoryGame"); + }); + + modelBuilder.Entity("ChatThreadUser", b => + { + b.Property("ChatThreadsId") + .HasColumnType("TEXT"); + + b.Property("ParticipantsId") + .HasColumnType("TEXT"); + + b.HasKey("ChatThreadsId", "ParticipantsId"); + + b.HasIndex("ParticipantsId"); + + b.ToTable("ChatThreadUser"); + }); + + modelBuilder.Entity("CollectionGame", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.HasKey("CollectionId", "GameId"); + + b.HasIndex("GameId"); + + b.ToTable("CollectionGame"); + }); + + modelBuilder.Entity("GameDeveloper", b => + { + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("DeveloperId") + .HasColumnType("TEXT"); + + b.HasKey("GameId", "DeveloperId"); + + b.HasIndex("DeveloperId"); + + b.ToTable("GameDeveloper"); + }); + + modelBuilder.Entity("GameGenre", b => + { + b.Property("GamesId") + .HasColumnType("TEXT"); + + b.Property("GenresId") + .HasColumnType("TEXT"); + + b.HasKey("GamesId", "GenresId"); + + b.HasIndex("GenresId"); + + b.ToTable("GameGenre"); + }); + + modelBuilder.Entity("GamePlatform", b => + { + b.Property("GamesId") + .HasColumnType("TEXT"); + + b.Property("PlatformsId") + .HasColumnType("TEXT"); + + b.HasKey("GamesId", "PlatformsId"); + + b.HasIndex("PlatformsId"); + + b.ToTable("GamePlatform"); + }); + + modelBuilder.Entity("GamePublisher", b => + { + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("PublisherId") + .HasColumnType("TEXT"); + + b.HasKey("GameId", "PublisherId"); + + b.HasIndex("PublisherId"); + + b.ToTable("GamePublisher"); + }); + + modelBuilder.Entity("GameRedistributable", b => + { + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("RedistributableId") + .HasColumnType("TEXT"); + + b.Property("Options") + .HasColumnType("TEXT"); + + b.HasKey("GameId", "RedistributableId"); + + b.HasIndex("RedistributableId"); + + b.ToTable("GameRedistributable"); + }); + + modelBuilder.Entity("GameTag", b => + { + b.Property("GamesId") + .HasColumnType("TEXT"); + + b.Property("TagsId") + .HasColumnType("TEXT"); + + b.HasKey("GamesId", "TagsId"); + + b.HasIndex("TagsId"); + + b.ToTable("GameTag"); + }); + + modelBuilder.Entity("GameTool", b => + { + b.Property("GamesId") + .HasColumnType("TEXT"); + + b.Property("ToolsId") + .HasColumnType("TEXT"); + + b.HasKey("GamesId", "ToolsId"); + + b.HasIndex("ToolsId"); + + b.ToTable("GameTool"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Action", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Arguments") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("GameVersionId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OptionOverrides") + .HasColumnType("TEXT"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("PrimaryAction") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("ToolId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("WorkingDirectory") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Actions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Archive", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Changelog") + .HasColumnType("TEXT"); + + b.Property("CompressedSize") + .HasColumnType("INTEGER"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("GameVersionId") + .HasColumnType("TEXT"); + + b.Property("LastVersionId") + .HasColumnType("TEXT"); + + b.Property("ObjectKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RedistributableId") + .HasColumnType("TEXT"); + + b.Property("StorageLocationId") + .HasColumnType("TEXT"); + + b.Property("ToolId") + .HasColumnType("TEXT"); + + b.Property("UncompressedSize") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("Version") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId") + .IsUnique(); + + b.HasIndex("LastVersionId"); + + b.HasIndex("RedistributableId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Archive"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ParentId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("ThreadId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ThreadId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ChatMessages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ChatThreads"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThreadReadStatus", b => + { + b.Property("ThreadId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LastReadMessageId") + .HasColumnType("TEXT"); + + b.HasKey("ThreadId", "UserId"); + + b.HasIndex("LastReadMessageId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatThreadReadStatuses"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Collection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Collections"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Engines"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("BaseGameId") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("DirectoryName") + .HasColumnType("TEXT"); + + b.Property("EngineId") + .HasColumnType("TEXT"); + + b.Property("KeyAllocationMethod") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("ReleasedOn") + .HasColumnType("TEXT"); + + b.Property("Singleplayer") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("ValidKeyRegex") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("BaseGameId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("EngineId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Games"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameCustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameCustomField"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameExternalId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameExternalIds"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameSave", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("Size") + .HasColumnType("INTEGER"); + + b.Property("StorageLocationId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("GameSaves"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Changelog") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("Version") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameVersions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Genres"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Issue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("ResolvedById") + .HasColumnType("TEXT"); + + b.Property("ResolvedOn") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("ResolvedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Key", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AllocationMethod") + .HasColumnType("INTEGER"); + + b.Property("ClaimedByComputerName") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("ClaimedByIpv4Address") + .HasMaxLength(15) + .HasColumnType("TEXT"); + + b.Property("ClaimedByMacAddress") + .HasMaxLength(17) + .HasColumnType("TEXT"); + + b.Property("ClaimedByUserId") + .HasColumnType("TEXT"); + + b.Property("ClaimedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ClaimedByUserId"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Keys"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Library", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Libraries"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Crc32") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("FileId") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("MimeType") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("SourceUrl") + .HasMaxLength(2048) + .HasColumnType("TEXT"); + + b.Property("StorageLocationId") + .HasColumnType("TEXT"); + + b.Property("ThumbnailId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("StorageLocationId"); + + b.HasIndex("ThumbnailId") + .IsUnique(); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.MultiplayerMode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("MaxPlayers") + .HasColumnType("INTEGER"); + + b.Property("MinPlayers") + .HasColumnType("INTEGER"); + + b.Property("NetworkProtocol") + .HasColumnType("INTEGER"); + + b.Property("Spectators") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("MultiplayerModes"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Contents") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("Route") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("TEXT"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("ToolId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ParentId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Pages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Platform", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Platforms"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.PlaySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("End") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("Start") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("PlaySessions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Rating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("REAL"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Ratings"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OptionSchema") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Redistributables"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("GameVersionId") + .HasColumnType("TEXT"); + + b.Property("IsRegex") + .HasColumnType("INTEGER"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("WorkingDirectory") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("SavePaths"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Script", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Contents") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("GameVersionId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RedistributableId") + .HasColumnType("TEXT"); + + b.Property("RequiresAdmin") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("ToolId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("GameVersionId"); + + b.HasIndex("RedistributableId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ToolId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Arguments") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Autostart") + .HasColumnType("INTEGER"); + + b.Property("AutostartDelay") + .HasColumnType("INTEGER"); + + b.Property("AutostartMethod") + .HasColumnType("INTEGER"); + + b.Property("ContainerId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DockerHostId") + .HasColumnType("TEXT"); + + b.Property("Engine") + .HasColumnType("INTEGER"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("Host") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OnStartScriptPath") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OnStopScriptPath") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.Property("ProcessTerminationMethod") + .HasColumnType("INTEGER"); + + b.Property("RemoteHostId") + .HasColumnType("TEXT"); + + b.Property("RemoteServerId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UseShellExecute") + .HasColumnType("INTEGER"); + + b.Property("WorkingDirectory") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Servers"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerConsole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Host") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ServerConsoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerHttpPath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("LocalPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("ServerHttpPath"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Default") + .HasColumnType("INTEGER"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("StorageLocations"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Tools"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ApprovedOn") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + 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("RefreshToken") + .HasColumnType("TEXT"); + + b.Property("RefreshTokenExpiration") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.HasIndex("UserId"); + + b.ToTable("UserCustomField"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("LibraryGame", b => + { + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("LibraryId") + .HasColumnType("TEXT"); + + b.HasKey("GameId", "LibraryId"); + + b.HasIndex("LibraryId"); + + b.ToTable("LibraryGame"); + }); + + modelBuilder.Entity("PageGame", b => + { + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("PageId") + .HasColumnType("TEXT"); + + b.HasKey("GameId", "PageId"); + + b.HasIndex("PageId"); + + b.ToTable("PageGame"); + }); + + modelBuilder.Entity("PageRedistributable", b => + { + b.Property("PageId") + .HasColumnType("TEXT"); + + b.Property("RedistributableId") + .HasColumnType("TEXT"); + + b.HasKey("PageId", "RedistributableId"); + + b.HasIndex("RedistributableId"); + + b.ToTable("PageRedistributable"); + }); + + modelBuilder.Entity("PageServer", b => + { + b.Property("PageId") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.HasKey("PageId", "ServerId"); + + b.HasIndex("ServerId"); + + b.ToTable("PageServer"); + }); + + modelBuilder.Entity("RoleCollection", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("CollectionId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleCollection"); + }); + + modelBuilder.Entity("CategoryGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Category", null) + .WithMany() + .HasForeignKey("CategoriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ChatThreadUser", b => + { + b.HasOne("LANCommander.Server.Data.Models.ChatThread", null) + .WithMany() + .HasForeignKey("ChatThreadsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("ParticipantsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("CollectionGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Collection", null) + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameDeveloper", b => + { + b.HasOne("LANCommander.Server.Data.Models.Company", null) + .WithMany() + .HasForeignKey("DeveloperId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameGenre", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Genre", null) + .WithMany() + .HasForeignKey("GenresId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GamePlatform", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Platform", null) + .WithMany() + .HasForeignKey("PlatformsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GamePublisher", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Company", null) + .WithMany() + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameRedistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", null) + .WithMany() + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameTag", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tag", null) + .WithMany() + .HasForeignKey("TagsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("GameTool", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GamesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tool", null) + .WithMany() + .HasForeignKey("ToolsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Action", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Actions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Actions") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("Actions") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Actions") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("Server"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Archive", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Archives") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithOne("Archive") + .HasForeignKey("LANCommander.Server.Data.Models.Archive", "GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Archive", "LastVersion") + .WithMany() + .HasForeignKey("LastVersionId"); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") + .WithMany("Archives") + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("Archives") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Archives") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("LastVersion"); + + b.Navigation("Redistributable"); + + b.Navigation("StorageLocation"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Category", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Parent"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatMessage", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.ChatThread", "Thread") + .WithMany("Messages") + .HasForeignKey("ThreadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Thread"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThreadReadStatus", b => + { + b.HasOne("LANCommander.Server.Data.Models.ChatMessage", "LastReadMessage") + .WithMany() + .HasForeignKey("LastReadMessageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.ChatThread", "Thread") + .WithMany() + .HasForeignKey("ThreadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LastReadMessage"); + + b.Navigation("Thread"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Collection", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Company", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", "BaseGame") + .WithMany("DependentGames") + .HasForeignKey("BaseGameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Engine", "Engine") + .WithMany("Games") + .HasForeignKey("EngineId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("BaseGame"); + + b.Navigation("CreatedBy"); + + b.Navigation("Engine"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameCustomField", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("CustomFields") + .HasForeignKey("GameId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameExternalId", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("ExternalIds") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameSave", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("GameSaves") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("GameSaves") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("GameSaves") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("StorageLocation"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Versions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Issue", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Issues") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "ResolvedBy") + .WithMany() + .HasForeignKey("ResolvedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("ResolvedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Key", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "ClaimedByUser") + .WithMany() + .HasForeignKey("ClaimedByUserId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Keys") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("ClaimedByUser"); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Library", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithOne("Library") + .HasForeignKey("LANCommander.Server.Data.Models.Library", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Media") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.StorageLocation", "StorageLocation") + .WithMany("Media") + .HasForeignKey("StorageLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Media", "Thumbnail") + .WithOne("Parent") + .HasForeignKey("LANCommander.Server.Data.Models.Media", "ThumbnailId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("Media") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("StorageLocation"); + + b.Navigation("Thumbnail"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.MultiplayerMode", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("MultiplayerModes") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Page", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", null) + .WithMany("Pages") + .HasForeignKey("ToolId"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Parent"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Platform", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.PlaySession", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("PlaySessions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("PlaySessions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Rating", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Ratings") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("SavePaths") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("SavePaths") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Script", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Scripts") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Scripts") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") + .WithMany("Scripts") + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("Scripts") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.Tool", "Tool") + .WithMany("Scripts") + .HasForeignKey("ToolId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("GameVersion"); + + b.Navigation("Redistributable"); + + b.Navigation("Server"); + + b.Navigation("Tool"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Servers") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerConsole", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("ServerConsoles") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Server"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ServerHttpPath", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") + .WithMany("HttpPaths") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Server"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById"); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById"); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tag", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("CustomFields") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("UpdatedBy"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "User") + .WithMany("UserRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LibraryGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Library", null) + .WithMany() + .HasForeignKey("LibraryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageGame", b => + { + b.HasOne("LANCommander.Server.Data.Models.Game", null) + .WithMany() + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageRedistributable", b => + { + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Redistributable", null) + .WithMany() + .HasForeignKey("RedistributableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("PageServer", b => + { + b.HasOne("LANCommander.Server.Data.Models.Page", null) + .WithMany() + .HasForeignKey("PageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Server", null) + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleCollection", b => + { + b.HasOne("LANCommander.Server.Data.Models.Collection", null) + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.ChatThread", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Engine", b => + { + b.Navigation("Games"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Game", b => + { + b.Navigation("Actions"); + + b.Navigation("Archives"); + + b.Navigation("CustomFields"); + + b.Navigation("DependentGames"); + + b.Navigation("ExternalIds"); + + b.Navigation("GameSaves"); + + b.Navigation("Issues"); + + b.Navigation("Keys"); + + b.Navigation("Media"); + + b.Navigation("MultiplayerModes"); + + b.Navigation("PlaySessions"); + + b.Navigation("Ratings"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); + + b.Navigation("Servers"); + + b.Navigation("Versions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Navigation("Actions"); + + b.Navigation("Archive"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => + { + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Page", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Redistributable", b => + { + b.Navigation("Archives"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b => + { + b.Navigation("Actions"); + + b.Navigation("HttpPaths"); + + b.Navigation("Scripts"); + + b.Navigation("ServerConsoles"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.StorageLocation", b => + { + b.Navigation("Archives"); + + b.Navigation("GameSaves"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Tool", b => + { + b.Navigation("Actions"); + + b.Navigation("Archives"); + + b.Navigation("Pages"); + + b.Navigation("Scripts"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.User", b => + { + b.Navigation("CustomFields"); + + b.Navigation("GameSaves"); + + b.Navigation("Library") + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("PlaySessions"); + + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.cs b/LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.cs new file mode 100644 index 00000000..e85decb2 --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20260627014005_AddGameVersions.cs @@ -0,0 +1,195 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Migrations +{ + /// + public partial class AddGameVersions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Scripts", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "SavePaths", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Archive", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "GameVersionId", + table: "Actions", + type: "TEXT", + nullable: true); + + migrationBuilder.CreateTable( + name: "GameVersions", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Version = table.Column(type: "TEXT", nullable: false), + Changelog = table.Column(type: "TEXT", nullable: true), + SortOrder = table.Column(type: "INTEGER", nullable: false), + GameId = table.Column(type: "TEXT", nullable: false), + CreatedOn = table.Column(type: "TEXT", nullable: false), + CreatedById = table.Column(type: "TEXT", nullable: true), + UpdatedOn = table.Column(type: "TEXT", nullable: false), + UpdatedById = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_GameVersions", x => x.Id); + table.ForeignKey( + name: "FK_GameVersions_Games_GameId", + column: x => x.GameId, + principalTable: "Games", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_GameVersions_Users_CreatedById", + column: x => x.CreatedById, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + table.ForeignKey( + name: "FK_GameVersions_Users_UpdatedById", + column: x => x.UpdatedById, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + }); + + migrationBuilder.CreateIndex( + name: "IX_Scripts_GameVersionId", + table: "Scripts", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_SavePaths_GameVersionId", + table: "SavePaths", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_Archive_GameVersionId", + table: "Archive", + column: "GameVersionId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Actions_GameVersionId", + table: "Actions", + column: "GameVersionId"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_CreatedById", + table: "GameVersions", + column: "CreatedById"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_GameId", + table: "GameVersions", + column: "GameId"); + + migrationBuilder.CreateIndex( + name: "IX_GameVersions_UpdatedById", + table: "GameVersions", + column: "UpdatedById"); + + migrationBuilder.AddForeignKey( + name: "FK_Actions_GameVersions_GameVersionId", + table: "Actions", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Archive_GameVersions_GameVersionId", + table: "Archive", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_SavePaths_GameVersions_GameVersionId", + table: "SavePaths", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Scripts_GameVersions_GameVersionId", + table: "Scripts", + column: "GameVersionId", + principalTable: "GameVersions", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Actions_GameVersions_GameVersionId", + table: "Actions"); + + migrationBuilder.DropForeignKey( + name: "FK_Archive_GameVersions_GameVersionId", + table: "Archive"); + + migrationBuilder.DropForeignKey( + name: "FK_SavePaths_GameVersions_GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropForeignKey( + name: "FK_Scripts_GameVersions_GameVersionId", + table: "Scripts"); + + migrationBuilder.DropTable( + name: "GameVersions"); + + migrationBuilder.DropIndex( + name: "IX_Scripts_GameVersionId", + table: "Scripts"); + + migrationBuilder.DropIndex( + name: "IX_SavePaths_GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropIndex( + name: "IX_Archive_GameVersionId", + table: "Archive"); + + migrationBuilder.DropIndex( + name: "IX_Actions_GameVersionId", + table: "Actions"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Scripts"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "SavePaths"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Archive"); + + migrationBuilder.DropColumn( + name: "GameVersionId", + table: "Actions"); + } + } +} diff --git a/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs b/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs index d9c7e282..ac58c3d6 100644 --- a/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs +++ b/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs @@ -188,6 +188,9 @@ namespace LANCommander.Migrations b.Property("GameId") .HasColumnType("TEXT"); + b.Property("GameVersionId") + .HasColumnType("TEXT"); + b.Property("Name") .IsRequired() .HasColumnType("TEXT"); @@ -225,6 +228,8 @@ namespace LANCommander.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("ServerId"); b.HasIndex("ToolId"); @@ -255,6 +260,9 @@ namespace LANCommander.Migrations b.Property("GameId") .HasColumnType("TEXT"); + b.Property("GameVersionId") + .HasColumnType("TEXT"); + b.Property("LastVersionId") .HasColumnType("TEXT"); @@ -290,6 +298,9 @@ namespace LANCommander.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId") + .IsUnique(); + b.HasIndex("LastVersionId"); b.HasIndex("RedistributableId"); @@ -717,6 +728,48 @@ namespace LANCommander.Migrations b.ToTable("GameSaves"); }); + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Changelog") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("Version") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("GameId"); + + b.HasIndex("UpdatedById"); + + b.ToTable("GameVersions"); + }); + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => { b.Property("Id") @@ -1301,6 +1354,9 @@ namespace LANCommander.Migrations b.Property("GameId") .HasColumnType("TEXT"); + b.Property("GameVersionId") + .HasColumnType("TEXT"); + b.Property("IsRegex") .HasColumnType("INTEGER"); @@ -1326,6 +1382,8 @@ namespace LANCommander.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("UpdatedById"); b.ToTable("SavePaths"); @@ -1353,6 +1411,9 @@ namespace LANCommander.Migrations b.Property("GameId") .HasColumnType("TEXT"); + b.Property("GameVersionId") + .HasColumnType("TEXT"); + b.Property("Name") .IsRequired() .HasColumnType("TEXT"); @@ -1384,6 +1445,8 @@ namespace LANCommander.Migrations b.HasIndex("GameId"); + b.HasIndex("GameVersionId"); + b.HasIndex("RedistributableId"); b.HasIndex("ServerId"); @@ -2147,6 +2210,11 @@ namespace LANCommander.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Actions") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Server", "Server") .WithMany("Actions") .HasForeignKey("ServerId") @@ -2166,6 +2234,8 @@ namespace LANCommander.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("Server"); b.Navigation("Tool"); @@ -2185,6 +2255,11 @@ namespace LANCommander.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithOne("Archive") + .HasForeignKey("LANCommander.Server.Data.Models.Archive", "GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Archive", "LastVersion") .WithMany() .HasForeignKey("LastVersionId"); @@ -2214,6 +2289,8 @@ namespace LANCommander.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("LastVersion"); b.Navigation("Redistributable"); @@ -2481,6 +2558,31 @@ namespace LANCommander.Migrations b.Navigation("User"); }); + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("LANCommander.Server.Data.Models.Game", "Game") + .WithMany("Versions") + .HasForeignKey("GameId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("UpdatedBy"); + }); + modelBuilder.Entity("LANCommander.Server.Data.Models.Genre", b => { b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy") @@ -2812,6 +2914,11 @@ namespace LANCommander.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("SavePaths") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.User", "UpdatedBy") .WithMany() .HasForeignKey("UpdatedById") @@ -2821,6 +2928,8 @@ namespace LANCommander.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("UpdatedBy"); }); @@ -2836,6 +2945,11 @@ namespace LANCommander.Migrations .HasForeignKey("GameId") .OnDelete(DeleteBehavior.Cascade); + b.HasOne("LANCommander.Server.Data.Models.GameVersion", "GameVersion") + .WithMany("Scripts") + .HasForeignKey("GameVersionId") + .OnDelete(DeleteBehavior.ClientCascade); + b.HasOne("LANCommander.Server.Data.Models.Redistributable", "Redistributable") .WithMany("Scripts") .HasForeignKey("RedistributableId") @@ -2860,6 +2974,8 @@ namespace LANCommander.Migrations b.Navigation("Game"); + b.Navigation("GameVersion"); + b.Navigation("Redistributable"); b.Navigation("Server"); @@ -3201,6 +3317,19 @@ namespace LANCommander.Migrations b.Navigation("Scripts"); b.Navigation("Servers"); + + b.Navigation("Versions"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.GameVersion", b => + { + b.Navigation("Actions"); + + b.Navigation("Archive"); + + b.Navigation("SavePaths"); + + b.Navigation("Scripts"); }); modelBuilder.Entity("LANCommander.Server.Data.Models.Media", b => diff --git a/LANCommander.Server.Data/DatabaseContext.cs b/LANCommander.Server.Data/DatabaseContext.cs index 13632fdb..ebf49ec7 100644 --- a/LANCommander.Server.Data/DatabaseContext.cs +++ b/LANCommander.Server.Data/DatabaseContext.cs @@ -75,6 +75,7 @@ namespace LANCommander.Server.Data builder.ConfigureBaseRelationships(); builder.ConfigureBaseRelationships(); builder.ConfigureBaseRelationships(); + builder.ConfigureBaseRelationships(); builder.ConfigureBaseRelationships(); builder.ConfigureBaseRelationships(); builder.ConfigureBaseRelationships(); @@ -264,6 +265,43 @@ namespace LANCommander.Server.Data .OnDelete(DeleteBehavior.Cascade); #endregion + #region Game Version Relationships + builder.Entity() + .HasMany(g => g.Versions) + .WithOne(v => v.Game) + .IsRequired(true) + .OnDelete(DeleteBehavior.Cascade); + + // GameVersion owns the version-scoped config. The same Archive/Script/Action/SavePath + // rows are also referenced by the Game (dual-write during the transition), which already + // declares a cascade path. A second cascade path here would be rejected by MySQL + // (multiple cascade paths), so the GameVersion side uses ClientCascade instead. + builder.Entity() + .HasOne(v => v.Archive) + .WithOne(a => a.GameVersion) + .HasForeignKey(a => a.GameVersionId) + .IsRequired(false) + .OnDelete(DeleteBehavior.ClientCascade); + + builder.Entity() + .HasMany(v => v.Scripts) + .WithOne(s => s.GameVersion) + .IsRequired(false) + .OnDelete(DeleteBehavior.ClientCascade); + + builder.Entity() + .HasMany(v => v.Actions) + .WithOne(a => a.GameVersion) + .IsRequired(false) + .OnDelete(DeleteBehavior.ClientCascade); + + builder.Entity() + .HasMany(v => v.SavePaths) + .WithOne(p => p.GameVersion) + .IsRequired(false) + .OnDelete(DeleteBehavior.ClientCascade); + #endregion + #region Media Relationships builder.Entity() .HasOne(m => m.Thumbnail) @@ -528,6 +566,8 @@ namespace LANCommander.Server.Data public DbSet? Games { get; set; } + public DbSet? GameVersions { get; set; } + public DbSet? Genres { get; set; } public DbSet? Categories { get; set; } diff --git a/LANCommander.Server.Data/Models/Action.cs b/LANCommander.Server.Data/Models/Action.cs index e0bddf35..666fb28b 100644 --- a/LANCommander.Server.Data/Models/Action.cs +++ b/LANCommander.Server.Data/Models/Action.cs @@ -31,5 +31,11 @@ namespace LANCommander.Server.Data.Models [ForeignKey(nameof(ToolId))] [InverseProperty("Actions")] public Tool? Tool { get; set; } + + public Guid? GameVersionId { get; set; } + [JsonIgnore] + [ForeignKey(nameof(GameVersionId))] + [InverseProperty(nameof(GameVersion.Actions))] + public GameVersion? GameVersion { get; set; } } } diff --git a/LANCommander.Server.Data/Models/Archive.cs b/LANCommander.Server.Data/Models/Archive.cs index 49fa60dc..267648b2 100644 --- a/LANCommander.Server.Data/Models/Archive.cs +++ b/LANCommander.Server.Data/Models/Archive.cs @@ -37,6 +37,12 @@ namespace LANCommander.Server.Data.Models [InverseProperty("Archives")] public Tool? Tool { get; set; } + public Guid? GameVersionId { get; set; } + [JsonIgnore] + [ForeignKey(nameof(GameVersionId))] + [InverseProperty(nameof(GameVersion.Archive))] + public GameVersion? GameVersion { get; set; } + [Display(Name = "Last Version")] public Archive? LastVersion { get; set; } diff --git a/LANCommander.Server.Data/Models/Game.cs b/LANCommander.Server.Data/Models/Game.cs index 36366dff..d1642e42 100644 --- a/LANCommander.Server.Data/Models/Game.cs +++ b/LANCommander.Server.Data/Models/Game.cs @@ -42,6 +42,7 @@ namespace LANCommander.Server.Data.Models public ICollection? Publishers { get; set; } public ICollection? Developers { get; set; } public ICollection? Archives { get; set; } + public ICollection? Versions { get; set; } public ICollection