diff --git a/LANCommander.Server.Data.SQLite/Migrations/20241016062829_AddUserRoleNavigationProperties.Designer.cs b/LANCommander.Server.Data.SQLite/Migrations/20241016062829_AddUserRoleNavigationProperties.Designer.cs new file mode 100644 index 00000000..bdeabbd2 --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20241016062829_AddUserRoleNavigationProperties.Designer.cs @@ -0,0 +1,2632 @@ +// +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("20241016062829_AddUserRoleNavigationProperties")] + partial class AddUserRoleNavigationProperties + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true); + + 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("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("DeveloperId") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.HasKey("DeveloperId", "GameId"); + + b.HasIndex("GameId"); + + 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.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("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("Path") + .HasColumnType("TEXT"); + + b.Property("PrimaryAction") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .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("ServerId"); + + 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("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("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.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("IGDBId") + .HasColumnType("INTEGER"); + + 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.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("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.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("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") + .IsRequired() + .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("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ParentId"); + + 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.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("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Redistributables"); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.HasIndex("UpdatedById"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("TEXT"); + + b.Property("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("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("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("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + 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("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() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerId1") + .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("ServerId1"); + + 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() + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("TEXT"); + + b.Property("ServerId1") + .HasColumnType("TEXT"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ServerId"); + + b.HasIndex("ServerId1"); + + 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.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") + .HasColumnType("TEXT"); + + b.Property("CreatedById") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("RefreshToken") + .HasColumnType("TEXT"); + + b.Property("RefreshTokenExpiration") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UpdatedById") + .HasColumnType("TEXT"); + + b.Property("UpdatedOn") + .HasColumnType("TEXT"); + + b.Property("UserName") + .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") + .IsRequired() + .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.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("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("UserRoles", b => + { + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("RoleId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + + 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("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("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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("Server"); + + 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.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("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.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.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.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.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.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.User", "UpdatedBy") + .WithMany() + .HasForeignKey("UpdatedById") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("CreatedBy"); + + b.Navigation("Game"); + + b.Navigation("Redistributable"); + + b.Navigation("Server"); + + 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() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Server", null) + .WithMany("ServerConsoles") + .HasForeignKey("ServerId1"); + + 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() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.Server", null) + .WithMany("HttpPaths") + .HasForeignKey("ServerId1"); + + 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.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.UserToken", b => + { + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .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("UserRoles", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => + { + b.Navigation("Children"); + }); + + 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("DependentGames"); + + b.Navigation("GameSaves"); + + b.Navigation("Issues"); + + b.Navigation("Keys"); + + b.Navigation("Media"); + + b.Navigation("MultiplayerModes"); + + b.Navigation("PlaySessions"); + + 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.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.User", b => + { + b.Navigation("CustomFields"); + + b.Navigation("GameSaves"); + + b.Navigation("Media"); + + b.Navigation("PlaySessions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LANCommander.Server.Data.SQLite/Migrations/20241016062829_AddUserRoleNavigationProperties.cs b/LANCommander.Server.Data.SQLite/Migrations/20241016062829_AddUserRoleNavigationProperties.cs new file mode 100644 index 00000000..b50923c8 --- /dev/null +++ b/LANCommander.Server.Data.SQLite/Migrations/20241016062829_AddUserRoleNavigationProperties.cs @@ -0,0 +1,85 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LANCommander.Migrations +{ + /// + public partial class AddUserRoleNavigationProperties : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Roles_Users_UserId", + table: "Roles"); + + migrationBuilder.DropPrimaryKey( + name: "PK_UserRoles", + table: "UserRoles"); + + migrationBuilder.DropIndex( + name: "IX_UserRoles_RoleId", + table: "UserRoles"); + + migrationBuilder.DropIndex( + name: "IX_Roles_UserId", + table: "Roles"); + + migrationBuilder.DropColumn( + name: "UserId", + table: "Roles"); + + migrationBuilder.AddPrimaryKey( + name: "PK_UserRoles", + table: "UserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_UserId", + table: "UserRoles", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_UserRoles", + table: "UserRoles"); + + migrationBuilder.DropIndex( + name: "IX_UserRoles_UserId", + table: "UserRoles"); + + migrationBuilder.AddColumn( + name: "UserId", + table: "Roles", + type: "TEXT", + nullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_UserRoles", + table: "UserRoles", + columns: new[] { "UserId", "RoleId" }); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_RoleId", + table: "UserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_Roles_UserId", + table: "Roles", + column: "UserId"); + + migrationBuilder.AddForeignKey( + name: "FK_Roles_Users_UserId", + table: "Roles", + column: "UserId", + principalTable: "Users", + principalColumn: "Id"); + } + } +} diff --git a/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs b/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs index f1a34fcc..f23f5b5d 100644 --- a/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs +++ b/LANCommander.Server.Data.SQLite/Migrations/DatabaseContextModelSnapshot.cs @@ -953,9 +953,6 @@ namespace LANCommander.Migrations b.Property("UpdatedOn") .HasColumnType("TEXT"); - b.Property("UserId") - .HasColumnType("TEXT"); - b.HasKey("Id"); b.HasIndex("CreatedById"); @@ -966,8 +963,6 @@ namespace LANCommander.Migrations b.HasIndex("UpdatedById"); - b.HasIndex("UserId"); - b.ToTable("Roles", (string)null); }); @@ -1525,21 +1520,6 @@ namespace LANCommander.Migrations 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") @@ -1619,6 +1599,21 @@ namespace LANCommander.Migrations b.ToTable("RoleCollection"); }); + modelBuilder.Entity("UserRoles", b => + { + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("RoleId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + modelBuilder.Entity("CategoryGame", b => { b.HasOne("LANCommander.Server.Data.Models.Category", null) @@ -2210,10 +2205,6 @@ namespace LANCommander.Migrations .HasForeignKey("UpdatedById") .OnDelete(DeleteBehavior.SetNull); - b.HasOne("LANCommander.Server.Data.Models.User", null) - .WithMany("Roles") - .HasForeignKey("UserId"); - b.Navigation("CreatedBy"); b.Navigation("UpdatedBy"); @@ -2464,21 +2455,6 @@ namespace LANCommander.Migrations .IsRequired(); }); - modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b => - { - b.HasOne("LANCommander.Server.Data.Models.Role", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LANCommander.Server.Data.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b => { b.HasOne("LANCommander.Server.Data.Models.User", null) @@ -2548,6 +2524,21 @@ namespace LANCommander.Migrations .IsRequired(); }); + modelBuilder.Entity("UserRoles", b => + { + b.HasOne("LANCommander.Server.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LANCommander.Server.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("LANCommander.Server.Data.Models.Category", b => { b.Navigation("Children"); @@ -2631,8 +2622,6 @@ namespace LANCommander.Migrations b.Navigation("Media"); b.Navigation("PlaySessions"); - - b.Navigation("Roles"); }); #pragma warning restore 612, 618 } diff --git a/LANCommander.Server.Data/DatabaseContext.cs b/LANCommander.Server.Data/DatabaseContext.cs index 5063b808..2555a128 100644 --- a/LANCommander.Server.Data/DatabaseContext.cs +++ b/LANCommander.Server.Data/DatabaseContext.cs @@ -228,11 +228,19 @@ namespace LANCommander.Server.Data // Each User can have many UserTokens b.HasMany().WithOne().HasForeignKey(ut => ut.UserId).IsRequired(); - - // Each User can have many entries in the UserRole join table - b.HasMany().WithOne().HasForeignKey(ur => ur.UserId).IsRequired(); }); + + + builder.Entity() + .HasMany(u => u.Roles) + .WithMany(r => r.Users) + .UsingEntity>( + "UserRoles", + ur => ur.HasOne().WithMany().HasForeignKey("RoleId").OnDelete(DeleteBehavior.Cascade), + ur => ur.HasOne().WithMany().HasForeignKey("UserId").OnDelete(DeleteBehavior.Cascade) + ); + builder.Entity(b => { // Primary key @@ -279,9 +287,6 @@ namespace LANCommander.Server.Data // The relationships between Role and other entity types // Note that these relationships are configured with no navigation properties - // Each Role can have many entries in the UserRole join table - b.HasMany().WithOne().HasForeignKey(ur => ur.RoleId).IsRequired(); - // Each Role can have many associated RoleClaims b.HasMany().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired(); }); @@ -294,15 +299,6 @@ namespace LANCommander.Server.Data // Maps to the AspNetRoleClaims table b.ToTable("RoleClaims"); }); - - builder.Entity(b => - { - // Primary key - b.HasKey(r => new { r.UserId, r.RoleId }); - - // Maps to the AspNetUserRoles table - b.ToTable("UserRoles"); - }); #endregion #region Server Relationships @@ -443,5 +439,7 @@ namespace LANCommander.Server.Data public DbSet? Issues { get; set; } public DbSet? Pages { get; set; } public DbSet? StorageLocations { get; set; } + public DbSet? Roles { get; set; } + public DbSet? Users { get; set; } } } \ No newline at end of file diff --git a/LANCommander.Server.Data/Models/Role.cs b/LANCommander.Server.Data/Models/Role.cs index baca86e5..c8081a32 100644 --- a/LANCommander.Server.Data/Models/Role.cs +++ b/LANCommander.Server.Data/Models/Role.cs @@ -8,6 +8,7 @@ namespace LANCommander.Server.Data.Models public class Role : IdentityRole, IBaseModel { public virtual ICollection Collections { get; set; } + public virtual ICollection Users { get; set; } [Display(Name = "Created On")] public DateTime CreatedOn { get; set; } diff --git a/LANCommander.Server.Data/Models/User.cs b/LANCommander.Server.Data/Models/User.cs index 03b8801a..91910ede 100644 --- a/LANCommander.Server.Data/Models/User.cs +++ b/LANCommander.Server.Data/Models/User.cs @@ -51,6 +51,7 @@ namespace LANCommander.Server.Data.Models [JsonIgnore] public virtual ICollection? Media { get; set; } + public virtual ICollection? Roles { get; set; } public virtual ICollection? CustomFields { get; set; } [JsonIgnore] @@ -61,8 +62,6 @@ namespace LANCommander.Server.Data.Models public string? Alias { get; set; } - public virtual ICollection Roles { get; set; } = new List(); - [Display(Name = "Created On")] public DateTime CreatedOn { get; set; } diff --git a/LANCommander.Server.Services/Models/ExistingEntityResult.cs b/LANCommander.Server.Services/Models/ExistingEntityResult.cs index 40f0a075..71da43f6 100644 --- a/LANCommander.Server.Services/Models/ExistingEntityResult.cs +++ b/LANCommander.Server.Services/Models/ExistingEntityResult.cs @@ -2,7 +2,7 @@ namespace LANCommander.Server.Services.Models { - public class ExistingEntityResult where T : BaseModel + public class ExistingEntityResult where T : class, IBaseModel { public T Value { get; set; } public bool Existing { get; set; } diff --git a/LANCommander.Server.Services/RoleService.cs b/LANCommander.Server.Services/RoleService.cs index f17eb552..eb6b56a0 100644 --- a/LANCommander.Server.Services/RoleService.cs +++ b/LANCommander.Server.Services/RoleService.cs @@ -1,58 +1,27 @@ -using LANCommander.Server.Data.Models; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; +using LANCommander.Server.Data; +using LANCommander.Server.Data.Models; using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace LANCommander.Server.Services { - public class RoleService : BaseService + public class RoleService : BaseDatabaseService { - private readonly RoleManager RoleManager; + public const string AdministratorRoleName = "Administrator"; public RoleService( ILogger logger, - RoleManager roleManager) : base(logger) - { - RoleManager = roleManager; - } - - public async Task> Get() - { - return await RoleManager.Roles.ToListAsync(); - } - - public async Task Get(Guid id) - { - return await RoleManager.FindByIdAsync(id.ToString()); - } + Repository repository) : base(logger, repository) { } public async Task Get(string roleName) { - return await RoleManager.FindByNameAsync(roleName); + return await Repository.FirstOrDefault(r => r.Name == roleName); } - public async Task Add(Role role) + public async Task> GetUsers(string roleName) { - await RoleManager.CreateAsync(role); + var role = await Get(roleName); - return await Get(role.Name); - } - - public async Task Update(Role role) - { - await RoleManager.UpdateAsync(role); - - return await RoleManager.FindByIdAsync(role.Id.ToString()); - } - - public async Task Delete(Role role) - { - await RoleManager.DeleteAsync(role); + return role.Users; } } } diff --git a/LANCommander.Server.Services/UserCustomFieldService.cs b/LANCommander.Server.Services/UserCustomFieldService.cs new file mode 100644 index 00000000..524fb0f4 --- /dev/null +++ b/LANCommander.Server.Services/UserCustomFieldService.cs @@ -0,0 +1,65 @@ +using LANCommander.Server.Data; +using LANCommander.Server.Data.Models; +using Microsoft.Extensions.Logging; + +namespace LANCommander.Server.Services +{ + public class UserCustomFieldService : BaseDatabaseService + { + + public UserCustomFieldService( + ILogger logger, + Repository repository) : base(logger, repository) { } + + public async Task Get(Guid userId, string name) + { + return await Repository.FirstOrDefault(cf => cf.UserId == userId && cf.Name == name); + } + + public async Task Update(Guid userId, string name, string value) + { + if (name.Length > 64) + throw new ArgumentException("Field name must be 64 characters or shorter"); + + if (value.Length > 1024) + throw new ArgumentException("Field value must be 1024 characters or less"); + + var existing = await Repository.FirstOrDefault(cf => cf.UserId == userId && cf.Name == name); + + if (existing.Value == value) + return; + + if (existing == null) + { + await Repository.Add(new UserCustomField + { + Name = name, + Value = value + }); + + await Repository.SaveChanges(); + } + else if (!String.IsNullOrWhiteSpace(value)) + { + existing.Value = value; + + Repository.Update(existing); + + await Repository.SaveChanges(); + } + else + { + await Delete(userId, name); + } + } + + public async Task Delete(Guid userId, string name) + { + var existing = await Repository.FirstOrDefault(cf => cf.UserId == userId && cf.Name == name); + + Repository.Delete(existing); + + await Repository.SaveChanges(); + } + } +} diff --git a/LANCommander.Server.Services/UserService.cs b/LANCommander.Server.Services/UserService.cs index 5ac914cd..637e3792 100644 --- a/LANCommander.Server.Services/UserService.cs +++ b/LANCommander.Server.Services/UserService.cs @@ -1,67 +1,24 @@ using LANCommander.Server.Data; using LANCommander.Server.Data.Models; -using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; namespace LANCommander.Server.Services { - public class UserService : BaseService + public class UserService : BaseDatabaseService { - private readonly Repository CustomFieldRepository; - private readonly UserManager UserManager; - private readonly RoleManager RoleManager; + private readonly RoleService RoleService; public UserService( ILogger logger, - Repository customFieldRepository, - UserManager userManager, - RoleManager roleManager) : base(logger) + Repository repository, + RoleService roleService) : base(logger, repository) { - CustomFieldRepository = customFieldRepository; - UserManager = userManager; - RoleManager = roleManager; - } - - public async Task> Get() - { - return UserManager.Users; - } - - public async Task Get(Guid id) - { - return await UserManager.FindByIdAsync(id.ToString()); + RoleService = roleService; } public async Task Get(string username) { - return await UserManager.FindByNameAsync(username); - } - - public async Task> GetInRole(string roleName) - { - return await UserManager.GetUsersInRoleAsync(roleName); - } - - public async Task Add(User user) - { - var result = await UserManager.CreateAsync(user); - - if (result.Succeeded) - return await Get(user.UserName); - else - return null; - } - - public async Task Update(User user) - { - await UserManager.UpdateAsync(user); - - return await Get(user.Id); - } - - public async Task Delete(User user) - { - await UserManager.DeleteAsync(user); + return await Repository.FirstOrDefault(u => u.UserName == username); } public async Task> GetRoles(string username) @@ -73,39 +30,32 @@ namespace LANCommander.Server.Services public async Task> GetRoles(User user) { - var roleNames = await UserManager.GetRolesAsync(user); - - var roles = new List(); - - foreach (var roleName in roleNames) - { - var role = await RoleManager.FindByNameAsync(roleName); - - if (role != null) - roles.Add(role); - } - - return roles; - } - - public async Task> GetUsersInRole(string roleName) - { - return await UserManager.GetUsersInRoleAsync(roleName); + return user.Roles; } public async Task IsInRole(User user, string roleName) { - return await UserManager.IsInRoleAsync(user, roleName); + if (user.Roles == null) + return false; + + return user.Roles.Any(r => r.Name == roleName); } - public async Task AddToRole(User user, string role) + public async Task AddToRole(User user, string roleName) { - await UserManager.AddToRoleAsync(user, role); + var role = await RoleService.Get(roleName); + + if (user.Roles == null) + user.Roles = new List(); + + user.Roles.Add(role); + + await Update(user); } - public async Task AddToRoles(User user, IEnumerable roles) + public async Task AddToRoles(User user, IEnumerable roleNames) { - await UserManager.AddToRolesAsync(user, roles); + var roles = await RoleService.Get(r => roleNames.Contains(r.Name)); } public async Task RemoveFromRole(User user, Role role) @@ -113,93 +63,45 @@ namespace LANCommander.Server.Services await RemoveFromRole(user, role.Name); } - public async Task RemoveFromRole(User user, string role) + public async Task RemoveFromRole(User user, string roleName) { - await UserManager.RemoveFromRoleAsync(user, role); + var role = user.Roles.FirstOrDefault(u => u.Name == roleName); + + if (role != null) + { + user.Roles.Remove(role); + + await Update(user); + } } public async Task CheckPassword(User user, string password) { - return await UserManager.CheckPasswordAsync(user, password); + // return await UserManager.CheckPasswordAsync(user, password); + return false; } public async Task ChangePassword(User user, string currentPassword, string newPassword) { - var result = await UserManager.ChangePasswordAsync(user, currentPassword, newPassword); + /*var result = await UserManager.ChangePasswordAsync(user, currentPassword, newPassword); - return result.Succeeded; + return result.Succeeded;*/ + return false; } public async Task ChangePassword(User user, string newPassword) { - var token = await UserManager.GeneratePasswordResetTokenAsync(user); + /*var token = await UserManager.GeneratePasswordResetTokenAsync(user); var result = await UserManager.ResetPasswordAsync(user, token, newPassword); - return result.Succeeded; + return result.Succeeded;*/ + return false; } public async Task SignOut() { } - - public async Task GetCustomField(Guid userId, string name) - { - return await CustomFieldRepository.FirstOrDefault(cf => cf.UserId == userId && cf.Name == name); - } - - public async Task UpdateCustomField(Guid userId, string name, string value) - { - if (name.Length > 64) - throw new ArgumentException("Field name must be 64 characters or shorter"); - - if (value.Length > 1024) - throw new ArgumentException("Field value must be 1024 characters or less"); - - var existing = await CustomFieldRepository.FirstOrDefault(cf => cf.UserId == userId && cf.Name == name); - - if (existing.Value == value) - return; - - if (existing == null) - { - await CustomFieldRepository.Add(new UserCustomField - { - Name = name, - Value = value - }); - - await CustomFieldRepository.SaveChanges(); - } - else if (!String.IsNullOrWhiteSpace(value)) - { - existing.Value = value; - - CustomFieldRepository.Update(existing); - - await CustomFieldRepository.SaveChanges(); - } - else - { - await DeleteCustomField(userId, name); - } - } - - public async Task DeleteCustomField(Guid userId, string name) - { - var existing = await CustomFieldRepository.FirstOrDefault(cf => cf.UserId == userId && cf.Name == name); - - CustomFieldRepository.Delete(existing); - await CustomFieldRepository.SaveChanges(); - } - - public async Task DeleteCustomField(Guid userId, Guid id) - { - var existing = await CustomFieldRepository.FirstOrDefault(cf => cf.UserId == userId && cf.Id == id); - - CustomFieldRepository.Delete(existing); - await CustomFieldRepository.SaveChanges(); - } } } diff --git a/LANCommander.Server.Services/_BaseDatabaseService.cs b/LANCommander.Server.Services/_BaseDatabaseService.cs index 670dd6db..0be7bdb0 100644 --- a/LANCommander.Server.Services/_BaseDatabaseService.cs +++ b/LANCommander.Server.Services/_BaseDatabaseService.cs @@ -8,7 +8,7 @@ using System.Linq.Expressions; namespace LANCommander.Server.Services { - public abstract class BaseDatabaseService : BaseService where T : BaseModel + public abstract class BaseDatabaseService : BaseService where T : class, IBaseModel { public Repository Repository { get; set; } diff --git a/LANCommander.Server/Areas/Identity/Pages/Account/Login.cshtml.cs b/LANCommander.Server/Areas/Identity/Pages/Account/Login.cshtml.cs index e42ea9c1..dab7ab8f 100644 --- a/LANCommander.Server/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/LANCommander.Server/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -24,17 +24,20 @@ namespace LANCommander.Server.Areas.Identity.Pages.Account public class LoginModel : PageModel { private readonly SignInManager _signInManager; - private readonly UserManager _userManager; + private readonly UserService UserService; + private readonly RoleService RoleService; private readonly ILogger _logger; public LoginModel( SignInManager signInManager, - UserManager userManager, + UserService userService, + RoleService roleService, ILogger logger ) { _signInManager = signInManager; - _userManager = userManager; + UserService = userService; + RoleService = roleService; _logger = logger; } @@ -114,9 +117,9 @@ namespace LANCommander.Server.Areas.Identity.Pages.Account if (DatabaseContext.Provider == Data.Enums.DatabaseProvider.Unknown) return Redirect("/FirstTimeSetup"); - var administrators = await _userManager.GetUsersInRoleAsync("Administrator"); + var administrators = await RoleService.GetUsers(RoleService.AdministratorRoleName); - if (administrators.Count == 0) + if (administrators != null && administrators.Any()) return Redirect("/FirstTimeSetup"); return Page(); @@ -139,9 +142,9 @@ namespace LANCommander.Server.Areas.Identity.Pages.Account if (settings.Authentication.RequireApproval) { - var user = await _userManager.FindByNameAsync(Input.UserName); + var user = await UserService.Get(Input.UserName); - if (user != null && !user.Approved && !(await _userManager.IsInRoleAsync(user, "Administrator"))) + if (user != null && !user.Approved && !(await UserService.IsInRole(user, RoleService.AdministratorRoleName))) { ModelState.AddModelError(string.Empty, "Your account must be approved by an administrator."); return Page(); diff --git a/LANCommander.Server/Controllers/Api/ProfileController.cs b/LANCommander.Server/Controllers/Api/ProfileController.cs index c5e4e413..431ca196 100644 --- a/LANCommander.Server/Controllers/Api/ProfileController.cs +++ b/LANCommander.Server/Controllers/Api/ProfileController.cs @@ -18,12 +18,15 @@ namespace LANCommander.Server.Controllers.Api public class ProfileController : BaseApiController { private readonly UserService UserService; + private readonly UserCustomFieldService UserCustomFieldService; public ProfileController( ILogger logger, - UserService userService) : base(logger) + UserService userService, + UserCustomFieldService userCustomFieldService) : base(logger) { UserService = userService; + UserCustomFieldService = userCustomFieldService; } [HttpGet] @@ -112,7 +115,7 @@ namespace LANCommander.Server.Controllers.Api { var user = await UserService.Get(User?.Identity?.Name); - var field = await UserService.GetCustomField(user.Id, name); + var field = await UserCustomFieldService.Get(user.Id, name); return Ok(field.Value); } @@ -131,7 +134,7 @@ namespace LANCommander.Server.Controllers.Api { var user = await UserService.Get(User?.Identity?.Name); - await UserService.UpdateCustomField(user.Id, name, value); + await UserCustomFieldService.Update(user.Id, name, value); return Ok(value); } diff --git a/LANCommander.Server/Program.cs b/LANCommander.Server/Program.cs index 014b35d6..a873163f 100644 --- a/LANCommander.Server/Program.cs +++ b/LANCommander.Server/Program.cs @@ -279,6 +279,7 @@ namespace LANCommander.Server builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/LANCommander.Server/UI/Pages/FirstTimeSetup/Administrator.razor b/LANCommander.Server/UI/Pages/FirstTimeSetup/Administrator.razor index c1a38080..fc27779a 100644 --- a/LANCommander.Server/UI/Pages/FirstTimeSetup/Administrator.razor +++ b/LANCommander.Server/UI/Pages/FirstTimeSetup/Administrator.razor @@ -59,9 +59,9 @@ Name = "Administrator" }); - var administrators = await UserService.GetUsersInRole("Administrator"); + var administrators = await RoleService.GetUsers("Administrator"); - if (administrators.Any()) + if (administrators != null && administrators.Any()) NavigationManager.NavigateTo("/"); else { diff --git a/LANCommander.Server/UI/Pages/FirstTimeSetup/FirstTimeSetupLayout.razor b/LANCommander.Server/UI/Pages/FirstTimeSetup/FirstTimeSetupLayout.razor index 6bb4715e..ea9425d9 100644 --- a/LANCommander.Server/UI/Pages/FirstTimeSetup/FirstTimeSetupLayout.razor +++ b/LANCommander.Server/UI/Pages/FirstTimeSetup/FirstTimeSetupLayout.razor @@ -2,8 +2,7 @@ @inherits LayoutComponentBase @layout BasicLayout @inject UserService UserService -@inject RoleManager RoleManager -@inject IUserStore UserStore +@inject RoleService RoleService @inject NavigationManager NavigationManager @@ -34,17 +33,17 @@ { if (DatabaseContext.Provider != Data.Enums.DatabaseProvider.Unknown) { - var role = await RoleManager.FindByNameAsync("Administrator"); + var role = await RoleService.Get("Administrator"); if (role == null) - await RoleManager.CreateAsync(new Role + await RoleService.Add(new Role { Name = "Administrator" }); - var administrators = await UserService.GetInRole("Administrator"); + var administrators = await RoleService.GetUsers("Administrator"); - if (administrators.Any()) + if (administrators != null && administrators.Any()) NavigationManager.NavigateTo("/"); } } diff --git a/LANCommander.Server/UI/Pages/Settings/Roles/Index.razor b/LANCommander.Server/UI/Pages/Settings/Roles/Index.razor index 6291cb5c..35fad3ea 100644 --- a/LANCommander.Server/UI/Pages/Settings/Roles/Index.razor +++ b/LANCommander.Server/UI/Pages/Settings/Roles/Index.razor @@ -102,14 +102,12 @@ foreach (var role in await RoleService.Get()) { - var users = await UserService.GetUsersInRole(role.Name); - Roles.Add(new RoleViewModel() { Id = role.Id, Name = role.Name, Collections = role.Collections != null ? role.Collections.Count : 0, - Users = users != null ? users.Count() : 0 + Users = role.Users.Count() }); } diff --git a/LANCommander.Server/UI/Pages/Settings/Users/Components/ManageRolesDialog.razor b/LANCommander.Server/UI/Pages/Settings/Users/Components/ManageRolesDialog.razor index 2a0a48b6..07529f8e 100644 --- a/LANCommander.Server/UI/Pages/Settings/Users/Components/ManageRolesDialog.razor +++ b/LANCommander.Server/UI/Pages/Settings/Users/Components/ManageRolesDialog.razor @@ -53,7 +53,7 @@ public override async Task OnFeedbackOkAsync(ModalClosingEventArgs args) { - var currentAdmins = await UserService.GetUsersInRole("Administrator"); + var currentAdmins = await RoleService.GetUsers("Administrator"); try { diff --git a/LANCommander.Server/UI/Pages/Settings/Users/Index.razor b/LANCommander.Server/UI/Pages/Settings/Users/Index.razor index fc2f8006..db6bc2f0 100644 --- a/LANCommander.Server/UI/Pages/Settings/Users/Index.razor +++ b/LANCommander.Server/UI/Pages/Settings/Users/Index.razor @@ -90,11 +90,13 @@ if (Directory.Exists(savePath)) saveSize = new DirectoryInfo(savePath).EnumerateFiles("*", SearchOption.AllDirectories).Sum(f => f.Length); + var roles = await UserService.GetRoles(user); + UserList.Add(new UserViewModel() { Id = user.Id, UserName = user.UserName, - Roles = (await UserService.GetRoles(user)).Select(r => r.Name), + Roles = roles.Select(r => r.Name), SavesSize = saveSize, Approved = user.Approved });