diff --git a/LANCommander.Server.Data.MySQL/Migrations/20260628172954_AddUserRoleLimits.Designer.cs b/LANCommander.Server.Data.MySQL/Migrations/20260628172954_AddUserRoleLimits.Designer.cs new file mode 100644 index 00000000..81f66900 --- /dev/null +++ b/LANCommander.Server.Data.MySQL/Migrations/20260628172954_AddUserRoleLimits.Designer.cs @@ -0,0 +1,3304 @@ +// +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("20260628172954_AddUserRoleLimits")] + partial class AddUserRoleLimits + { + /// + 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("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("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("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("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.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("DownloadSpeedKBps") + .HasColumnType("int"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("StorageQuotaMB") + .HasColumnType("int"); + + 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("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("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("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("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("AlwaysInstall") + .HasColumnType("tinyint(1)"); + + 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("DownloadSpeedKBps") + .HasColumnType("int"); + + 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("StorageQuotaMB") + .HasColumnType("int"); + + 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.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("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.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("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.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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + 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.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("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"); + }); + + 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/20260628172954_AddUserRoleLimits.cs b/LANCommander.Server.Data.MySQL/Migrations/20260628172954_AddUserRoleLimits.cs new file mode 100644 index 00000000..fa5b516b --- /dev/null +++ b/LANCommander.Server.Data.MySQL/Migrations/20260628172954_AddUserRoleLimits.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Server.Data.MySQL.Migrations +{ + /// + public partial class AddUserRoleLimits : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DownloadSpeedKBps", + table: "Users", + type: "int", + nullable: true); + + migrationBuilder.AddColumn( + name: "StorageQuotaMB", + table: "Users", + type: "int", + nullable: true); + + migrationBuilder.AddColumn( + name: "DownloadSpeedKBps", + table: "Roles", + type: "int", + nullable: true); + + migrationBuilder.AddColumn( + name: "StorageQuotaMB", + table: "Roles", + type: "int", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DownloadSpeedKBps", + table: "Users"); + + migrationBuilder.DropColumn( + name: "StorageQuotaMB", + table: "Users"); + + migrationBuilder.DropColumn( + name: "DownloadSpeedKBps", + table: "Roles"); + + migrationBuilder.DropColumn( + name: "StorageQuotaMB", + table: "Roles"); + } + } +} diff --git a/LANCommander.Server.Data.MySQL/Migrations/20260628181234_AddEnableSaves.Designer.cs b/LANCommander.Server.Data.MySQL/Migrations/20260628181234_AddEnableSaves.Designer.cs new file mode 100644 index 00000000..40b15f89 --- /dev/null +++ b/LANCommander.Server.Data.MySQL/Migrations/20260628181234_AddEnableSaves.Designer.cs @@ -0,0 +1,3310 @@ +// +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("20260628181234_AddEnableSaves")] + partial class AddEnableSaves + { + /// + 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("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("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("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("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.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("DownloadSpeedKBps") + .HasColumnType("int"); + + b.Property("EnableSaves") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("StorageQuotaMB") + .HasColumnType("int"); + + 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("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("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("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("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("AlwaysInstall") + .HasColumnType("tinyint(1)"); + + 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("DownloadSpeedKBps") + .HasColumnType("int"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EnableSaves") + .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("StorageQuotaMB") + .HasColumnType("int"); + + 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.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("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.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("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.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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + 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.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("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"); + }); + + 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/20260628181234_AddEnableSaves.cs b/LANCommander.Server.Data.MySQL/Migrations/20260628181234_AddEnableSaves.cs new file mode 100644 index 00000000..4cc10b7a --- /dev/null +++ b/LANCommander.Server.Data.MySQL/Migrations/20260628181234_AddEnableSaves.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Server.Data.MySQL.Migrations +{ + /// + public partial class AddEnableSaves : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EnableSaves", + table: "Users", + type: "tinyint(1)", + nullable: true); + + migrationBuilder.AddColumn( + name: "EnableSaves", + table: "Roles", + type: "tinyint(1)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EnableSaves", + table: "Users"); + + migrationBuilder.DropColumn( + name: "EnableSaves", + table: "Roles"); + } + } +} diff --git a/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs b/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs index f61ec7c7..da7c9803 100644 --- a/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs +++ b/LANCommander.Server.Data.MySQL/Migrations/DatabaseContextModelSnapshot.cs @@ -1242,6 +1242,12 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("CreatedOn") .HasColumnType("datetime(6)"); + b.Property("DownloadSpeedKBps") + .HasColumnType("int"); + + b.Property("EnableSaves") + .HasColumnType("tinyint(1)"); + b.Property("Name") .HasMaxLength(256) .HasColumnType("varchar(256)"); @@ -1250,6 +1256,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations .HasMaxLength(256) .HasColumnType("varchar(256)"); + b.Property("StorageQuotaMB") + .HasColumnType("int"); + b.Property("UpdatedById") .HasColumnType("char(36)"); @@ -1733,6 +1742,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("CreatedOn") .HasColumnType("datetime(6)"); + b.Property("DownloadSpeedKBps") + .HasColumnType("int"); + b.Property("Email") .HasMaxLength(256) .HasColumnType("varchar(256)"); @@ -1740,6 +1752,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("EmailConfirmed") .HasColumnType("tinyint(1)"); + b.Property("EnableSaves") + .HasColumnType("tinyint(1)"); + b.Property("LockoutEnabled") .HasColumnType("tinyint(1)"); @@ -1772,6 +1787,9 @@ namespace LANCommander.Server.Data.MySQL.Migrations b.Property("SecurityStamp") .HasColumnType("longtext"); + b.Property("StorageQuotaMB") + .HasColumnType("int"); + b.Property("TwoFactorEnabled") .HasColumnType("tinyint(1)"); diff --git a/LANCommander.Server.Data.PostgreSQL/Migrations/20260628172752_AddUserRoleLimits.Designer.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628172752_AddUserRoleLimits.Designer.cs new file mode 100644 index 00000000..1989ef4a --- /dev/null +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628172752_AddUserRoleLimits.Designer.cs @@ -0,0 +1,3304 @@ +// +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("20260628172752_AddUserRoleLimits")] + partial class AddUserRoleLimits + { + /// + 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("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("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("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("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.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("DownloadSpeedKBps") + .HasColumnType("integer"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("StorageQuotaMB") + .HasColumnType("integer"); + + 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("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("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("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("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("AlwaysInstall") + .HasColumnType("boolean"); + + 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("DownloadSpeedKBps") + .HasColumnType("integer"); + + 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("StorageQuotaMB") + .HasColumnType("integer"); + + 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.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("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.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("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.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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + 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.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("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"); + }); + + 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/20260628172752_AddUserRoleLimits.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628172752_AddUserRoleLimits.cs new file mode 100644 index 00000000..82587277 --- /dev/null +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628172752_AddUserRoleLimits.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Server.Data.PostgreSQL.Migrations +{ + /// + public partial class AddUserRoleLimits : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DownloadSpeedKBps", + table: "Users", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "StorageQuotaMB", + table: "Users", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "DownloadSpeedKBps", + table: "Roles", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "StorageQuotaMB", + table: "Roles", + type: "integer", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DownloadSpeedKBps", + table: "Users"); + + migrationBuilder.DropColumn( + name: "StorageQuotaMB", + table: "Users"); + + migrationBuilder.DropColumn( + name: "DownloadSpeedKBps", + table: "Roles"); + + migrationBuilder.DropColumn( + name: "StorageQuotaMB", + table: "Roles"); + } + } +} diff --git a/LANCommander.Server.Data.PostgreSQL/Migrations/20260628181115_AddEnableSaves.Designer.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628181115_AddEnableSaves.Designer.cs new file mode 100644 index 00000000..7ff8a750 --- /dev/null +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628181115_AddEnableSaves.Designer.cs @@ -0,0 +1,3310 @@ +// +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("20260628181115_AddEnableSaves")] + partial class AddEnableSaves + { + /// + 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("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("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("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("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.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("DownloadSpeedKBps") + .HasColumnType("integer"); + + b.Property("EnableSaves") + .HasColumnType("boolean"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("StorageQuotaMB") + .HasColumnType("integer"); + + 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("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("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("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("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("AlwaysInstall") + .HasColumnType("boolean"); + + 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("DownloadSpeedKBps") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("EnableSaves") + .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("StorageQuotaMB") + .HasColumnType("integer"); + + 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.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("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.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("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.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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + 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.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("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"); + }); + + 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/20260628181115_AddEnableSaves.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628181115_AddEnableSaves.cs new file mode 100644 index 00000000..7e79da2b --- /dev/null +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/20260628181115_AddEnableSaves.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Server.Data.PostgreSQL.Migrations +{ + /// + public partial class AddEnableSaves : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EnableSaves", + table: "Users", + type: "boolean", + nullable: true); + + migrationBuilder.AddColumn( + name: "EnableSaves", + table: "Roles", + type: "boolean", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EnableSaves", + table: "Users"); + + migrationBuilder.DropColumn( + name: "EnableSaves", + table: "Roles"); + } + } +} diff --git a/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs b/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs index 96997bc2..c6872d2a 100644 --- a/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs +++ b/LANCommander.Server.Data.PostgreSQL/Migrations/DatabaseContextModelSnapshot.cs @@ -1242,6 +1242,12 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("CreatedOn") .HasColumnType("timestamp with time zone"); + b.Property("DownloadSpeedKBps") + .HasColumnType("integer"); + + b.Property("EnableSaves") + .HasColumnType("boolean"); + b.Property("Name") .HasMaxLength(256) .HasColumnType("character varying(256)"); @@ -1250,6 +1256,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations .HasMaxLength(256) .HasColumnType("character varying(256)"); + b.Property("StorageQuotaMB") + .HasColumnType("integer"); + b.Property("UpdatedById") .HasColumnType("uuid"); @@ -1733,6 +1742,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("CreatedOn") .HasColumnType("timestamp with time zone"); + b.Property("DownloadSpeedKBps") + .HasColumnType("integer"); + b.Property("Email") .HasMaxLength(256) .HasColumnType("character varying(256)"); @@ -1740,6 +1752,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("EmailConfirmed") .HasColumnType("boolean"); + b.Property("EnableSaves") + .HasColumnType("boolean"); + b.Property("LockoutEnabled") .HasColumnType("boolean"); @@ -1772,6 +1787,9 @@ namespace LANCommander.Server.Data.PostgreSQL.Migrations b.Property("SecurityStamp") .HasColumnType("text"); + b.Property("StorageQuotaMB") + .HasColumnType("integer"); + b.Property("TwoFactorEnabled") .HasColumnType("boolean"); diff --git a/LANCommander.Server.Data.SQLite/Migrations/20260628172405_AddUserRoleLimits.Designer.cs b/LANCommander.Server.Data.SQLite/Migrations/20260628172405_AddUserRoleLimits.Designer.cs new file mode 100644 index 00000000..9fa67a39 --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20260628172405_AddUserRoleLimits.Designer.cs @@ -0,0 +1,3295 @@ +// +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("20260628172405_AddUserRoleLimits")] + partial class AddUserRoleLimits + { + /// + 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("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("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("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("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.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("DownloadSpeedKBps") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("StorageQuotaMB") + .HasColumnType("INTEGER"); + + 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("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("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("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("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("AlwaysInstall") + .HasColumnType("INTEGER"); + + 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("DownloadSpeedKBps") + .HasColumnType("INTEGER"); + + 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("StorageQuotaMB") + .HasColumnType("INTEGER"); + + 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.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("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.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("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.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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + 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.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("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"); + }); + + 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/20260628172405_AddUserRoleLimits.cs b/LANCommander.Server.Data.SQLite/Migrations/20260628172405_AddUserRoleLimits.cs new file mode 100644 index 00000000..c7ba2f4c --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20260628172405_AddUserRoleLimits.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Migrations +{ + /// + public partial class AddUserRoleLimits : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DownloadSpeedKBps", + table: "Users", + type: "INTEGER", + nullable: true); + + migrationBuilder.AddColumn( + name: "StorageQuotaMB", + table: "Users", + type: "INTEGER", + nullable: true); + + migrationBuilder.AddColumn( + name: "DownloadSpeedKBps", + table: "Roles", + type: "INTEGER", + nullable: true); + + migrationBuilder.AddColumn( + name: "StorageQuotaMB", + table: "Roles", + type: "INTEGER", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DownloadSpeedKBps", + table: "Users"); + + migrationBuilder.DropColumn( + name: "StorageQuotaMB", + table: "Users"); + + migrationBuilder.DropColumn( + name: "DownloadSpeedKBps", + table: "Roles"); + + migrationBuilder.DropColumn( + name: "StorageQuotaMB", + table: "Roles"); + } + } +} diff --git a/LANCommander.Server.Data.SQLite/Migrations/20260628180740_AddEnableSaves.Designer.cs b/LANCommander.Server.Data.SQLite/Migrations/20260628180740_AddEnableSaves.Designer.cs new file mode 100644 index 00000000..1c7813cd --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20260628180740_AddEnableSaves.Designer.cs @@ -0,0 +1,3301 @@ +// +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("20260628180740_AddEnableSaves")] + partial class AddEnableSaves + { + /// + 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("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("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("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("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.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("DownloadSpeedKBps") + .HasColumnType("INTEGER"); + + b.Property("EnableSaves") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("StorageQuotaMB") + .HasColumnType("INTEGER"); + + 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("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("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("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("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("AlwaysInstall") + .HasColumnType("INTEGER"); + + 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("DownloadSpeedKBps") + .HasColumnType("INTEGER"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EnableSaves") + .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("StorageQuotaMB") + .HasColumnType("INTEGER"); + + 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.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("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.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("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.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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + 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.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("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"); + }); + + 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/20260628180740_AddEnableSaves.cs b/LANCommander.Server.Data.SQLite/Migrations/20260628180740_AddEnableSaves.cs new file mode 100644 index 00000000..c0d8171a --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20260628180740_AddEnableSaves.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Migrations +{ + /// + public partial class AddEnableSaves : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EnableSaves", + table: "Users", + type: "INTEGER", + nullable: true); + + migrationBuilder.AddColumn( + name: "EnableSaves", + table: "Roles", + type: "INTEGER", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EnableSaves", + table: "Users"); + + migrationBuilder.DropColumn( + name: "EnableSaves", + table: "Roles"); + } + } +} diff --git a/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs b/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs index 78ce5f03..2e89c0fd 100644 --- a/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs +++ b/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs @@ -1237,6 +1237,12 @@ namespace LANCommander.Migrations b.Property("CreatedOn") .HasColumnType("TEXT"); + b.Property("DownloadSpeedKBps") + .HasColumnType("INTEGER"); + + b.Property("EnableSaves") + .HasColumnType("INTEGER"); + b.Property("Name") .HasMaxLength(256) .HasColumnType("TEXT"); @@ -1245,6 +1251,9 @@ namespace LANCommander.Migrations .HasMaxLength(256) .HasColumnType("TEXT"); + b.Property("StorageQuotaMB") + .HasColumnType("INTEGER"); + b.Property("UpdatedById") .HasColumnType("TEXT"); @@ -1726,6 +1735,9 @@ namespace LANCommander.Migrations b.Property("CreatedOn") .HasColumnType("TEXT"); + b.Property("DownloadSpeedKBps") + .HasColumnType("INTEGER"); + b.Property("Email") .HasMaxLength(256) .HasColumnType("TEXT"); @@ -1733,6 +1745,9 @@ namespace LANCommander.Migrations b.Property("EmailConfirmed") .HasColumnType("INTEGER"); + b.Property("EnableSaves") + .HasColumnType("INTEGER"); + b.Property("LockoutEnabled") .HasColumnType("INTEGER"); @@ -1765,6 +1780,9 @@ namespace LANCommander.Migrations b.Property("SecurityStamp") .HasColumnType("TEXT"); + b.Property("StorageQuotaMB") + .HasColumnType("INTEGER"); + b.Property("TwoFactorEnabled") .HasColumnType("INTEGER"); diff --git a/LANCommander.Server.Data/Models/Role.cs b/LANCommander.Server.Data/Models/Role.cs index 21397609..0cfdaeea 100644 --- a/LANCommander.Server.Data/Models/Role.cs +++ b/LANCommander.Server.Data/Models/Role.cs @@ -9,6 +9,16 @@ namespace LANCommander.Server.Data.Models { public ICollection Collections { get; set; } public ICollection UserRoles { get; set; } + + [Display(Name = "Storage Quota (MB)")] + public int? StorageQuotaMB { get; set; } + + [Display(Name = "Download Speed (KB/s)")] + public int? DownloadSpeedKBps { get; set; } + + [Display(Name = "Enable Saves")] + public bool? EnableSaves { get; set; } + [NotMapped] public ICollection Users { diff --git a/LANCommander.Server.Data/Models/User.cs b/LANCommander.Server.Data/Models/User.cs index 395bb548..4401df80 100644 --- a/LANCommander.Server.Data/Models/User.cs +++ b/LANCommander.Server.Data/Models/User.cs @@ -74,6 +74,18 @@ namespace LANCommander.Server.Data.Models public string? Alias { get; set; } + [JsonIgnore] + [Display(Name = "Storage Quota (MB)")] + public int? StorageQuotaMB { get; set; } + + [JsonIgnore] + [Display(Name = "Download Speed (KB/s)")] + public int? DownloadSpeedKBps { get; set; } + + [JsonIgnore] + [Display(Name = "Enable Saves")] + public bool? EnableSaves { get; set; } + [JsonIgnore] [Display(Name = "Created On")] public DateTime CreatedOn { get; set; } = DateTime.UtcNow; diff --git a/LANCommander.Server.Services/LANCommander.Server.Services.csproj b/LANCommander.Server.Services/LANCommander.Server.Services.csproj index 53a80c95..31c481d9 100644 --- a/LANCommander.Server.Services/LANCommander.Server.Services.csproj +++ b/LANCommander.Server.Services/LANCommander.Server.Services.csproj @@ -28,6 +28,10 @@ + + + + diff --git a/LANCommander.Server.Services/Models/UserLimits.cs b/LANCommander.Server.Services/Models/UserLimits.cs new file mode 100644 index 00000000..f4ef0d9c --- /dev/null +++ b/LANCommander.Server.Services/Models/UserLimits.cs @@ -0,0 +1,10 @@ +namespace LANCommander.Server.Services.Models +{ + public readonly record struct UserLimits(int StorageQuotaMB, int DownloadSpeedKBps, bool SavesEnabled) + { + public long StorageQuotaBytes => StorageQuotaMB <= 0 ? 0 : (long)StorageQuotaMB * 1024 * 1024; + public long DownloadSpeedBytesPerSecond => DownloadSpeedKBps <= 0 ? 0 : (long)DownloadSpeedKBps * 1024; + public bool StorageUnlimited => StorageQuotaMB <= 0; + public bool DownloadUnlimited => DownloadSpeedKBps <= 0; + } +} diff --git a/LANCommander.Server.Services/RoleService.cs b/LANCommander.Server.Services/RoleService.cs index 1779ac5f..9bbf507e 100644 --- a/LANCommander.Server.Services/RoleService.cs +++ b/LANCommander.Server.Services/RoleService.cs @@ -37,10 +37,15 @@ namespace LANCommander.Server.Services public override async Task UpdateAsync(Role entity) { - return await base.UpdateAsync(entity, async context => + var role = await base.UpdateAsync(entity, async context => { await context.UpdateRelationshipAsync(r => r.Collections); }); + + // Role limit columns are cached as part of users' role snapshots, so invalidate them. + await cache.RemoveByTagAsync(["User/Roles", "User/Security"]); + + return role; } public async Task GetAsync(string roleName) diff --git a/LANCommander.Server.Services/UserService.cs b/LANCommander.Server.Services/UserService.cs index cc5f0b9a..ee5889b9 100644 --- a/LANCommander.Server.Services/UserService.cs +++ b/LANCommander.Server.Services/UserService.cs @@ -100,6 +100,49 @@ namespace LANCommander.Server.Services return roles.Any(r => r.Name == roleName); } + public async Task GetLimitsAsync(User user) + { + var roles = await GetRolesAsync(user); + + var storageQuota = Resolve(user.StorageQuotaMB, roles.Select(r => r.StorageQuotaMB)); + var downloadSpeed = Resolve(user.DownloadSpeedKBps, roles.Select(r => r.DownloadSpeedKBps)); + var savesEnabled = Resolve(user.EnableSaves, roles.Select(r => r.EnableSaves)); + + return new UserLimits(storageQuota, downloadSpeed, savesEnabled); + } + + /// + /// Resolves an effective limit value. A per-user override (if set) takes precedence. Otherwise the most + /// restrictive (lowest non-zero) value across the user's roles is used. A value of 0 means unlimited, and a + /// null role value means the limit is not configured for that role and is ignored. + /// + internal static int Resolve(int? userOverride, IEnumerable roleValues) + { + if (userOverride.HasValue) + return userOverride.Value; + + var restrictive = roleValues + .Where(v => v.HasValue && v.Value > 0) + .Select(v => v!.Value) + .ToList(); + + return restrictive.Count == 0 ? 0 : restrictive.Min(); + } + + /// + /// Resolves an effective boolean permission (e.g. whether saves are enabled). A per-user override (if set) + /// takes precedence. Otherwise the most restrictive value across the user's roles is used: if any role + /// explicitly disables the permission it is disabled. A null role value means the permission is not configured + /// for that role and is ignored; if no role configures it the permission defaults to enabled. + /// + internal static bool Resolve(bool? userOverride, IEnumerable roleValues) + { + if (userOverride.HasValue) + return userOverride.Value; + + return !roleValues.Any(v => v == false); + } + public async Task> GetCollectionsAsync(User user) { try @@ -523,9 +566,14 @@ namespace LANCommander.Server.Services user.Alias = entity.Alias; user.Approved = entity.Approved; user.ApprovedOn = entity.ApprovedOn; + user.StorageQuotaMB = entity.StorageQuotaMB; + user.DownloadSpeedKBps = entity.DownloadSpeedKBps; + user.EnableSaves = entity.EnableSaves; await identityContext.UserManager.UpdateAsync(user); + await Cache.RemoveByTagAsync($"User/{entity.Id}"); + return user; } diff --git a/LANCommander.Server/Endpoints/ArchivesEndpoints.cs b/LANCommander.Server/Endpoints/ArchivesEndpoints.cs index 261a378e..a6fd22d3 100644 --- a/LANCommander.Server/Endpoints/ArchivesEndpoints.cs +++ b/LANCommander.Server/Endpoints/ArchivesEndpoints.cs @@ -37,7 +37,9 @@ public static class ArchivesEndpoints internal static async Task> DownloadAsync( Guid id, + System.Security.Claims.ClaimsPrincipal user, [FromServices] ArchiveService archiveService, + [FromServices] DownloadThrottle downloadThrottle, [FromServices] ILoggerFactory loggerFactory) { var logger = loggerFactory.CreateLogger("ArchivesApi"); @@ -64,8 +66,11 @@ public static class ArchivesEndpoints return TypedResults.NotFound(); } + var stream = await downloadThrottle.ApplyAsync( + new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), user); + return TypedResults.File( - new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), + stream, "application/octet-stream", $"{archive.Game.Title.SanitizeFilename()}.zip"); } diff --git a/LANCommander.Server/Endpoints/DownloadEndpoints.cs b/LANCommander.Server/Endpoints/DownloadEndpoints.cs index e3ca0158..aadb440e 100644 --- a/LANCommander.Server/Endpoints/DownloadEndpoints.cs +++ b/LANCommander.Server/Endpoints/DownloadEndpoints.cs @@ -20,13 +20,15 @@ public static class DownloadEndpoints internal static async Task> DownloadArchiveAsync( Guid id, + ClaimsPrincipal user, [FromServices] ArchiveService archiveService, + [FromServices] DownloadThrottle downloadThrottle, [FromServices] ILoggerFactory loggerFactory) { - var logger = loggerFactory.CreateLogger(nameof(DownloadEndpoints)); - - logger.LogInformation("Attempting to download archive with ID: {ArchiveId}", id); - + var logger = loggerFactory.CreateLogger(nameof(DownloadEndpoints)); + + logger.LogInformation("Attempting to download archive with ID: {ArchiveId}", id); + var archive = await archiveService .Include(a => a.Game!) .Include(a => a.Redistributable!) @@ -36,10 +38,10 @@ public static class DownloadEndpoints { logger.LogWarning("Archive with ID {ArchiveId} not found", id); return TypedResults.NotFound(); - } - - var fileName = await archiveService.GetArchiveFileLocationAsync(archive); - + } + + var fileName = await archiveService.GetArchiveFileLocationAsync(archive); + if (!File.Exists(fileName)) { logger.LogWarning("Archive file not found at path: {FilePath} for archive ID {ArchiveId}", fileName, id); @@ -57,9 +59,12 @@ public static class DownloadEndpoints { name = $"{archive.Redistributable.Name.SanitizeFilename()}.zip"; logger.LogInformation("Serving redistributable archive {RedistName} (ID: {ArchiveId})", archive.Redistributable.Name, id); - } - - return TypedResults.File(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read), fileDownloadName: name, contentType: MediaTypeNames.Application.Octet); + } + + var stream = await downloadThrottle.ApplyAsync( + new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read), user); + + return TypedResults.File(stream, fileDownloadName: name, contentType: MediaTypeNames.Application.Octet); } internal static async Task> DownloadSaveAsync( @@ -68,29 +73,29 @@ public static class DownloadEndpoints [FromServices] GameSaveService gameSaveService, [FromServices] ILoggerFactory loggerFactory) { - var logger = loggerFactory.CreateLogger(nameof(DownloadEndpoints)); - - logger.LogInformation("Attempting to download save with ID: {SaveId}", id); - + var logger = loggerFactory.CreateLogger(nameof(DownloadEndpoints)); + + logger.LogInformation("Attempting to download save with ID: {SaveId}", id); + var save = await gameSaveService .Include(s => s.Game!) .Include(s => s.User!) - .GetAsync(id); - + .GetAsync(id); + if (user == null || user.Identity?.Name != save.User?.UserName && !user.IsInRole(RoleService.AdministratorRoleName)) { logger.LogWarning("Unauthorized access attempt for save {SaveId} by user {UserName}", id, user?.Identity?.Name); return TypedResults.Unauthorized(); - } - + } + if (save == null) { logger.LogWarning("Save with ID {SaveId} not found", id); return TypedResults.NotFound(); } - var fileName = gameSaveService.GetSavePath(save); - + var fileName = gameSaveService.GetSavePath(save); + if (!File.Exists(fileName)) { logger.LogWarning("Save file not found at path: {FilePath}", fileName); @@ -111,10 +116,10 @@ public static class DownloadEndpoints [FromServices] UpdateService updateService, [FromServices] ILoggerFactory loggerFactory) { - var logger = loggerFactory.CreateLogger(nameof(DownloadEndpoints)); - - logger.LogInformation("Attempting to download launcher file with object key: {ObjectKey}", objectKey); - + var logger = loggerFactory.CreateLogger(nameof(DownloadEndpoints)); + + logger.LogInformation("Attempting to download launcher file with object key: {ObjectKey}", objectKey); + if (string.IsNullOrEmpty(objectKey)) { logger.LogWarning("Empty object key provided for launcher download"); diff --git a/LANCommander.Server/Endpoints/DownloadThrottle.cs b/LANCommander.Server/Endpoints/DownloadThrottle.cs new file mode 100644 index 00000000..33ca98f5 --- /dev/null +++ b/LANCommander.Server/Endpoints/DownloadThrottle.cs @@ -0,0 +1,31 @@ +using System.Security.Claims; +using LANCommander.Server.Services; + +namespace LANCommander.Server.Endpoints; + +internal sealed class DownloadThrottle(UserService userService) +{ + /// + /// Wraps the source stream in a using the authenticated user's resolved download + /// speed limit. Anonymous requests and users without a configured limit are returned unthrottled. + /// + public async Task ApplyAsync(Stream source, ClaimsPrincipal? principal) + { + var userName = principal?.Identity?.Name; + + if (principal?.Identity?.IsAuthenticated != true || string.IsNullOrEmpty(userName)) + return source; + + var user = await userService.GetAsync(userName); + + if (user == null) + return source; + + var limits = await userService.GetLimitsAsync(user); + + if (limits.DownloadUnlimited) + return source; + + return new ThrottledStream(source, limits.DownloadSpeedBytesPerSecond); + } +} diff --git a/LANCommander.Server/Endpoints/GameEndpoints.cs b/LANCommander.Server/Endpoints/GameEndpoints.cs index 9194b2be..aa756014 100644 --- a/LANCommander.Server/Endpoints/GameEndpoints.cs +++ b/LANCommander.Server/Endpoints/GameEndpoints.cs @@ -412,6 +412,7 @@ public static class GameEndpoints internal static async Task DownloadAsync( [FromServices] GameService gameService, [FromServices] ArchiveService archiveService, + [FromServices] DownloadThrottle downloadThrottle, [FromServices] IOptions settings, [FromServices] ILogger logger, ClaimsPrincipal userPrincipal, @@ -463,8 +464,10 @@ public static class GameEndpoints var contentType = MediaTypeNames.Application.Octet; var fileName = $"{game.Title.SanitizeFilename()}.zip"; - - return TypedResults.File(fs, contentType, fileName); + + var stream = await downloadThrottle.ApplyAsync(fs, userPrincipal); + + return TypedResults.File(stream, contentType, fileName); } internal static async Task ImportAsync( diff --git a/LANCommander.Server/Endpoints/SaveEndpoints.cs b/LANCommander.Server/Endpoints/SaveEndpoints.cs index 141a2972..a84bbbe0 100644 --- a/LANCommander.Server/Endpoints/SaveEndpoints.cs +++ b/LANCommander.Server/Endpoints/SaveEndpoints.cs @@ -252,6 +252,35 @@ public static class SaveEndpoints using (var stream = file.OpenReadStream()) { + var limits = await userService.GetLimitsAsync(user); + + if (!limits.SavesEnabled) + return TypedResults.BadRequest("Cloud saves are disabled for your account."); + + if (!limits.StorageUnlimited) + { + if (stream.Length > limits.StorageQuotaBytes) + return TypedResults.BadRequest("Save exceeds your storage quota."); + + // Cull oldest saves (across all games) to make room for the incoming save. + var existingSaves = await saveService + .Query(q => q + .Where(s => s.UserId == user.Id) + .OrderBy(s => s.CreatedOn)) + .GetAsync(); + + var used = existingSaves.Sum(s => s.Size); + + foreach (var saveToCull in existingSaves) + { + if (used + stream.Length <= limits.StorageQuotaBytes) + break; + + await saveService.DeleteAsync(saveToCull); + used -= saveToCull.Size; + } + } + var save = new GameSave { Game = game, @@ -259,9 +288,9 @@ public static class SaveEndpoints Size = stream.Length, StorageLocation = saveStorageLocation, }; - + stream.Seek(0, SeekOrigin.Begin); - + save = await saveService.AddAsync(save); try diff --git a/LANCommander.Server/Endpoints/StreamFileResult.cs b/LANCommander.Server/Endpoints/StreamFileResult.cs new file mode 100644 index 00000000..8713b675 --- /dev/null +++ b/LANCommander.Server/Endpoints/StreamFileResult.cs @@ -0,0 +1,48 @@ +using System.Net.Mime; +using Microsoft.AspNetCore.Http; + +namespace LANCommander.Server.Endpoints; + +/// +/// Streams a file to the response with a configurable buffer size for higher download throughput. +/// +internal sealed class StreamFileResult : IResult +{ + private const int DefaultBufferSize = 1024 * 1024; // 1 MB + + private readonly Stream _fileStream; + private readonly string _contentType; + private readonly string _fileDownloadName; + private readonly int _bufferSize; + + public StreamFileResult( + Stream fileStream, + string contentType, + string fileDownloadName, + int bufferSize = DefaultBufferSize) + { + _fileStream = fileStream; + _contentType = contentType; + _fileDownloadName = fileDownloadName; + _bufferSize = bufferSize; + } + + public async Task ExecuteAsync(HttpContext httpContext) + { + var response = httpContext.Response; + var cancellationToken = httpContext.RequestAborted; + + response.ContentType = _contentType; + response.Headers.ContentLength = _fileStream.Length; + response.Headers.ContentDisposition = $"attachment; filename=\"{_fileDownloadName}\""; + + try + { + await _fileStream.CopyToAsync(response.Body, _bufferSize, cancellationToken); + } + finally + { + await _fileStream.DisposeAsync(); + } + } +} diff --git a/LANCommander.Server/Endpoints/ThrottledStream.cs b/LANCommander.Server/Endpoints/ThrottledStream.cs new file mode 100644 index 00000000..595088a8 --- /dev/null +++ b/LANCommander.Server/Endpoints/ThrottledStream.cs @@ -0,0 +1,119 @@ +using System.Diagnostics; + +namespace LANCommander.Server.Endpoints; + +/// +/// Wraps a source stream and limits how fast it can be read by sleeping when a per-second byte budget is exceeded. +/// Seek and length members are delegated to the inner stream so HTTP range/resume and Content-Length keep working. +/// A of 0 (or less) disables throttling. +/// +internal sealed class ThrottledStream : Stream +{ + private readonly Stream _inner; + private readonly long _bytesPerSecond; + + private long _windowStartTimestamp; + private long _bytesInWindow; + + public ThrottledStream(Stream inner, long bytesPerSecond) + { + _inner = inner ?? throw new ArgumentNullException(nameof(inner)); + _bytesPerSecond = bytesPerSecond; + _windowStartTimestamp = Stopwatch.GetTimestamp(); + } + + public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + if (_bytesPerSecond <= 0) + return await _inner.ReadAsync(buffer, cancellationToken); + + await ThrottleAsync(cancellationToken); + + var read = await _inner.ReadAsync(buffer, cancellationToken); + + Accumulate(read); + + return read; + } + + public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + return await ReadAsync(buffer.AsMemory(offset, count), cancellationToken); + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (_bytesPerSecond <= 0) + return _inner.Read(buffer, offset, count); + + ThrottleAsync(CancellationToken.None).AsTask().GetAwaiter().GetResult(); + + var read = _inner.Read(buffer, offset, count); + + Accumulate(read); + + return read; + } + + private async ValueTask ThrottleAsync(CancellationToken cancellationToken) + { + if (_bytesInWindow < _bytesPerSecond) + return; + + var elapsed = Stopwatch.GetElapsedTime(_windowStartTimestamp); + var remaining = TimeSpan.FromSeconds(1) - elapsed; + + if (remaining > TimeSpan.Zero) + await Task.Delay(remaining, cancellationToken); + + _windowStartTimestamp = Stopwatch.GetTimestamp(); + _bytesInWindow = 0; + } + + private void Accumulate(int read) + { + if (read <= 0) + return; + + if (Stopwatch.GetElapsedTime(_windowStartTimestamp) >= TimeSpan.FromSeconds(1)) + { + _windowStartTimestamp = Stopwatch.GetTimestamp(); + _bytesInWindow = 0; + } + + _bytesInWindow += read; + } + + public override bool CanRead => _inner.CanRead; + public override bool CanSeek => _inner.CanSeek; + public override bool CanWrite => false; + public override long Length => _inner.Length; + + public override long Position + { + get => _inner.Position; + set => _inner.Position = value; + } + + public override long Seek(long offset, SeekOrigin origin) => _inner.Seek(offset, origin); + + public override void Flush() => _inner.Flush(); + + public override void SetLength(long value) => throw new NotSupportedException(); + + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); + + protected override void Dispose(bool disposing) + { + if (disposing) + _inner.Dispose(); + + base.Dispose(disposing); + } + + public override async ValueTask DisposeAsync() + { + await _inner.DisposeAsync(); + await base.DisposeAsync(); + } +} diff --git a/LANCommander.Server/Startup/Services.cs b/LANCommander.Server/Startup/Services.cs index b21651b3..576185b7 100644 --- a/LANCommander.Server/Startup/Services.cs +++ b/LANCommander.Server/Startup/Services.cs @@ -18,6 +18,7 @@ public static class Services builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddLANCommanderClient(); builder.Services.AddLANCommanderServer(); diff --git a/LANCommander.Server/UI/Pages/Settings/Roles/Edit.razor b/LANCommander.Server/UI/Pages/Settings/Roles/Edit.razor index 3e11fc74..d1d69f75 100644 --- a/LANCommander.Server/UI/Pages/Settings/Roles/Edit.razor +++ b/LANCommander.Server/UI/Pages/Settings/Roles/Edit.razor @@ -24,6 +24,21 @@ + + + + + + + + + diff --git a/LANCommander.Server/UI/Pages/Settings/Users/Edit.razor b/LANCommander.Server/UI/Pages/Settings/Users/Edit.razor index 90829ed7..76604112 100644 --- a/LANCommander.Server/UI/Pages/Settings/Users/Edit.razor +++ b/LANCommander.Server/UI/Pages/Settings/Users/Edit.razor @@ -30,6 +30,29 @@ + @if (IsAdministrator) + { + Limits + + + + + + + + + + + + + } + Custom Fields @if (context.CustomFields == null || context.CustomFields?.Count == 0) @@ -76,11 +99,14 @@ Form Form; bool FieldsModified = false; + bool IsAdministrator = false; protected override async Task OnInitializedAsync() { var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + IsAdministrator = authState.User.IsInRole(RoleService.AdministratorRoleName); + if (authState.User.Identity.IsAuthenticated) { User = await UserService