From 4feb64f01566b3c8ca5c119a1c3f034d08967677 Mon Sep 17 00:00:00 2001 From: defnotken Date: Thu, 4 Sep 2025 10:54:52 -0500 Subject: [PATCH 01/14] Unban work --- .../Controllers/AuthControllerBase.cs | 1 + .../Controllers/UserController.cs | 79 ++ .../LightlessSyncAuthService/Startup.cs | 2 +- .../LightlessSyncServerTest.csproj | 2 +- .../Discord/DiscordBot.cs | 1 - .../Discord/MareModule.cs | 80 ++ .../LightlessDbContextModelSnapshot.cs | 1095 ++++++++++++++++ .../LightlessSyncShared.csproj | 4 + .../20250904154857_AddBannedUid.Designer.cs | 1098 +++++++++++++++++ .../Migrations/20250904154857_AddBannedUid.cs | 36 + .../Migrations/MareDbContextModelSnapshot.cs | 4 + .../LightlessSyncShared/Models/Banned.cs | 1 + 12 files changed, 2400 insertions(+), 3 deletions(-) create mode 100644 LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs create mode 100644 LightlessSyncServer/LightlessSyncShared/LightlessSyncServer/Migrations/LightlessDbContextModelSnapshot.cs create mode 100644 LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.Designer.cs create mode 100644 LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs diff --git a/LightlessSyncServer/LightlessSyncAuthService/Controllers/AuthControllerBase.cs b/LightlessSyncServer/LightlessSyncAuthService/Controllers/AuthControllerBase.cs index d207db6..b47f38d 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Controllers/AuthControllerBase.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Controllers/AuthControllerBase.cs @@ -121,6 +121,7 @@ public abstract class AuthControllerBase : Controller { CharacterIdentification = charaIdent, Reason = "Autobanned CharacterIdent (" + uid + ")", + BannedUid = uid, }); } diff --git a/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs new file mode 100644 index 0000000..df981a8 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs @@ -0,0 +1,79 @@ +using LightlessSync.API.Routes; +using LightlessSyncShared.Data; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace LightlessSyncAuthService.Controllers; + +[Route(LightlessAuth.User)] +public class UserController : Controller +{ + protected readonly ILogger Logger; + protected readonly IDbContextFactory LightlessDbContextFactory; + public UserController(ILogger logger, IDbContextFactory lightlessDbContext) + { + Logger = logger; + LightlessDbContextFactory = lightlessDbContext; + } + + [Authorize(Policy = "Internal")] + [HttpPost(LightlessAuth.User_Unban_Uid)] + public async Task UnBanUserByUid(string uid) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Unbanning user with UID {UID}", uid); + + //Mark User as not banned, and not marked for ban (if marked) + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); + if (auth != null) + { + auth.IsBanned = false; + auth.MarkForBan = false; + } + + // Remove all bans associated with this user + var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == uid); + dbContext.BannedUsers.RemoveRange(bannedFromLightlessIds); + + // Remove all character/discord bans associated with this user + var lodestoneAuths = dbContext.LodeStoneAuth.Where(l => l.User != null && l.User.UID == uid).ToList(); + foreach (var lodestoneAuth in lodestoneAuths) + { + var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == lodestoneAuth.HashedLodestoneId || b.DiscordIdOrLodestoneAuth == lodestoneAuth.DiscordId.ToString()); + dbContext.BannedRegistrations.RemoveRange(bannedRegs); + } + + await dbContext.SaveChangesAsync(); + } + + [Authorize(Policy = "Internal")] + [HttpPost(LightlessAuth.User_Unban_Discord)] + public async Task UnBanUserByDiscordId(string discordId) + { + Logger.LogInformation("Unbanning user with discordId: {discordId}", discordId); + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + var userByDiscord = await dbContext.LodeStoneAuth.Include(l => l.User).FirstOrDefaultAsync(l => l.DiscordId.ToString() == discordId); + + if (userByDiscord?.User == null) + { + Logger.LogInformation("Unbanning user with discordId: {discordId} but no user found", discordId); + return; + } + var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == discordId || b.DiscordIdOrLodestoneAuth == userByDiscord.HashedLodestoneId); + //Mark User as not banned, and not marked for ban (if marked) + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == userByDiscord.User.UID); + if (auth != null) + { + auth.IsBanned = false; + auth.MarkForBan = false; + } + // Remove all bans associated with this user + var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == auth.UserUID || b.BannedUid == auth.PrimaryUserUID); + dbContext.BannedUsers.RemoveRange(bannedFromLightlessIds); + + await dbContext.SaveChangesAsync(); + } +} \ No newline at end of file diff --git a/LightlessSyncServer/LightlessSyncAuthService/Startup.cs b/LightlessSyncServer/LightlessSyncAuthService/Startup.cs index 385fa32..2f81451 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Startup.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Startup.cs @@ -88,7 +88,7 @@ public class Startup services.AddControllers().ConfigureApplicationPartManager(a => { a.FeatureProviders.Remove(a.FeatureProviders.OfType().First()); - a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(JwtController), typeof(OAuthController))); + a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(JwtController), typeof(OAuthController), typeof(UserController))); }); } diff --git a/LightlessSyncServer/LightlessSyncServerTest/LightlessSyncServerTest.csproj b/LightlessSyncServer/LightlessSyncServerTest/LightlessSyncServerTest.csproj index 471a7a3..4753c04 100644 --- a/LightlessSyncServer/LightlessSyncServerTest/LightlessSyncServerTest.csproj +++ b/LightlessSyncServer/LightlessSyncServerTest/LightlessSyncServerTest.csproj @@ -1,7 +1,7 @@  - net6.0 + net9.0 enable enable diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs b/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs index 9fd515f..bbf96c4 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs @@ -7,7 +7,6 @@ using LightlessSyncShared.Models; using LightlessSyncShared.Services; using LightlessSyncShared.Utils.Configuration; using Microsoft.EntityFrameworkCore; -using Newtonsoft.Json.Linq; using StackExchange.Redis; namespace LightlessSyncServices.Discord; diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index 05460e3..84cb501 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -103,6 +103,7 @@ public class LightlessModule : InteractionModuleBase try { using HttpClient c = new HttpClient(); + _logger.LogInformation("Sending message to main server with {}", scope); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/msgc/sendMessage"), new ClientMessage(messageType, message, uid ?? string.Empty)) .ConfigureAwait(false); @@ -138,6 +139,85 @@ public class LightlessModule : InteractionModuleBase } } + [SlashCommand("unbanbydiscord", "ADMIN ONLY: Unban a user by their discord ID")] + public async Task UnbanByDiscord([Summary("discord_id", "Discord ID to unban")] ulong discordId) + { + _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", + Context.Interaction.User.Id, nameof(UnbanByDiscord), + string.Join(",", new[] { $"{nameof(discordId)}:{discordId}" })); + try + { + using HttpClient c = new HttpClient(); + await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue + (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"), new { discordId }) + .ConfigureAwait(false); + var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); + if (discordChannelForMessages != null) + { + var discordChannel = await Context.Guild.GetChannelAsync(discordChannelForMessages.Value).ConfigureAwait(false) as IMessageChannel; + if (discordChannel != null) + { + var embedColor = Color.Blue; + + EmbedBuilder eb = new(); + eb.WithTitle("Unban Alert!"); + eb.WithColor(embedColor); + eb.WithDescription(discordId + " has been unbanned"); + + await discordChannel.SendMessageAsync(embed: eb.Build()).ConfigureAwait(false); + } + } + + await RespondAsync("Message sent", ephemeral: true).ConfigureAwait(false); + } + catch (Exception ex) + { + EmbedBuilder eb = new(); + eb.WithTitle("An error occured"); + eb.WithDescription("Please report this: " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine); + await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); + } + } + + [SlashCommand("unbanbyuid", "ADMIN ONLY: Unban a user by their uid")] + public async Task UnbanByUID([Summary("uid", "uid to unban")] string uid) + { + _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", + Context.Interaction.User.Id, nameof(UnbanByUID), + string.Join(",", new[] { $"{nameof(uid)}:{uid}" })); + try + { + using HttpClient c = new HttpClient(); + await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue + (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanUID"), new { uid }) + .ConfigureAwait(false); + var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); + if (discordChannelForMessages != null) + { + var discordChannel = await Context.Guild.GetChannelAsync(discordChannelForMessages.Value).ConfigureAwait(false) as IMessageChannel; + if (discordChannel != null) + { + var embedColor = Color.Blue; + + EmbedBuilder eb = new(); + eb.WithTitle("Unban Alert!"); + eb.WithColor(embedColor); + eb.WithDescription(uid + " has been unbanned"); + + await discordChannel.SendMessageAsync(embed: eb.Build()).ConfigureAwait(false); + } + } + + await RespondAsync("Message sent", ephemeral: true).ConfigureAwait(false); + } + catch (Exception ex) + { + EmbedBuilder eb = new(); + eb.WithTitle("An error occured"); + eb.WithDescription("Please report this: " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine); + await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); + } + } public async Task HandleUserAdd(string desiredUid, ulong discordUserId) { var embed = new EmbedBuilder(); diff --git a/LightlessSyncServer/LightlessSyncShared/LightlessSyncServer/Migrations/LightlessDbContextModelSnapshot.cs b/LightlessSyncServer/LightlessSyncShared/LightlessSyncServer/Migrations/LightlessDbContextModelSnapshot.cs new file mode 100644 index 0000000..e2ce4c6 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncShared/LightlessSyncServer/Migrations/LightlessDbContextModelSnapshot.cs @@ -0,0 +1,1095 @@ +// +using System; +using LightlessSyncShared.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LightlessSyncServer.Migrations +{ + [DbContext(typeof(LightlessDbContext))] + partial class LightlessDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LightlessSyncShared.Models.Auth", b => + { + b.Property("HashedKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("hashed_key"); + + b.Property("IsBanned") + .HasColumnType("boolean") + .HasColumnName("is_banned"); + + b.Property("MarkForBan") + .HasColumnType("boolean") + .HasColumnName("mark_for_ban"); + + b.Property("PrimaryUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("primary_user_uid"); + + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.HasKey("HashedKey") + .HasName("pk_auth"); + + b.HasIndex("PrimaryUserUID") + .HasDatabaseName("ix_auth_primary_user_uid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_auth_user_uid"); + + b.ToTable("auth", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Banned", b => + { + b.Property("CharacterIdentification") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("character_identification"); + + b.Property("BannedUid") + .HasColumnType("text") + .HasColumnName("banned_uid"); + + b.Property("Reason") + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("CharacterIdentification") + .HasName("pk_banned_users"); + + b.ToTable("banned_users", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.BannedRegistrations", b => + { + b.Property("DiscordIdOrLodestoneAuth") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("discord_id_or_lodestone_auth"); + + b.HasKey("DiscordIdOrLodestoneAuth") + .HasName("pk_banned_registrations"); + + b.ToTable("banned_registrations", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => + { + b.Property("Id") + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("UploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("uploader_uid"); + + b.Property("AccessType") + .HasColumnType("integer") + .HasColumnName("access_type"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_date"); + + b.Property("CustomizeData") + .HasColumnType("text") + .HasColumnName("customize_data"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("DownloadCount") + .HasColumnType("integer") + .HasColumnName("download_count"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("GlamourerData") + .HasColumnType("text") + .HasColumnName("glamourer_data"); + + b.Property("ManipulationData") + .HasColumnType("text") + .HasColumnName("manipulation_data"); + + b.Property("ShareType") + .HasColumnType("integer") + .HasColumnName("share_type"); + + b.Property("UpdatedDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_date"); + + b.HasKey("Id", "UploaderUID") + .HasName("pk_chara_data"); + + b.HasIndex("Id") + .HasDatabaseName("ix_chara_data_id"); + + b.HasIndex("UploaderUID") + .HasDatabaseName("ix_chara_data_uploader_uid"); + + b.ToTable("chara_data", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataAllowance", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowedGroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("allowed_group_gid"); + + b.Property("AllowedUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("allowed_user_uid"); + + b.HasKey("ParentId", "ParentUploaderUID", "Id") + .HasName("pk_chara_data_allowance"); + + b.HasIndex("AllowedGroupGID") + .HasDatabaseName("ix_chara_data_allowance_allowed_group_gid"); + + b.HasIndex("AllowedUserUID") + .HasDatabaseName("ix_chara_data_allowance_allowed_user_uid"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_allowance_parent_id"); + + b.ToTable("chara_data_allowance", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFile", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("GamePath") + .HasColumnType("text") + .HasColumnName("game_path"); + + b.Property("FileCacheHash") + .HasColumnType("character varying(40)") + .HasColumnName("file_cache_hash"); + + b.HasKey("ParentId", "ParentUploaderUID", "GamePath") + .HasName("pk_chara_data_files"); + + b.HasIndex("FileCacheHash") + .HasDatabaseName("ix_chara_data_files_file_cache_hash"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_files_parent_id"); + + b.ToTable("chara_data_files", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFileSwap", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("GamePath") + .HasColumnType("text") + .HasColumnName("game_path"); + + b.Property("FilePath") + .HasColumnType("text") + .HasColumnName("file_path"); + + b.HasKey("ParentId", "ParentUploaderUID", "GamePath") + .HasName("pk_chara_data_file_swaps"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_file_swaps_parent_id"); + + b.ToTable("chara_data_file_swaps", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataOriginalFile", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("GamePath") + .HasColumnType("text") + .HasColumnName("game_path"); + + b.Property("Hash") + .HasColumnType("text") + .HasColumnName("hash"); + + b.HasKey("ParentId", "ParentUploaderUID", "GamePath") + .HasName("pk_chara_data_orig_files"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_orig_files_parent_id"); + + b.ToTable("chara_data_orig_files", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataPose", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("PoseData") + .HasColumnType("text") + .HasColumnName("pose_data"); + + b.Property("WorldData") + .HasColumnType("text") + .HasColumnName("world_data"); + + b.HasKey("ParentId", "ParentUploaderUID", "Id") + .HasName("pk_chara_data_poses"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_poses_parent_id"); + + b.ToTable("chara_data_poses", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.ClientPair", b => + { + b.Property("UserUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("OtherUserUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("other_user_uid"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("UserUID", "OtherUserUID") + .HasName("pk_client_pairs"); + + b.HasIndex("OtherUserUID") + .HasDatabaseName("ix_client_pairs_other_user_uid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_client_pairs_user_uid"); + + b.ToTable("client_pairs", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.FileCache", b => + { + b.Property("Hash") + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("hash"); + + b.Property("RawSize") + .HasColumnType("bigint") + .HasColumnName("raw_size"); + + b.Property("Size") + .HasColumnType("bigint") + .HasColumnName("size"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.Property("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("upload_date"); + + b.Property("Uploaded") + .HasColumnType("boolean") + .HasColumnName("uploaded"); + + b.Property("UploaderUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("uploader_uid"); + + b.HasKey("Hash") + .HasName("pk_file_caches"); + + b.HasIndex("UploaderUID") + .HasDatabaseName("ix_file_caches_uploader_uid"); + + b.ToTable("file_caches", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.ForbiddenUploadEntry", b => + { + b.Property("Hash") + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("hash"); + + b.Property("ForbiddenBy") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("forbidden_by"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("Hash") + .HasName("pk_forbidden_upload_entries"); + + b.ToTable("forbidden_upload_entries", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Group", b => + { + b.Property("GID") + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("gid"); + + b.Property("Alias") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("alias"); + + b.Property("HashedPassword") + .HasColumnType("text") + .HasColumnName("hashed_password"); + + b.Property("InvitesEnabled") + .HasColumnType("boolean") + .HasColumnName("invites_enabled"); + + b.Property("OwnerUID") + .HasColumnType("character varying(10)") + .HasColumnName("owner_uid"); + + b.Property("PreferDisableAnimations") + .HasColumnType("boolean") + .HasColumnName("prefer_disable_animations"); + + b.Property("PreferDisableSounds") + .HasColumnType("boolean") + .HasColumnName("prefer_disable_sounds"); + + b.Property("PreferDisableVFX") + .HasColumnType("boolean") + .HasColumnName("prefer_disable_vfx"); + + b.HasKey("GID") + .HasName("pk_groups"); + + b.HasIndex("OwnerUID") + .HasDatabaseName("ix_groups_owner_uid"); + + b.ToTable("groups", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupBan", b => + { + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("BannedUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("banned_user_uid"); + + b.Property("BannedByUID") + .HasColumnType("character varying(10)") + .HasColumnName("banned_by_uid"); + + b.Property("BannedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("banned_on"); + + b.Property("BannedReason") + .HasColumnType("text") + .HasColumnName("banned_reason"); + + b.HasKey("GroupGID", "BannedUserUID") + .HasName("pk_group_bans"); + + b.HasIndex("BannedByUID") + .HasDatabaseName("ix_group_bans_banned_by_uid"); + + b.HasIndex("BannedUserUID") + .HasDatabaseName("ix_group_bans_banned_user_uid"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_bans_group_gid"); + + b.ToTable("group_bans", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPair", b => + { + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("GroupUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("group_user_uid"); + + b.Property("IsModerator") + .HasColumnType("boolean") + .HasColumnName("is_moderator"); + + b.Property("IsPinned") + .HasColumnType("boolean") + .HasColumnName("is_pinned"); + + b.HasKey("GroupGID", "GroupUserUID") + .HasName("pk_group_pairs"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_pairs_group_gid"); + + b.HasIndex("GroupUserUID") + .HasDatabaseName("ix_group_pairs_group_user_uid"); + + b.ToTable("group_pairs", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPairPreferredPermission", b => + { + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("DisableAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_animations"); + + b.Property("DisableSounds") + .HasColumnType("boolean") + .HasColumnName("disable_sounds"); + + b.Property("DisableVFX") + .HasColumnType("boolean") + .HasColumnName("disable_vfx"); + + b.Property("IsPaused") + .HasColumnType("boolean") + .HasColumnName("is_paused"); + + b.HasKey("UserUID", "GroupGID") + .HasName("pk_group_pair_preferred_permissions"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_pair_preferred_permissions_group_gid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_group_pair_preferred_permissions_user_uid"); + + b.ToTable("group_pair_preferred_permissions", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupTempInvite", b => + { + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("Invite") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("invite"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_date"); + + b.HasKey("GroupGID", "Invite") + .HasName("pk_group_temp_invites"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_temp_invites_group_gid"); + + b.HasIndex("Invite") + .HasDatabaseName("ix_group_temp_invites_invite"); + + b.ToTable("group_temp_invites", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.LodeStoneAuth", b => + { + b.Property("DiscordId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("discord_id"); + + b.Property("HashedLodestoneId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("hashed_lodestone_id"); + + b.Property("LodestoneAuthString") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("lodestone_auth_string"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("started_at"); + + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.HasKey("DiscordId") + .HasName("pk_lodestone_auth"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_lodestone_auth_user_uid"); + + b.ToTable("lodestone_auth", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.User", b => + { + b.Property("UID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("uid"); + + b.Property("Alias") + .HasMaxLength(15) + .HasColumnType("character varying(15)") + .HasColumnName("alias"); + + b.Property("IsAdmin") + .HasColumnType("boolean") + .HasColumnName("is_admin"); + + b.Property("IsModerator") + .HasColumnType("boolean") + .HasColumnName("is_moderator"); + + b.Property("LastLoggedIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_logged_in"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("UID") + .HasName("pk_users"); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserDefaultPreferredPermission", b => + { + b.Property("UserUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("DisableGroupAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_group_animations"); + + b.Property("DisableGroupSounds") + .HasColumnType("boolean") + .HasColumnName("disable_group_sounds"); + + b.Property("DisableGroupVFX") + .HasColumnType("boolean") + .HasColumnName("disable_group_vfx"); + + b.Property("DisableIndividualAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_individual_animations"); + + b.Property("DisableIndividualSounds") + .HasColumnType("boolean") + .HasColumnName("disable_individual_sounds"); + + b.Property("DisableIndividualVFX") + .HasColumnType("boolean") + .HasColumnName("disable_individual_vfx"); + + b.Property("IndividualIsSticky") + .HasColumnType("boolean") + .HasColumnName("individual_is_sticky"); + + b.HasKey("UserUID") + .HasName("pk_user_default_preferred_permissions"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_user_default_preferred_permissions_user_uid"); + + b.ToTable("user_default_preferred_permissions", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserPermissionSet", b => + { + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("OtherUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("other_user_uid"); + + b.Property("DisableAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_animations"); + + b.Property("DisableSounds") + .HasColumnType("boolean") + .HasColumnName("disable_sounds"); + + b.Property("DisableVFX") + .HasColumnType("boolean") + .HasColumnName("disable_vfx"); + + b.Property("IsPaused") + .HasColumnType("boolean") + .HasColumnName("is_paused"); + + b.Property("Sticky") + .HasColumnType("boolean") + .HasColumnName("sticky"); + + b.HasKey("UserUID", "OtherUserUID") + .HasName("pk_user_permission_sets"); + + b.HasIndex("OtherUserUID") + .HasDatabaseName("ix_user_permission_sets_other_user_uid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_user_permission_sets_user_uid"); + + b.HasIndex("UserUID", "OtherUserUID", "IsPaused") + .HasDatabaseName("ix_user_permission_sets_user_uid_other_user_uid_is_paused"); + + b.ToTable("user_permission_sets", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserProfileData", b => + { + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("Base64ProfileImage") + .HasColumnType("text") + .HasColumnName("base64profile_image"); + + b.Property("FlaggedForReport") + .HasColumnType("boolean") + .HasColumnName("flagged_for_report"); + + b.Property("IsNSFW") + .HasColumnType("boolean") + .HasColumnName("is_nsfw"); + + b.Property("ProfileDisabled") + .HasColumnType("boolean") + .HasColumnName("profile_disabled"); + + b.Property("UserDescription") + .HasColumnType("text") + .HasColumnName("user_description"); + + b.HasKey("UserUID") + .HasName("pk_user_profile_data"); + + b.ToTable("user_profile_data", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Auth", b => + { + b.HasOne("LightlessSyncShared.Models.User", "PrimaryUser") + .WithMany() + .HasForeignKey("PrimaryUserUID") + .HasConstraintName("fk_auth_users_primary_user_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .HasConstraintName("fk_auth_users_user_uid"); + + b.Navigation("PrimaryUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => + { + b.HasOne("LightlessSyncShared.Models.User", "Uploader") + .WithMany() + .HasForeignKey("UploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_users_uploader_uid"); + + b.Navigation("Uploader"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataAllowance", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "AllowedGroup") + .WithMany() + .HasForeignKey("AllowedGroupGID") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_chara_data_allowance_groups_allowed_group_gid"); + + b.HasOne("LightlessSyncShared.Models.User", "AllowedUser") + .WithMany() + .HasForeignKey("AllowedUserUID") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_chara_data_allowance_users_allowed_user_uid"); + + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("AllowedIndividiuals") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_allowance_chara_data_parent_id_parent_uploader_u"); + + b.Navigation("AllowedGroup"); + + b.Navigation("AllowedUser"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFile", b => + { + b.HasOne("LightlessSyncShared.Models.FileCache", "FileCache") + .WithMany() + .HasForeignKey("FileCacheHash") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_chara_data_files_files_file_cache_hash"); + + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("Files") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_files_chara_data_parent_id_parent_uploader_uid"); + + b.Navigation("FileCache"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFileSwap", b => + { + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("FileSwaps") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_file_swaps_chara_data_parent_id_parent_uploader_"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataOriginalFile", b => + { + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("OriginalFiles") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_orig_files_chara_data_parent_id_parent_uploader_"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataPose", b => + { + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("Poses") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_poses_chara_data_parent_id_parent_uploader_uid"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.ClientPair", b => + { + b.HasOne("LightlessSyncShared.Models.User", "OtherUser") + .WithMany() + .HasForeignKey("OtherUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_client_pairs_users_other_user_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_client_pairs_users_user_uid"); + + b.Navigation("OtherUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.FileCache", b => + { + b.HasOne("LightlessSyncShared.Models.User", "Uploader") + .WithMany() + .HasForeignKey("UploaderUID") + .HasConstraintName("fk_file_caches_users_uploader_uid"); + + b.Navigation("Uploader"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Group", b => + { + b.HasOne("LightlessSyncShared.Models.User", "Owner") + .WithMany() + .HasForeignKey("OwnerUID") + .HasConstraintName("fk_groups_users_owner_uid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupBan", b => + { + b.HasOne("LightlessSyncShared.Models.User", "BannedBy") + .WithMany() + .HasForeignKey("BannedByUID") + .HasConstraintName("fk_group_bans_users_banned_by_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "BannedUser") + .WithMany() + .HasForeignKey("BannedUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_bans_users_banned_user_uid"); + + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_bans_groups_group_gid"); + + b.Navigation("BannedBy"); + + b.Navigation("BannedUser"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPair", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pairs_groups_group_gid"); + + b.HasOne("LightlessSyncShared.Models.User", "GroupUser") + .WithMany() + .HasForeignKey("GroupUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pairs_users_group_user_uid"); + + b.Navigation("Group"); + + b.Navigation("GroupUser"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPairPreferredPermission", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pair_preferred_permissions_groups_group_gid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pair_preferred_permissions_users_user_uid"); + + b.Navigation("Group"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupTempInvite", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_temp_invites_groups_group_gid"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.LodeStoneAuth", b => + { + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .HasConstraintName("fk_lodestone_auth_users_user_uid"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserDefaultPreferredPermission", b => + { + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_default_preferred_permissions_users_user_uid"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserPermissionSet", b => + { + b.HasOne("LightlessSyncShared.Models.User", "OtherUser") + .WithMany() + .HasForeignKey("OtherUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_permission_sets_users_other_user_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_permission_sets_users_user_uid"); + + b.Navigation("OtherUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserProfileData", b => + { + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_profile_data_users_user_uid"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => + { + b.Navigation("AllowedIndividiuals"); + + b.Navigation("FileSwaps"); + + b.Navigation("Files"); + + b.Navigation("OriginalFiles"); + + b.Navigation("Poses"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj b/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj index 8cc310e..b5b7383 100644 --- a/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj +++ b/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj @@ -54,4 +54,8 @@ + + + + diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.Designer.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.Designer.cs new file mode 100644 index 0000000..218efbe --- /dev/null +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.Designer.cs @@ -0,0 +1,1098 @@ +// +using System; +using LightlessSyncShared.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 LightlessSyncServer.Migrations +{ + [DbContext(typeof(LightlessDbContext))] + [Migration("20250904154857_AddBannedUid")] + partial class AddBannedUid + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LightlessSyncShared.Models.Auth", b => + { + b.Property("HashedKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("hashed_key"); + + b.Property("IsBanned") + .HasColumnType("boolean") + .HasColumnName("is_banned"); + + b.Property("MarkForBan") + .HasColumnType("boolean") + .HasColumnName("mark_for_ban"); + + b.Property("PrimaryUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("primary_user_uid"); + + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.HasKey("HashedKey") + .HasName("pk_auth"); + + b.HasIndex("PrimaryUserUID") + .HasDatabaseName("ix_auth_primary_user_uid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_auth_user_uid"); + + b.ToTable("auth", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Banned", b => + { + b.Property("CharacterIdentification") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("character_identification"); + + b.Property("BannedUid") + .HasColumnType("text") + .HasColumnName("banned_uid"); + + b.Property("Reason") + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("CharacterIdentification") + .HasName("pk_banned_users"); + + b.ToTable("banned_users", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.BannedRegistrations", b => + { + b.Property("DiscordIdOrLodestoneAuth") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("discord_id_or_lodestone_auth"); + + b.HasKey("DiscordIdOrLodestoneAuth") + .HasName("pk_banned_registrations"); + + b.ToTable("banned_registrations", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => + { + b.Property("Id") + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("UploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("uploader_uid"); + + b.Property("AccessType") + .HasColumnType("integer") + .HasColumnName("access_type"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_date"); + + b.Property("CustomizeData") + .HasColumnType("text") + .HasColumnName("customize_data"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("DownloadCount") + .HasColumnType("integer") + .HasColumnName("download_count"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("GlamourerData") + .HasColumnType("text") + .HasColumnName("glamourer_data"); + + b.Property("ManipulationData") + .HasColumnType("text") + .HasColumnName("manipulation_data"); + + b.Property("ShareType") + .HasColumnType("integer") + .HasColumnName("share_type"); + + b.Property("UpdatedDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_date"); + + b.HasKey("Id", "UploaderUID") + .HasName("pk_chara_data"); + + b.HasIndex("Id") + .HasDatabaseName("ix_chara_data_id"); + + b.HasIndex("UploaderUID") + .HasDatabaseName("ix_chara_data_uploader_uid"); + + b.ToTable("chara_data", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataAllowance", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowedGroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("allowed_group_gid"); + + b.Property("AllowedUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("allowed_user_uid"); + + b.HasKey("ParentId", "ParentUploaderUID", "Id") + .HasName("pk_chara_data_allowance"); + + b.HasIndex("AllowedGroupGID") + .HasDatabaseName("ix_chara_data_allowance_allowed_group_gid"); + + b.HasIndex("AllowedUserUID") + .HasDatabaseName("ix_chara_data_allowance_allowed_user_uid"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_allowance_parent_id"); + + b.ToTable("chara_data_allowance", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFile", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("GamePath") + .HasColumnType("text") + .HasColumnName("game_path"); + + b.Property("FileCacheHash") + .HasColumnType("character varying(40)") + .HasColumnName("file_cache_hash"); + + b.HasKey("ParentId", "ParentUploaderUID", "GamePath") + .HasName("pk_chara_data_files"); + + b.HasIndex("FileCacheHash") + .HasDatabaseName("ix_chara_data_files_file_cache_hash"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_files_parent_id"); + + b.ToTable("chara_data_files", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFileSwap", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("GamePath") + .HasColumnType("text") + .HasColumnName("game_path"); + + b.Property("FilePath") + .HasColumnType("text") + .HasColumnName("file_path"); + + b.HasKey("ParentId", "ParentUploaderUID", "GamePath") + .HasName("pk_chara_data_file_swaps"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_file_swaps_parent_id"); + + b.ToTable("chara_data_file_swaps", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataOriginalFile", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("GamePath") + .HasColumnType("text") + .HasColumnName("game_path"); + + b.Property("Hash") + .HasColumnType("text") + .HasColumnName("hash"); + + b.HasKey("ParentId", "ParentUploaderUID", "GamePath") + .HasName("pk_chara_data_orig_files"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_orig_files_parent_id"); + + b.ToTable("chara_data_orig_files", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataPose", b => + { + b.Property("ParentId") + .HasColumnType("text") + .HasColumnName("parent_id"); + + b.Property("ParentUploaderUID") + .HasColumnType("character varying(10)") + .HasColumnName("parent_uploader_uid"); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("PoseData") + .HasColumnType("text") + .HasColumnName("pose_data"); + + b.Property("WorldData") + .HasColumnType("text") + .HasColumnName("world_data"); + + b.HasKey("ParentId", "ParentUploaderUID", "Id") + .HasName("pk_chara_data_poses"); + + b.HasIndex("ParentId") + .HasDatabaseName("ix_chara_data_poses_parent_id"); + + b.ToTable("chara_data_poses", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.ClientPair", b => + { + b.Property("UserUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("OtherUserUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("other_user_uid"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("UserUID", "OtherUserUID") + .HasName("pk_client_pairs"); + + b.HasIndex("OtherUserUID") + .HasDatabaseName("ix_client_pairs_other_user_uid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_client_pairs_user_uid"); + + b.ToTable("client_pairs", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.FileCache", b => + { + b.Property("Hash") + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("hash"); + + b.Property("RawSize") + .HasColumnType("bigint") + .HasColumnName("raw_size"); + + b.Property("Size") + .HasColumnType("bigint") + .HasColumnName("size"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.Property("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("upload_date"); + + b.Property("Uploaded") + .HasColumnType("boolean") + .HasColumnName("uploaded"); + + b.Property("UploaderUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("uploader_uid"); + + b.HasKey("Hash") + .HasName("pk_file_caches"); + + b.HasIndex("UploaderUID") + .HasDatabaseName("ix_file_caches_uploader_uid"); + + b.ToTable("file_caches", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.ForbiddenUploadEntry", b => + { + b.Property("Hash") + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("hash"); + + b.Property("ForbiddenBy") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("forbidden_by"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("Hash") + .HasName("pk_forbidden_upload_entries"); + + b.ToTable("forbidden_upload_entries", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Group", b => + { + b.Property("GID") + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("gid"); + + b.Property("Alias") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("alias"); + + b.Property("HashedPassword") + .HasColumnType("text") + .HasColumnName("hashed_password"); + + b.Property("InvitesEnabled") + .HasColumnType("boolean") + .HasColumnName("invites_enabled"); + + b.Property("OwnerUID") + .HasColumnType("character varying(10)") + .HasColumnName("owner_uid"); + + b.Property("PreferDisableAnimations") + .HasColumnType("boolean") + .HasColumnName("prefer_disable_animations"); + + b.Property("PreferDisableSounds") + .HasColumnType("boolean") + .HasColumnName("prefer_disable_sounds"); + + b.Property("PreferDisableVFX") + .HasColumnType("boolean") + .HasColumnName("prefer_disable_vfx"); + + b.HasKey("GID") + .HasName("pk_groups"); + + b.HasIndex("OwnerUID") + .HasDatabaseName("ix_groups_owner_uid"); + + b.ToTable("groups", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupBan", b => + { + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("BannedUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("banned_user_uid"); + + b.Property("BannedByUID") + .HasColumnType("character varying(10)") + .HasColumnName("banned_by_uid"); + + b.Property("BannedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("banned_on"); + + b.Property("BannedReason") + .HasColumnType("text") + .HasColumnName("banned_reason"); + + b.HasKey("GroupGID", "BannedUserUID") + .HasName("pk_group_bans"); + + b.HasIndex("BannedByUID") + .HasDatabaseName("ix_group_bans_banned_by_uid"); + + b.HasIndex("BannedUserUID") + .HasDatabaseName("ix_group_bans_banned_user_uid"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_bans_group_gid"); + + b.ToTable("group_bans", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPair", b => + { + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("GroupUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("group_user_uid"); + + b.Property("IsModerator") + .HasColumnType("boolean") + .HasColumnName("is_moderator"); + + b.Property("IsPinned") + .HasColumnType("boolean") + .HasColumnName("is_pinned"); + + b.HasKey("GroupGID", "GroupUserUID") + .HasName("pk_group_pairs"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_pairs_group_gid"); + + b.HasIndex("GroupUserUID") + .HasDatabaseName("ix_group_pairs_group_user_uid"); + + b.ToTable("group_pairs", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPairPreferredPermission", b => + { + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("DisableAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_animations"); + + b.Property("DisableSounds") + .HasColumnType("boolean") + .HasColumnName("disable_sounds"); + + b.Property("DisableVFX") + .HasColumnType("boolean") + .HasColumnName("disable_vfx"); + + b.Property("IsPaused") + .HasColumnType("boolean") + .HasColumnName("is_paused"); + + b.HasKey("UserUID", "GroupGID") + .HasName("pk_group_pair_preferred_permissions"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_pair_preferred_permissions_group_gid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_group_pair_preferred_permissions_user_uid"); + + b.ToTable("group_pair_preferred_permissions", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupTempInvite", b => + { + b.Property("GroupGID") + .HasColumnType("character varying(20)") + .HasColumnName("group_gid"); + + b.Property("Invite") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("invite"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_date"); + + b.HasKey("GroupGID", "Invite") + .HasName("pk_group_temp_invites"); + + b.HasIndex("GroupGID") + .HasDatabaseName("ix_group_temp_invites_group_gid"); + + b.HasIndex("Invite") + .HasDatabaseName("ix_group_temp_invites_invite"); + + b.ToTable("group_temp_invites", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.LodeStoneAuth", b => + { + b.Property("DiscordId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("discord_id"); + + b.Property("HashedLodestoneId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("hashed_lodestone_id"); + + b.Property("LodestoneAuthString") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("lodestone_auth_string"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("started_at"); + + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.HasKey("DiscordId") + .HasName("pk_lodestone_auth"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_lodestone_auth_user_uid"); + + b.ToTable("lodestone_auth", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.User", b => + { + b.Property("UID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("uid"); + + b.Property("Alias") + .HasMaxLength(15) + .HasColumnType("character varying(15)") + .HasColumnName("alias"); + + b.Property("IsAdmin") + .HasColumnType("boolean") + .HasColumnName("is_admin"); + + b.Property("IsModerator") + .HasColumnType("boolean") + .HasColumnName("is_moderator"); + + b.Property("LastLoggedIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_logged_in"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea") + .HasColumnName("timestamp"); + + b.HasKey("UID") + .HasName("pk_users"); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserDefaultPreferredPermission", b => + { + b.Property("UserUID") + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("DisableGroupAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_group_animations"); + + b.Property("DisableGroupSounds") + .HasColumnType("boolean") + .HasColumnName("disable_group_sounds"); + + b.Property("DisableGroupVFX") + .HasColumnType("boolean") + .HasColumnName("disable_group_vfx"); + + b.Property("DisableIndividualAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_individual_animations"); + + b.Property("DisableIndividualSounds") + .HasColumnType("boolean") + .HasColumnName("disable_individual_sounds"); + + b.Property("DisableIndividualVFX") + .HasColumnType("boolean") + .HasColumnName("disable_individual_vfx"); + + b.Property("IndividualIsSticky") + .HasColumnType("boolean") + .HasColumnName("individual_is_sticky"); + + b.HasKey("UserUID") + .HasName("pk_user_default_preferred_permissions"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_user_default_preferred_permissions_user_uid"); + + b.ToTable("user_default_preferred_permissions", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserPermissionSet", b => + { + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("OtherUserUID") + .HasColumnType("character varying(10)") + .HasColumnName("other_user_uid"); + + b.Property("DisableAnimations") + .HasColumnType("boolean") + .HasColumnName("disable_animations"); + + b.Property("DisableSounds") + .HasColumnType("boolean") + .HasColumnName("disable_sounds"); + + b.Property("DisableVFX") + .HasColumnType("boolean") + .HasColumnName("disable_vfx"); + + b.Property("IsPaused") + .HasColumnType("boolean") + .HasColumnName("is_paused"); + + b.Property("Sticky") + .HasColumnType("boolean") + .HasColumnName("sticky"); + + b.HasKey("UserUID", "OtherUserUID") + .HasName("pk_user_permission_sets"); + + b.HasIndex("OtherUserUID") + .HasDatabaseName("ix_user_permission_sets_other_user_uid"); + + b.HasIndex("UserUID") + .HasDatabaseName("ix_user_permission_sets_user_uid"); + + b.HasIndex("UserUID", "OtherUserUID", "IsPaused") + .HasDatabaseName("ix_user_permission_sets_user_uid_other_user_uid_is_paused"); + + b.ToTable("user_permission_sets", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserProfileData", b => + { + b.Property("UserUID") + .HasColumnType("character varying(10)") + .HasColumnName("user_uid"); + + b.Property("Base64ProfileImage") + .HasColumnType("text") + .HasColumnName("base64profile_image"); + + b.Property("FlaggedForReport") + .HasColumnType("boolean") + .HasColumnName("flagged_for_report"); + + b.Property("IsNSFW") + .HasColumnType("boolean") + .HasColumnName("is_nsfw"); + + b.Property("ProfileDisabled") + .HasColumnType("boolean") + .HasColumnName("profile_disabled"); + + b.Property("UserDescription") + .HasColumnType("text") + .HasColumnName("user_description"); + + b.HasKey("UserUID") + .HasName("pk_user_profile_data"); + + b.ToTable("user_profile_data", (string)null); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Auth", b => + { + b.HasOne("LightlessSyncShared.Models.User", "PrimaryUser") + .WithMany() + .HasForeignKey("PrimaryUserUID") + .HasConstraintName("fk_auth_users_primary_user_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .HasConstraintName("fk_auth_users_user_uid"); + + b.Navigation("PrimaryUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => + { + b.HasOne("LightlessSyncShared.Models.User", "Uploader") + .WithMany() + .HasForeignKey("UploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_users_uploader_uid"); + + b.Navigation("Uploader"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataAllowance", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "AllowedGroup") + .WithMany() + .HasForeignKey("AllowedGroupGID") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_chara_data_allowance_groups_allowed_group_gid"); + + b.HasOne("LightlessSyncShared.Models.User", "AllowedUser") + .WithMany() + .HasForeignKey("AllowedUserUID") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_chara_data_allowance_users_allowed_user_uid"); + + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("AllowedIndividiuals") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_allowance_chara_data_parent_id_parent_uploader_u"); + + b.Navigation("AllowedGroup"); + + b.Navigation("AllowedUser"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFile", b => + { + b.HasOne("LightlessSyncShared.Models.FileCache", "FileCache") + .WithMany() + .HasForeignKey("FileCacheHash") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_chara_data_files_files_file_cache_hash"); + + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("Files") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_files_chara_data_parent_id_parent_uploader_uid"); + + b.Navigation("FileCache"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFileSwap", b => + { + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("FileSwaps") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_file_swaps_chara_data_parent_id_parent_uploader_"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataOriginalFile", b => + { + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("OriginalFiles") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_orig_files_chara_data_parent_id_parent_uploader_"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaDataPose", b => + { + b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") + .WithMany("Poses") + .HasForeignKey("ParentId", "ParentUploaderUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chara_data_poses_chara_data_parent_id_parent_uploader_uid"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.ClientPair", b => + { + b.HasOne("LightlessSyncShared.Models.User", "OtherUser") + .WithMany() + .HasForeignKey("OtherUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_client_pairs_users_other_user_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_client_pairs_users_user_uid"); + + b.Navigation("OtherUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.FileCache", b => + { + b.HasOne("LightlessSyncShared.Models.User", "Uploader") + .WithMany() + .HasForeignKey("UploaderUID") + .HasConstraintName("fk_file_caches_users_uploader_uid"); + + b.Navigation("Uploader"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.Group", b => + { + b.HasOne("LightlessSyncShared.Models.User", "Owner") + .WithMany() + .HasForeignKey("OwnerUID") + .HasConstraintName("fk_groups_users_owner_uid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupBan", b => + { + b.HasOne("LightlessSyncShared.Models.User", "BannedBy") + .WithMany() + .HasForeignKey("BannedByUID") + .HasConstraintName("fk_group_bans_users_banned_by_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "BannedUser") + .WithMany() + .HasForeignKey("BannedUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_bans_users_banned_user_uid"); + + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_bans_groups_group_gid"); + + b.Navigation("BannedBy"); + + b.Navigation("BannedUser"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPair", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pairs_groups_group_gid"); + + b.HasOne("LightlessSyncShared.Models.User", "GroupUser") + .WithMany() + .HasForeignKey("GroupUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pairs_users_group_user_uid"); + + b.Navigation("Group"); + + b.Navigation("GroupUser"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupPairPreferredPermission", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pair_preferred_permissions_groups_group_gid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_pair_preferred_permissions_users_user_uid"); + + b.Navigation("Group"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.GroupTempInvite", b => + { + b.HasOne("LightlessSyncShared.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupGID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_group_temp_invites_groups_group_gid"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.LodeStoneAuth", b => + { + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .HasConstraintName("fk_lodestone_auth_users_user_uid"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserDefaultPreferredPermission", b => + { + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_default_preferred_permissions_users_user_uid"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserPermissionSet", b => + { + b.HasOne("LightlessSyncShared.Models.User", "OtherUser") + .WithMany() + .HasForeignKey("OtherUserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_permission_sets_users_other_user_uid"); + + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_permission_sets_users_user_uid"); + + b.Navigation("OtherUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.UserProfileData", b => + { + b.HasOne("LightlessSyncShared.Models.User", "User") + .WithMany() + .HasForeignKey("UserUID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_profile_data_users_user_uid"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => + { + b.Navigation("AllowedIndividiuals"); + + b.Navigation("FileSwaps"); + + b.Navigation("Files"); + + b.Navigation("OriginalFiles"); + + b.Navigation("Poses"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs new file mode 100644 index 0000000..9d68973 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LightlessSyncServer.Migrations +{ + /// + public partial class AddBannedUid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "banned_uid", + table: "banned_users", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(10)", + oldNullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "banned_uid", + table: "banned_users", + type: "character varying(10)", + nullable: true, + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + } + } +} diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs index f5f0cdc..72bec03 100644 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs @@ -68,6 +68,10 @@ namespace LightlessSyncServer.Migrations .HasColumnType("text") .HasColumnName("reason"); + b.Property("BannedUid") + .HasColumnType("character varying(10)") + .HasColumnName("banned_uid"); + b.Property("Timestamp") .IsConcurrencyToken() .ValueGeneratedOnAddOrUpdate() diff --git a/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs b/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs index 25886e0..bc09e55 100644 --- a/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs +++ b/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs @@ -8,6 +8,7 @@ public class Banned [MaxLength(100)] public string CharacterIdentification { get; set; } public string Reason { get; set; } + public string BannedUid { get; set; } [Timestamp] public byte[] Timestamp { get; set; } } -- 2.49.1 From 3f76121e26e4f9704d9d6dc2d58893c208ceb9d9 Mon Sep 17 00:00:00 2001 From: defnotken Date: Thu, 4 Sep 2025 10:55:08 -0500 Subject: [PATCH 02/14] Unban work --- LightlessAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LightlessAPI b/LightlessAPI index 3a69c94..d9c0be5 160000 --- a/LightlessAPI +++ b/LightlessAPI @@ -1 +1 @@ -Subproject commit 3a69c94f7fb10a0cfc51c857b2194640fda48140 +Subproject commit d9c0be5da3a90411f333932a5a58ae1c7762af45 -- 2.49.1 From 7c81f880e11837216b7c423ed4e57fee9ee4e627 Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 11:24:33 -0500 Subject: [PATCH 03/14] Adding Auth to Unbans --- .../Discord/DiscordBotTest.cs | 2 +- .../Discord/MareModule.cs | 2 + .../Migrations/20250904154857_AddBannedUid.cs | 36 - ...> 20250905161830_AddBannedUid.Designer.cs} | 2 +- .../Migrations/20250905161830_AddBannedUid.cs | 736 +++++++++++ .../Migrations/MareDbContextModelSnapshot.cs | 1095 ----------------- 6 files changed, 740 insertions(+), 1133 deletions(-) delete mode 100644 LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs rename LightlessSyncServer/LightlessSyncShared/Migrations/{20250904154857_AddBannedUid.Designer.cs => 20250905161830_AddBannedUid.Designer.cs} (99%) create mode 100644 LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs delete mode 100644 LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs diff --git a/LightlessSyncServer/LightlessSyncServerTest/Discord/DiscordBotTest.cs b/LightlessSyncServer/LightlessSyncServerTest/Discord/DiscordBotTest.cs index d57ca55..a10b34e 100644 --- a/LightlessSyncServer/LightlessSyncServerTest/Discord/DiscordBotTest.cs +++ b/LightlessSyncServer/LightlessSyncServerTest/Discord/DiscordBotTest.cs @@ -1,5 +1,5 @@ using FluentAssertions; -using LightlessSyncServer.Discord; +using LightlessSyncServices.Discord; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index 7e1a036..aaaf4bc 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -152,6 +152,7 @@ public class LightlessModule : InteractionModuleBase try { using HttpClient c = new HttpClient(); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"), new { discordId }) .ConfigureAwait(false); @@ -192,6 +193,7 @@ public class LightlessModule : InteractionModuleBase try { using HttpClient c = new HttpClient(); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanUID"), new { uid }) .ConfigureAwait(false); diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs deleted file mode 100644 index 9d68973..0000000 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace LightlessSyncServer.Migrations -{ - /// - public partial class AddBannedUid : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "banned_uid", - table: "banned_users", - type: "text", - nullable: true, - oldClrType: typeof(string), - oldType: "character varying(10)", - oldNullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "banned_uid", - table: "banned_users", - type: "character varying(10)", - nullable: true, - oldClrType: typeof(string), - oldType: "text", - oldNullable: true); - } - } -} diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.Designer.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.Designer.cs similarity index 99% rename from LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.Designer.cs rename to LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.Designer.cs index 218efbe..840c97b 100644 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/20250904154857_AddBannedUid.Designer.cs +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace LightlessSyncServer.Migrations { [DbContext(typeof(LightlessDbContext))] - [Migration("20250904154857_AddBannedUid")] + [Migration("20250905161830_AddBannedUid")] partial class AddBannedUid { /// diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs new file mode 100644 index 0000000..a616022 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs @@ -0,0 +1,736 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LightlessSyncServer.Migrations +{ + /// + public partial class AddBannedUid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "banned_registrations", + columns: table => new + { + discord_id_or_lodestone_auth = table.Column(type: "character varying(100)", maxLength: 100, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_banned_registrations", x => x.discord_id_or_lodestone_auth); + }); + + migrationBuilder.CreateTable( + name: "banned_users", + columns: table => new + { + character_identification = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + reason = table.Column(type: "text", nullable: true), + banned_uid = table.Column(type: "text", nullable: true), + timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_banned_users", x => x.character_identification); + }); + + migrationBuilder.CreateTable( + name: "forbidden_upload_entries", + columns: table => new + { + hash = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + forbidden_by = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_forbidden_upload_entries", x => x.hash); + }); + + migrationBuilder.CreateTable( + name: "users", + columns: table => new + { + uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), + timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true), + is_moderator = table.Column(type: "boolean", nullable: false), + is_admin = table.Column(type: "boolean", nullable: false), + last_logged_in = table.Column(type: "timestamp with time zone", nullable: false), + alias = table.Column(type: "character varying(15)", maxLength: 15, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_users", x => x.uid); + }); + + migrationBuilder.CreateTable( + name: "auth", + columns: table => new + { + hashed_key = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + user_uid = table.Column(type: "character varying(10)", nullable: true), + mark_for_ban = table.Column(type: "boolean", nullable: false), + is_banned = table.Column(type: "boolean", nullable: false), + primary_user_uid = table.Column(type: "character varying(10)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_auth", x => x.hashed_key); + table.ForeignKey( + name: "fk_auth_users_primary_user_uid", + column: x => x.primary_user_uid, + principalTable: "users", + principalColumn: "uid"); + table.ForeignKey( + name: "fk_auth_users_user_uid", + column: x => x.user_uid, + principalTable: "users", + principalColumn: "uid"); + }); + + migrationBuilder.CreateTable( + name: "chara_data", + columns: table => new + { + id = table.Column(type: "text", nullable: false), + uploader_uid = table.Column(type: "character varying(10)", nullable: false), + created_date = table.Column(type: "timestamp with time zone", nullable: false), + updated_date = table.Column(type: "timestamp with time zone", nullable: false), + description = table.Column(type: "text", nullable: true), + access_type = table.Column(type: "integer", nullable: false), + share_type = table.Column(type: "integer", nullable: false), + expiry_date = table.Column(type: "timestamp with time zone", nullable: true), + glamourer_data = table.Column(type: "text", nullable: true), + customize_data = table.Column(type: "text", nullable: true), + manipulation_data = table.Column(type: "text", nullable: true), + download_count = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_chara_data", x => new { x.id, x.uploader_uid }); + table.ForeignKey( + name: "fk_chara_data_users_uploader_uid", + column: x => x.uploader_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "client_pairs", + columns: table => new + { + user_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), + other_user_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), + timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_client_pairs", x => new { x.user_uid, x.other_user_uid }); + table.ForeignKey( + name: "fk_client_pairs_users_other_user_uid", + column: x => x.other_user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_client_pairs_users_user_uid", + column: x => x.user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "file_caches", + columns: table => new + { + hash = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + uploader_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: true), + uploaded = table.Column(type: "boolean", nullable: false), + upload_date = table.Column(type: "timestamp with time zone", nullable: false), + timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true), + size = table.Column(type: "bigint", nullable: false), + raw_size = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_file_caches", x => x.hash); + table.ForeignKey( + name: "fk_file_caches_users_uploader_uid", + column: x => x.uploader_uid, + principalTable: "users", + principalColumn: "uid"); + }); + + migrationBuilder.CreateTable( + name: "groups", + columns: table => new + { + gid = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + owner_uid = table.Column(type: "character varying(10)", nullable: true), + alias = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + invites_enabled = table.Column(type: "boolean", nullable: false), + hashed_password = table.Column(type: "text", nullable: true), + prefer_disable_sounds = table.Column(type: "boolean", nullable: false), + prefer_disable_animations = table.Column(type: "boolean", nullable: false), + prefer_disable_vfx = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_groups", x => x.gid); + table.ForeignKey( + name: "fk_groups_users_owner_uid", + column: x => x.owner_uid, + principalTable: "users", + principalColumn: "uid"); + }); + + migrationBuilder.CreateTable( + name: "lodestone_auth", + columns: table => new + { + discord_id = table.Column(type: "numeric(20,0)", nullable: false), + hashed_lodestone_id = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + lodestone_auth_string = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + user_uid = table.Column(type: "character varying(10)", nullable: true), + started_at = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_lodestone_auth", x => x.discord_id); + table.ForeignKey( + name: "fk_lodestone_auth_users_user_uid", + column: x => x.user_uid, + principalTable: "users", + principalColumn: "uid"); + }); + + migrationBuilder.CreateTable( + name: "user_default_preferred_permissions", + columns: table => new + { + user_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), + disable_individual_animations = table.Column(type: "boolean", nullable: false), + disable_individual_sounds = table.Column(type: "boolean", nullable: false), + disable_individual_vfx = table.Column(type: "boolean", nullable: false), + disable_group_animations = table.Column(type: "boolean", nullable: false), + disable_group_sounds = table.Column(type: "boolean", nullable: false), + disable_group_vfx = table.Column(type: "boolean", nullable: false), + individual_is_sticky = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_user_default_preferred_permissions", x => x.user_uid); + table.ForeignKey( + name: "fk_user_default_preferred_permissions_users_user_uid", + column: x => x.user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_permission_sets", + columns: table => new + { + user_uid = table.Column(type: "character varying(10)", nullable: false), + other_user_uid = table.Column(type: "character varying(10)", nullable: false), + sticky = table.Column(type: "boolean", nullable: false), + is_paused = table.Column(type: "boolean", nullable: false), + disable_animations = table.Column(type: "boolean", nullable: false), + disable_vfx = table.Column(type: "boolean", nullable: false), + disable_sounds = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_user_permission_sets", x => new { x.user_uid, x.other_user_uid }); + table.ForeignKey( + name: "fk_user_permission_sets_users_other_user_uid", + column: x => x.other_user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_user_permission_sets_users_user_uid", + column: x => x.user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "user_profile_data", + columns: table => new + { + user_uid = table.Column(type: "character varying(10)", nullable: false), + base64profile_image = table.Column(type: "text", nullable: true), + flagged_for_report = table.Column(type: "boolean", nullable: false), + is_nsfw = table.Column(type: "boolean", nullable: false), + profile_disabled = table.Column(type: "boolean", nullable: false), + user_description = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_user_profile_data", x => x.user_uid); + table.ForeignKey( + name: "fk_user_profile_data_users_user_uid", + column: x => x.user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "chara_data_file_swaps", + columns: table => new + { + parent_id = table.Column(type: "text", nullable: false), + parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), + game_path = table.Column(type: "text", nullable: false), + file_path = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_chara_data_file_swaps", x => new { x.parent_id, x.parent_uploader_uid, x.game_path }); + table.ForeignKey( + name: "fk_chara_data_file_swaps_chara_data_parent_id_parent_uploader_", + columns: x => new { x.parent_id, x.parent_uploader_uid }, + principalTable: "chara_data", + principalColumns: new[] { "id", "uploader_uid" }, + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "chara_data_orig_files", + columns: table => new + { + parent_id = table.Column(type: "text", nullable: false), + parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), + game_path = table.Column(type: "text", nullable: false), + hash = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_chara_data_orig_files", x => new { x.parent_id, x.parent_uploader_uid, x.game_path }); + table.ForeignKey( + name: "fk_chara_data_orig_files_chara_data_parent_id_parent_uploader_", + columns: x => new { x.parent_id, x.parent_uploader_uid }, + principalTable: "chara_data", + principalColumns: new[] { "id", "uploader_uid" }, + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "chara_data_poses", + columns: table => new + { + id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + parent_id = table.Column(type: "text", nullable: false), + parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), + description = table.Column(type: "text", nullable: true), + pose_data = table.Column(type: "text", nullable: true), + world_data = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_chara_data_poses", x => new { x.parent_id, x.parent_uploader_uid, x.id }); + table.ForeignKey( + name: "fk_chara_data_poses_chara_data_parent_id_parent_uploader_uid", + columns: x => new { x.parent_id, x.parent_uploader_uid }, + principalTable: "chara_data", + principalColumns: new[] { "id", "uploader_uid" }, + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "chara_data_files", + columns: table => new + { + game_path = table.Column(type: "text", nullable: false), + parent_id = table.Column(type: "text", nullable: false), + parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), + file_cache_hash = table.Column(type: "character varying(40)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_chara_data_files", x => new { x.parent_id, x.parent_uploader_uid, x.game_path }); + table.ForeignKey( + name: "fk_chara_data_files_chara_data_parent_id_parent_uploader_uid", + columns: x => new { x.parent_id, x.parent_uploader_uid }, + principalTable: "chara_data", + principalColumns: new[] { "id", "uploader_uid" }, + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_chara_data_files_files_file_cache_hash", + column: x => x.file_cache_hash, + principalTable: "file_caches", + principalColumn: "hash", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "chara_data_allowance", + columns: table => new + { + id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + parent_id = table.Column(type: "text", nullable: false), + parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), + allowed_user_uid = table.Column(type: "character varying(10)", nullable: true), + allowed_group_gid = table.Column(type: "character varying(20)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_chara_data_allowance", x => new { x.parent_id, x.parent_uploader_uid, x.id }); + table.ForeignKey( + name: "fk_chara_data_allowance_chara_data_parent_id_parent_uploader_u", + columns: x => new { x.parent_id, x.parent_uploader_uid }, + principalTable: "chara_data", + principalColumns: new[] { "id", "uploader_uid" }, + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_chara_data_allowance_groups_allowed_group_gid", + column: x => x.allowed_group_gid, + principalTable: "groups", + principalColumn: "gid", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_chara_data_allowance_users_allowed_user_uid", + column: x => x.allowed_user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "group_bans", + columns: table => new + { + group_gid = table.Column(type: "character varying(20)", nullable: false), + banned_user_uid = table.Column(type: "character varying(10)", nullable: false), + banned_by_uid = table.Column(type: "character varying(10)", nullable: true), + banned_on = table.Column(type: "timestamp with time zone", nullable: false), + banned_reason = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_group_bans", x => new { x.group_gid, x.banned_user_uid }); + table.ForeignKey( + name: "fk_group_bans_groups_group_gid", + column: x => x.group_gid, + principalTable: "groups", + principalColumn: "gid", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_group_bans_users_banned_by_uid", + column: x => x.banned_by_uid, + principalTable: "users", + principalColumn: "uid"); + table.ForeignKey( + name: "fk_group_bans_users_banned_user_uid", + column: x => x.banned_user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "group_pair_preferred_permissions", + columns: table => new + { + group_gid = table.Column(type: "character varying(20)", nullable: false), + user_uid = table.Column(type: "character varying(10)", nullable: false), + is_paused = table.Column(type: "boolean", nullable: false), + disable_animations = table.Column(type: "boolean", nullable: false), + disable_sounds = table.Column(type: "boolean", nullable: false), + disable_vfx = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_group_pair_preferred_permissions", x => new { x.user_uid, x.group_gid }); + table.ForeignKey( + name: "fk_group_pair_preferred_permissions_groups_group_gid", + column: x => x.group_gid, + principalTable: "groups", + principalColumn: "gid", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_group_pair_preferred_permissions_users_user_uid", + column: x => x.user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "group_pairs", + columns: table => new + { + group_gid = table.Column(type: "character varying(20)", nullable: false), + group_user_uid = table.Column(type: "character varying(10)", nullable: false), + is_pinned = table.Column(type: "boolean", nullable: false), + is_moderator = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_group_pairs", x => new { x.group_gid, x.group_user_uid }); + table.ForeignKey( + name: "fk_group_pairs_groups_group_gid", + column: x => x.group_gid, + principalTable: "groups", + principalColumn: "gid", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_group_pairs_users_group_user_uid", + column: x => x.group_user_uid, + principalTable: "users", + principalColumn: "uid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "group_temp_invites", + columns: table => new + { + group_gid = table.Column(type: "character varying(20)", nullable: false), + invite = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + expiration_date = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_group_temp_invites", x => new { x.group_gid, x.invite }); + table.ForeignKey( + name: "fk_group_temp_invites_groups_group_gid", + column: x => x.group_gid, + principalTable: "groups", + principalColumn: "gid", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "ix_auth_primary_user_uid", + table: "auth", + column: "primary_user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_auth_user_uid", + table: "auth", + column: "user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_id", + table: "chara_data", + column: "id"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_uploader_uid", + table: "chara_data", + column: "uploader_uid"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_allowance_allowed_group_gid", + table: "chara_data_allowance", + column: "allowed_group_gid"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_allowance_allowed_user_uid", + table: "chara_data_allowance", + column: "allowed_user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_allowance_parent_id", + table: "chara_data_allowance", + column: "parent_id"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_file_swaps_parent_id", + table: "chara_data_file_swaps", + column: "parent_id"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_files_file_cache_hash", + table: "chara_data_files", + column: "file_cache_hash"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_files_parent_id", + table: "chara_data_files", + column: "parent_id"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_orig_files_parent_id", + table: "chara_data_orig_files", + column: "parent_id"); + + migrationBuilder.CreateIndex( + name: "ix_chara_data_poses_parent_id", + table: "chara_data_poses", + column: "parent_id"); + + migrationBuilder.CreateIndex( + name: "ix_client_pairs_other_user_uid", + table: "client_pairs", + column: "other_user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_client_pairs_user_uid", + table: "client_pairs", + column: "user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_file_caches_uploader_uid", + table: "file_caches", + column: "uploader_uid"); + + migrationBuilder.CreateIndex( + name: "ix_group_bans_banned_by_uid", + table: "group_bans", + column: "banned_by_uid"); + + migrationBuilder.CreateIndex( + name: "ix_group_bans_banned_user_uid", + table: "group_bans", + column: "banned_user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_group_bans_group_gid", + table: "group_bans", + column: "group_gid"); + + migrationBuilder.CreateIndex( + name: "ix_group_pair_preferred_permissions_group_gid", + table: "group_pair_preferred_permissions", + column: "group_gid"); + + migrationBuilder.CreateIndex( + name: "ix_group_pair_preferred_permissions_user_uid", + table: "group_pair_preferred_permissions", + column: "user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_group_pairs_group_gid", + table: "group_pairs", + column: "group_gid"); + + migrationBuilder.CreateIndex( + name: "ix_group_pairs_group_user_uid", + table: "group_pairs", + column: "group_user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_group_temp_invites_group_gid", + table: "group_temp_invites", + column: "group_gid"); + + migrationBuilder.CreateIndex( + name: "ix_group_temp_invites_invite", + table: "group_temp_invites", + column: "invite"); + + migrationBuilder.CreateIndex( + name: "ix_groups_owner_uid", + table: "groups", + column: "owner_uid"); + + migrationBuilder.CreateIndex( + name: "ix_lodestone_auth_user_uid", + table: "lodestone_auth", + column: "user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_user_default_preferred_permissions_user_uid", + table: "user_default_preferred_permissions", + column: "user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_user_permission_sets_other_user_uid", + table: "user_permission_sets", + column: "other_user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_user_permission_sets_user_uid", + table: "user_permission_sets", + column: "user_uid"); + + migrationBuilder.CreateIndex( + name: "ix_user_permission_sets_user_uid_other_user_uid_is_paused", + table: "user_permission_sets", + columns: new[] { "user_uid", "other_user_uid", "is_paused" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "auth"); + + migrationBuilder.DropTable( + name: "banned_registrations"); + + migrationBuilder.DropTable( + name: "banned_users"); + + migrationBuilder.DropTable( + name: "chara_data_allowance"); + + migrationBuilder.DropTable( + name: "chara_data_file_swaps"); + + migrationBuilder.DropTable( + name: "chara_data_files"); + + migrationBuilder.DropTable( + name: "chara_data_orig_files"); + + migrationBuilder.DropTable( + name: "chara_data_poses"); + + migrationBuilder.DropTable( + name: "client_pairs"); + + migrationBuilder.DropTable( + name: "forbidden_upload_entries"); + + migrationBuilder.DropTable( + name: "group_bans"); + + migrationBuilder.DropTable( + name: "group_pair_preferred_permissions"); + + migrationBuilder.DropTable( + name: "group_pairs"); + + migrationBuilder.DropTable( + name: "group_temp_invites"); + + migrationBuilder.DropTable( + name: "lodestone_auth"); + + migrationBuilder.DropTable( + name: "user_default_preferred_permissions"); + + migrationBuilder.DropTable( + name: "user_permission_sets"); + + migrationBuilder.DropTable( + name: "user_profile_data"); + + migrationBuilder.DropTable( + name: "file_caches"); + + migrationBuilder.DropTable( + name: "chara_data"); + + migrationBuilder.DropTable( + name: "groups"); + + migrationBuilder.DropTable( + name: "users"); + } + } +} diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs deleted file mode 100644 index 72bec03..0000000 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/MareDbContextModelSnapshot.cs +++ /dev/null @@ -1,1095 +0,0 @@ -// -using System; -using LightlessSyncShared.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace LightlessSyncServer.Migrations -{ - [DbContext(typeof(LightlessDbContext))] - partial class LightlessDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "9.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("LightlessSyncShared.Models.Auth", b => - { - b.Property("HashedKey") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("hashed_key"); - - b.Property("IsBanned") - .HasColumnType("boolean") - .HasColumnName("is_banned"); - - b.Property("MarkForBan") - .HasColumnType("boolean") - .HasColumnName("mark_for_ban"); - - b.Property("PrimaryUserUID") - .HasColumnType("character varying(10)") - .HasColumnName("primary_user_uid"); - - b.Property("UserUID") - .HasColumnType("character varying(10)") - .HasColumnName("user_uid"); - - b.HasKey("HashedKey") - .HasName("pk_auth"); - - b.HasIndex("PrimaryUserUID") - .HasDatabaseName("ix_auth_primary_user_uid"); - - b.HasIndex("UserUID") - .HasDatabaseName("ix_auth_user_uid"); - - b.ToTable("auth", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.Banned", b => - { - b.Property("CharacterIdentification") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("character_identification"); - - b.Property("Reason") - .HasColumnType("text") - .HasColumnName("reason"); - - b.Property("BannedUid") - .HasColumnType("character varying(10)") - .HasColumnName("banned_uid"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasColumnName("timestamp"); - - b.HasKey("CharacterIdentification") - .HasName("pk_banned_users"); - - b.ToTable("banned_users", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.BannedRegistrations", b => - { - b.Property("DiscordIdOrLodestoneAuth") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("discord_id_or_lodestone_auth"); - - b.HasKey("DiscordIdOrLodestoneAuth") - .HasName("pk_banned_registrations"); - - b.ToTable("banned_registrations", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => - { - b.Property("Id") - .HasColumnType("text") - .HasColumnName("id"); - - b.Property("UploaderUID") - .HasColumnType("character varying(10)") - .HasColumnName("uploader_uid"); - - b.Property("AccessType") - .HasColumnType("integer") - .HasColumnName("access_type"); - - b.Property("CreatedDate") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_date"); - - b.Property("CustomizeData") - .HasColumnType("text") - .HasColumnName("customize_data"); - - b.Property("Description") - .HasColumnType("text") - .HasColumnName("description"); - - b.Property("DownloadCount") - .HasColumnType("integer") - .HasColumnName("download_count"); - - b.Property("ExpiryDate") - .HasColumnType("timestamp with time zone") - .HasColumnName("expiry_date"); - - b.Property("GlamourerData") - .HasColumnType("text") - .HasColumnName("glamourer_data"); - - b.Property("ManipulationData") - .HasColumnType("text") - .HasColumnName("manipulation_data"); - - b.Property("ShareType") - .HasColumnType("integer") - .HasColumnName("share_type"); - - b.Property("UpdatedDate") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_date"); - - b.HasKey("Id", "UploaderUID") - .HasName("pk_chara_data"); - - b.HasIndex("Id") - .HasDatabaseName("ix_chara_data_id"); - - b.HasIndex("UploaderUID") - .HasDatabaseName("ix_chara_data_uploader_uid"); - - b.ToTable("chara_data", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataAllowance", b => - { - b.Property("ParentId") - .HasColumnType("text") - .HasColumnName("parent_id"); - - b.Property("ParentUploaderUID") - .HasColumnType("character varying(10)") - .HasColumnName("parent_uploader_uid"); - - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AllowedGroupGID") - .HasColumnType("character varying(20)") - .HasColumnName("allowed_group_gid"); - - b.Property("AllowedUserUID") - .HasColumnType("character varying(10)") - .HasColumnName("allowed_user_uid"); - - b.HasKey("ParentId", "ParentUploaderUID", "Id") - .HasName("pk_chara_data_allowance"); - - b.HasIndex("AllowedGroupGID") - .HasDatabaseName("ix_chara_data_allowance_allowed_group_gid"); - - b.HasIndex("AllowedUserUID") - .HasDatabaseName("ix_chara_data_allowance_allowed_user_uid"); - - b.HasIndex("ParentId") - .HasDatabaseName("ix_chara_data_allowance_parent_id"); - - b.ToTable("chara_data_allowance", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFile", b => - { - b.Property("ParentId") - .HasColumnType("text") - .HasColumnName("parent_id"); - - b.Property("ParentUploaderUID") - .HasColumnType("character varying(10)") - .HasColumnName("parent_uploader_uid"); - - b.Property("GamePath") - .HasColumnType("text") - .HasColumnName("game_path"); - - b.Property("FileCacheHash") - .HasColumnType("character varying(40)") - .HasColumnName("file_cache_hash"); - - b.HasKey("ParentId", "ParentUploaderUID", "GamePath") - .HasName("pk_chara_data_files"); - - b.HasIndex("FileCacheHash") - .HasDatabaseName("ix_chara_data_files_file_cache_hash"); - - b.HasIndex("ParentId") - .HasDatabaseName("ix_chara_data_files_parent_id"); - - b.ToTable("chara_data_files", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFileSwap", b => - { - b.Property("ParentId") - .HasColumnType("text") - .HasColumnName("parent_id"); - - b.Property("ParentUploaderUID") - .HasColumnType("character varying(10)") - .HasColumnName("parent_uploader_uid"); - - b.Property("GamePath") - .HasColumnType("text") - .HasColumnName("game_path"); - - b.Property("FilePath") - .HasColumnType("text") - .HasColumnName("file_path"); - - b.HasKey("ParentId", "ParentUploaderUID", "GamePath") - .HasName("pk_chara_data_file_swaps"); - - b.HasIndex("ParentId") - .HasDatabaseName("ix_chara_data_file_swaps_parent_id"); - - b.ToTable("chara_data_file_swaps", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataOriginalFile", b => - { - b.Property("ParentId") - .HasColumnType("text") - .HasColumnName("parent_id"); - - b.Property("ParentUploaderUID") - .HasColumnType("character varying(10)") - .HasColumnName("parent_uploader_uid"); - - b.Property("GamePath") - .HasColumnType("text") - .HasColumnName("game_path"); - - b.Property("Hash") - .HasColumnType("text") - .HasColumnName("hash"); - - b.HasKey("ParentId", "ParentUploaderUID", "GamePath") - .HasName("pk_chara_data_orig_files"); - - b.HasIndex("ParentId") - .HasDatabaseName("ix_chara_data_orig_files_parent_id"); - - b.ToTable("chara_data_orig_files", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataPose", b => - { - b.Property("ParentId") - .HasColumnType("text") - .HasColumnName("parent_id"); - - b.Property("ParentUploaderUID") - .HasColumnType("character varying(10)") - .HasColumnName("parent_uploader_uid"); - - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Description") - .HasColumnType("text") - .HasColumnName("description"); - - b.Property("PoseData") - .HasColumnType("text") - .HasColumnName("pose_data"); - - b.Property("WorldData") - .HasColumnType("text") - .HasColumnName("world_data"); - - b.HasKey("ParentId", "ParentUploaderUID", "Id") - .HasName("pk_chara_data_poses"); - - b.HasIndex("ParentId") - .HasDatabaseName("ix_chara_data_poses_parent_id"); - - b.ToTable("chara_data_poses", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.ClientPair", b => - { - b.Property("UserUID") - .HasMaxLength(10) - .HasColumnType("character varying(10)") - .HasColumnName("user_uid"); - - b.Property("OtherUserUID") - .HasMaxLength(10) - .HasColumnType("character varying(10)") - .HasColumnName("other_user_uid"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasColumnName("timestamp"); - - b.HasKey("UserUID", "OtherUserUID") - .HasName("pk_client_pairs"); - - b.HasIndex("OtherUserUID") - .HasDatabaseName("ix_client_pairs_other_user_uid"); - - b.HasIndex("UserUID") - .HasDatabaseName("ix_client_pairs_user_uid"); - - b.ToTable("client_pairs", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.FileCache", b => - { - b.Property("Hash") - .HasMaxLength(40) - .HasColumnType("character varying(40)") - .HasColumnName("hash"); - - b.Property("RawSize") - .HasColumnType("bigint") - .HasColumnName("raw_size"); - - b.Property("Size") - .HasColumnType("bigint") - .HasColumnName("size"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasColumnName("timestamp"); - - b.Property("UploadDate") - .HasColumnType("timestamp with time zone") - .HasColumnName("upload_date"); - - b.Property("Uploaded") - .HasColumnType("boolean") - .HasColumnName("uploaded"); - - b.Property("UploaderUID") - .HasMaxLength(10) - .HasColumnType("character varying(10)") - .HasColumnName("uploader_uid"); - - b.HasKey("Hash") - .HasName("pk_file_caches"); - - b.HasIndex("UploaderUID") - .HasDatabaseName("ix_file_caches_uploader_uid"); - - b.ToTable("file_caches", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.ForbiddenUploadEntry", b => - { - b.Property("Hash") - .HasMaxLength(40) - .HasColumnType("character varying(40)") - .HasColumnName("hash"); - - b.Property("ForbiddenBy") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("forbidden_by"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasColumnName("timestamp"); - - b.HasKey("Hash") - .HasName("pk_forbidden_upload_entries"); - - b.ToTable("forbidden_upload_entries", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.Group", b => - { - b.Property("GID") - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasColumnName("gid"); - - b.Property("Alias") - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasColumnName("alias"); - - b.Property("HashedPassword") - .HasColumnType("text") - .HasColumnName("hashed_password"); - - b.Property("InvitesEnabled") - .HasColumnType("boolean") - .HasColumnName("invites_enabled"); - - b.Property("OwnerUID") - .HasColumnType("character varying(10)") - .HasColumnName("owner_uid"); - - b.Property("PreferDisableAnimations") - .HasColumnType("boolean") - .HasColumnName("prefer_disable_animations"); - - b.Property("PreferDisableSounds") - .HasColumnType("boolean") - .HasColumnName("prefer_disable_sounds"); - - b.Property("PreferDisableVFX") - .HasColumnType("boolean") - .HasColumnName("prefer_disable_vfx"); - - b.HasKey("GID") - .HasName("pk_groups"); - - b.HasIndex("OwnerUID") - .HasDatabaseName("ix_groups_owner_uid"); - - b.ToTable("groups", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupBan", b => - { - b.Property("GroupGID") - .HasColumnType("character varying(20)") - .HasColumnName("group_gid"); - - b.Property("BannedUserUID") - .HasColumnType("character varying(10)") - .HasColumnName("banned_user_uid"); - - b.Property("BannedByUID") - .HasColumnType("character varying(10)") - .HasColumnName("banned_by_uid"); - - b.Property("BannedOn") - .HasColumnType("timestamp with time zone") - .HasColumnName("banned_on"); - - b.Property("BannedReason") - .HasColumnType("text") - .HasColumnName("banned_reason"); - - b.HasKey("GroupGID", "BannedUserUID") - .HasName("pk_group_bans"); - - b.HasIndex("BannedByUID") - .HasDatabaseName("ix_group_bans_banned_by_uid"); - - b.HasIndex("BannedUserUID") - .HasDatabaseName("ix_group_bans_banned_user_uid"); - - b.HasIndex("GroupGID") - .HasDatabaseName("ix_group_bans_group_gid"); - - b.ToTable("group_bans", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupPair", b => - { - b.Property("GroupGID") - .HasColumnType("character varying(20)") - .HasColumnName("group_gid"); - - b.Property("GroupUserUID") - .HasColumnType("character varying(10)") - .HasColumnName("group_user_uid"); - - b.Property("IsModerator") - .HasColumnType("boolean") - .HasColumnName("is_moderator"); - - b.Property("IsPinned") - .HasColumnType("boolean") - .HasColumnName("is_pinned"); - - b.HasKey("GroupGID", "GroupUserUID") - .HasName("pk_group_pairs"); - - b.HasIndex("GroupGID") - .HasDatabaseName("ix_group_pairs_group_gid"); - - b.HasIndex("GroupUserUID") - .HasDatabaseName("ix_group_pairs_group_user_uid"); - - b.ToTable("group_pairs", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupPairPreferredPermission", b => - { - b.Property("UserUID") - .HasColumnType("character varying(10)") - .HasColumnName("user_uid"); - - b.Property("GroupGID") - .HasColumnType("character varying(20)") - .HasColumnName("group_gid"); - - b.Property("DisableAnimations") - .HasColumnType("boolean") - .HasColumnName("disable_animations"); - - b.Property("DisableSounds") - .HasColumnType("boolean") - .HasColumnName("disable_sounds"); - - b.Property("DisableVFX") - .HasColumnType("boolean") - .HasColumnName("disable_vfx"); - - b.Property("IsPaused") - .HasColumnType("boolean") - .HasColumnName("is_paused"); - - b.HasKey("UserUID", "GroupGID") - .HasName("pk_group_pair_preferred_permissions"); - - b.HasIndex("GroupGID") - .HasDatabaseName("ix_group_pair_preferred_permissions_group_gid"); - - b.HasIndex("UserUID") - .HasDatabaseName("ix_group_pair_preferred_permissions_user_uid"); - - b.ToTable("group_pair_preferred_permissions", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupTempInvite", b => - { - b.Property("GroupGID") - .HasColumnType("character varying(20)") - .HasColumnName("group_gid"); - - b.Property("Invite") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("invite"); - - b.Property("ExpirationDate") - .HasColumnType("timestamp with time zone") - .HasColumnName("expiration_date"); - - b.HasKey("GroupGID", "Invite") - .HasName("pk_group_temp_invites"); - - b.HasIndex("GroupGID") - .HasDatabaseName("ix_group_temp_invites_group_gid"); - - b.HasIndex("Invite") - .HasDatabaseName("ix_group_temp_invites_invite"); - - b.ToTable("group_temp_invites", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.LodeStoneAuth", b => - { - b.Property("DiscordId") - .ValueGeneratedOnAdd() - .HasColumnType("numeric(20,0)") - .HasColumnName("discord_id"); - - b.Property("HashedLodestoneId") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("hashed_lodestone_id"); - - b.Property("LodestoneAuthString") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("lodestone_auth_string"); - - b.Property("StartedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("started_at"); - - b.Property("UserUID") - .HasColumnType("character varying(10)") - .HasColumnName("user_uid"); - - b.HasKey("DiscordId") - .HasName("pk_lodestone_auth"); - - b.HasIndex("UserUID") - .HasDatabaseName("ix_lodestone_auth_user_uid"); - - b.ToTable("lodestone_auth", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.User", b => - { - b.Property("UID") - .HasMaxLength(10) - .HasColumnType("character varying(10)") - .HasColumnName("uid"); - - b.Property("Alias") - .HasMaxLength(15) - .HasColumnType("character varying(15)") - .HasColumnName("alias"); - - b.Property("IsAdmin") - .HasColumnType("boolean") - .HasColumnName("is_admin"); - - b.Property("IsModerator") - .HasColumnType("boolean") - .HasColumnName("is_moderator"); - - b.Property("LastLoggedIn") - .HasColumnType("timestamp with time zone") - .HasColumnName("last_logged_in"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("bytea") - .HasColumnName("timestamp"); - - b.HasKey("UID") - .HasName("pk_users"); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.UserDefaultPreferredPermission", b => - { - b.Property("UserUID") - .HasMaxLength(10) - .HasColumnType("character varying(10)") - .HasColumnName("user_uid"); - - b.Property("DisableGroupAnimations") - .HasColumnType("boolean") - .HasColumnName("disable_group_animations"); - - b.Property("DisableGroupSounds") - .HasColumnType("boolean") - .HasColumnName("disable_group_sounds"); - - b.Property("DisableGroupVFX") - .HasColumnType("boolean") - .HasColumnName("disable_group_vfx"); - - b.Property("DisableIndividualAnimations") - .HasColumnType("boolean") - .HasColumnName("disable_individual_animations"); - - b.Property("DisableIndividualSounds") - .HasColumnType("boolean") - .HasColumnName("disable_individual_sounds"); - - b.Property("DisableIndividualVFX") - .HasColumnType("boolean") - .HasColumnName("disable_individual_vfx"); - - b.Property("IndividualIsSticky") - .HasColumnType("boolean") - .HasColumnName("individual_is_sticky"); - - b.HasKey("UserUID") - .HasName("pk_user_default_preferred_permissions"); - - b.HasIndex("UserUID") - .HasDatabaseName("ix_user_default_preferred_permissions_user_uid"); - - b.ToTable("user_default_preferred_permissions", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.UserPermissionSet", b => - { - b.Property("UserUID") - .HasColumnType("character varying(10)") - .HasColumnName("user_uid"); - - b.Property("OtherUserUID") - .HasColumnType("character varying(10)") - .HasColumnName("other_user_uid"); - - b.Property("DisableAnimations") - .HasColumnType("boolean") - .HasColumnName("disable_animations"); - - b.Property("DisableSounds") - .HasColumnType("boolean") - .HasColumnName("disable_sounds"); - - b.Property("DisableVFX") - .HasColumnType("boolean") - .HasColumnName("disable_vfx"); - - b.Property("IsPaused") - .HasColumnType("boolean") - .HasColumnName("is_paused"); - - b.Property("Sticky") - .HasColumnType("boolean") - .HasColumnName("sticky"); - - b.HasKey("UserUID", "OtherUserUID") - .HasName("pk_user_permission_sets"); - - b.HasIndex("OtherUserUID") - .HasDatabaseName("ix_user_permission_sets_other_user_uid"); - - b.HasIndex("UserUID") - .HasDatabaseName("ix_user_permission_sets_user_uid"); - - b.HasIndex("UserUID", "OtherUserUID", "IsPaused") - .HasDatabaseName("ix_user_permission_sets_user_uid_other_user_uid_is_paused"); - - b.ToTable("user_permission_sets", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.UserProfileData", b => - { - b.Property("UserUID") - .HasColumnType("character varying(10)") - .HasColumnName("user_uid"); - - b.Property("Base64ProfileImage") - .HasColumnType("text") - .HasColumnName("base64profile_image"); - - b.Property("FlaggedForReport") - .HasColumnType("boolean") - .HasColumnName("flagged_for_report"); - - b.Property("IsNSFW") - .HasColumnType("boolean") - .HasColumnName("is_nsfw"); - - b.Property("ProfileDisabled") - .HasColumnType("boolean") - .HasColumnName("profile_disabled"); - - b.Property("UserDescription") - .HasColumnType("text") - .HasColumnName("user_description"); - - b.HasKey("UserUID") - .HasName("pk_user_profile_data"); - - b.ToTable("user_profile_data", (string)null); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.Auth", b => - { - b.HasOne("LightlessSyncShared.Models.User", "PrimaryUser") - .WithMany() - .HasForeignKey("PrimaryUserUID") - .HasConstraintName("fk_auth_users_primary_user_uid"); - - b.HasOne("LightlessSyncShared.Models.User", "User") - .WithMany() - .HasForeignKey("UserUID") - .HasConstraintName("fk_auth_users_user_uid"); - - b.Navigation("PrimaryUser"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => - { - b.HasOne("LightlessSyncShared.Models.User", "Uploader") - .WithMany() - .HasForeignKey("UploaderUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_chara_data_users_uploader_uid"); - - b.Navigation("Uploader"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataAllowance", b => - { - b.HasOne("LightlessSyncShared.Models.Group", "AllowedGroup") - .WithMany() - .HasForeignKey("AllowedGroupGID") - .OnDelete(DeleteBehavior.Cascade) - .HasConstraintName("fk_chara_data_allowance_groups_allowed_group_gid"); - - b.HasOne("LightlessSyncShared.Models.User", "AllowedUser") - .WithMany() - .HasForeignKey("AllowedUserUID") - .OnDelete(DeleteBehavior.Cascade) - .HasConstraintName("fk_chara_data_allowance_users_allowed_user_uid"); - - b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") - .WithMany("AllowedIndividiuals") - .HasForeignKey("ParentId", "ParentUploaderUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_chara_data_allowance_chara_data_parent_id_parent_uploader_u"); - - b.Navigation("AllowedGroup"); - - b.Navigation("AllowedUser"); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFile", b => - { - b.HasOne("LightlessSyncShared.Models.FileCache", "FileCache") - .WithMany() - .HasForeignKey("FileCacheHash") - .OnDelete(DeleteBehavior.Cascade) - .HasConstraintName("fk_chara_data_files_files_file_cache_hash"); - - b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") - .WithMany("Files") - .HasForeignKey("ParentId", "ParentUploaderUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_chara_data_files_chara_data_parent_id_parent_uploader_uid"); - - b.Navigation("FileCache"); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataFileSwap", b => - { - b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") - .WithMany("FileSwaps") - .HasForeignKey("ParentId", "ParentUploaderUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_chara_data_file_swaps_chara_data_parent_id_parent_uploader_"); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataOriginalFile", b => - { - b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") - .WithMany("OriginalFiles") - .HasForeignKey("ParentId", "ParentUploaderUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_chara_data_orig_files_chara_data_parent_id_parent_uploader_"); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaDataPose", b => - { - b.HasOne("LightlessSyncShared.Models.CharaData", "Parent") - .WithMany("Poses") - .HasForeignKey("ParentId", "ParentUploaderUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_chara_data_poses_chara_data_parent_id_parent_uploader_uid"); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.ClientPair", b => - { - b.HasOne("LightlessSyncShared.Models.User", "OtherUser") - .WithMany() - .HasForeignKey("OtherUserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_client_pairs_users_other_user_uid"); - - b.HasOne("LightlessSyncShared.Models.User", "User") - .WithMany() - .HasForeignKey("UserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_client_pairs_users_user_uid"); - - b.Navigation("OtherUser"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.FileCache", b => - { - b.HasOne("LightlessSyncShared.Models.User", "Uploader") - .WithMany() - .HasForeignKey("UploaderUID") - .HasConstraintName("fk_file_caches_users_uploader_uid"); - - b.Navigation("Uploader"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.Group", b => - { - b.HasOne("LightlessSyncShared.Models.User", "Owner") - .WithMany() - .HasForeignKey("OwnerUID") - .HasConstraintName("fk_groups_users_owner_uid"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupBan", b => - { - b.HasOne("LightlessSyncShared.Models.User", "BannedBy") - .WithMany() - .HasForeignKey("BannedByUID") - .HasConstraintName("fk_group_bans_users_banned_by_uid"); - - b.HasOne("LightlessSyncShared.Models.User", "BannedUser") - .WithMany() - .HasForeignKey("BannedUserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_group_bans_users_banned_user_uid"); - - b.HasOne("LightlessSyncShared.Models.Group", "Group") - .WithMany() - .HasForeignKey("GroupGID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_group_bans_groups_group_gid"); - - b.Navigation("BannedBy"); - - b.Navigation("BannedUser"); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupPair", b => - { - b.HasOne("LightlessSyncShared.Models.Group", "Group") - .WithMany() - .HasForeignKey("GroupGID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_group_pairs_groups_group_gid"); - - b.HasOne("LightlessSyncShared.Models.User", "GroupUser") - .WithMany() - .HasForeignKey("GroupUserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_group_pairs_users_group_user_uid"); - - b.Navigation("Group"); - - b.Navigation("GroupUser"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupPairPreferredPermission", b => - { - b.HasOne("LightlessSyncShared.Models.Group", "Group") - .WithMany() - .HasForeignKey("GroupGID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_group_pair_preferred_permissions_groups_group_gid"); - - b.HasOne("LightlessSyncShared.Models.User", "User") - .WithMany() - .HasForeignKey("UserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_group_pair_preferred_permissions_users_user_uid"); - - b.Navigation("Group"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.GroupTempInvite", b => - { - b.HasOne("LightlessSyncShared.Models.Group", "Group") - .WithMany() - .HasForeignKey("GroupGID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_group_temp_invites_groups_group_gid"); - - b.Navigation("Group"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.LodeStoneAuth", b => - { - b.HasOne("LightlessSyncShared.Models.User", "User") - .WithMany() - .HasForeignKey("UserUID") - .HasConstraintName("fk_lodestone_auth_users_user_uid"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.UserDefaultPreferredPermission", b => - { - b.HasOne("LightlessSyncShared.Models.User", "User") - .WithMany() - .HasForeignKey("UserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_default_preferred_permissions_users_user_uid"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.UserPermissionSet", b => - { - b.HasOne("LightlessSyncShared.Models.User", "OtherUser") - .WithMany() - .HasForeignKey("OtherUserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_permission_sets_users_other_user_uid"); - - b.HasOne("LightlessSyncShared.Models.User", "User") - .WithMany() - .HasForeignKey("UserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_permission_sets_users_user_uid"); - - b.Navigation("OtherUser"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.UserProfileData", b => - { - b.HasOne("LightlessSyncShared.Models.User", "User") - .WithMany() - .HasForeignKey("UserUID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_profile_data_users_user_uid"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LightlessSyncShared.Models.CharaData", b => - { - b.Navigation("AllowedIndividiuals"); - - b.Navigation("FileSwaps"); - - b.Navigation("Files"); - - b.Navigation("OriginalFiles"); - - b.Navigation("Poses"); - }); -#pragma warning restore 612, 618 - } - } -} -- 2.49.1 From b5aa817d0b67b6bd9f28d6450d251c94975edc4b Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 13:27:09 -0500 Subject: [PATCH 04/14] Ban and unban work --- .../Controllers/UserController.cs | 18 ++++++++ .../Discord/MareModule.cs | 42 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs index df981a8..5d11e47 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs @@ -17,6 +17,24 @@ public class UserController : Controller LightlessDbContextFactory = lightlessDbContext; } + [Authorize(Policy = "Internal")] + [HttpPost(LightlessAuth.Ban_Uid)] + public async Task MarkForBanUid(string uid) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Banning user with UID {UID}", uid); + + //Mark User as banned, and not marked for ban + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); + if (auth != null) + { + auth.MarkForBan = true; + } + + await dbContext.SaveChangesAsync(); + } + [Authorize(Policy = "Internal")] [HttpPost(LightlessAuth.User_Unban_Uid)] public async Task UnBanUserByUid(string uid) diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index aaaf4bc..100efcc 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -224,6 +224,48 @@ public class LightlessModule : InteractionModuleBase await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); } } + + [SlashCommand("markUidforBan", "ADMIN ONLY: ban a user by their uid")] + public async Task MarkUidForBan([Summary("uid", "uid to ban")] string uid) + { + _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", + Context.Interaction.User.Id, nameof(MarkUidForBan), + string.Join(",", new[] { $"{nameof(uid)}:{uid}" })); + try + { + using HttpClient c = new HttpClient(); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); + await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue + (nameof(ServicesConfiguration.MainServerAddress)), "/user/ban"), new { uid }) + .ConfigureAwait(false); + var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); + if (discordChannelForMessages != null) + { + var discordChannel = await Context.Guild.GetChannelAsync(discordChannelForMessages.Value).ConfigureAwait(false) as IMessageChannel; + if (discordChannel != null) + { + var embedColor = Color.Blue; + + EmbedBuilder eb = new(); + eb.WithTitle("Ban Alert!"); + eb.WithColor(embedColor); + eb.WithDescription(uid + " has been marked for ban"); + + await discordChannel.SendMessageAsync(embed: eb.Build()).ConfigureAwait(false); + } + } + + await RespondAsync("Message sent", ephemeral: true).ConfigureAwait(false); + } + catch (Exception ex) + { + EmbedBuilder eb = new(); + eb.WithTitle("An error occured"); + eb.WithDescription("Please report this: " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine); + await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); + } + } + public async Task HandleUserAdd(string desiredUid, ulong discordUserId) { var embed = new EmbedBuilder(); -- 2.49.1 From 232b3d535c9fb1770450d6c174ff5f41aee375df Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 13:50:02 -0500 Subject: [PATCH 05/14] submodule --- LightlessAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LightlessAPI b/LightlessAPI index d9c0be5..4918a2c 160000 --- a/LightlessAPI +++ b/LightlessAPI @@ -1 +1 @@ -Subproject commit d9c0be5da3a90411f333932a5a58ae1c7762af45 +Subproject commit 4918a2c4e321a79c8320e1b31aec36ddceacbb45 -- 2.49.1 From b700f58d88cef5d06fd29c9590e394da267292ad Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 14:04:11 -0500 Subject: [PATCH 06/14] Lets try this --- .../LightlessSyncShared.csproj | 4 - .../Migrations/20250905161830_AddBannedUid.cs | 736 ------------------ ...> 20250905190334_AddBannedUid.Designer.cs} | 2 +- .../Migrations/20250905190334_AddBannedUid.cs | 22 + .../LightlessDbContextModelSnapshot.cs | 0 5 files changed, 23 insertions(+), 741 deletions(-) delete mode 100644 LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs rename LightlessSyncServer/LightlessSyncShared/Migrations/{20250905161830_AddBannedUid.Designer.cs => 20250905190334_AddBannedUid.Designer.cs} (99%) create mode 100644 LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.cs rename LightlessSyncServer/LightlessSyncShared/{LightlessSyncServer => }/Migrations/LightlessDbContextModelSnapshot.cs (100%) diff --git a/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj b/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj index b5b7383..8cc310e 100644 --- a/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj +++ b/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj @@ -54,8 +54,4 @@ - - - - diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs deleted file mode 100644 index a616022..0000000 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.cs +++ /dev/null @@ -1,736 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace LightlessSyncServer.Migrations -{ - /// - public partial class AddBannedUid : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "banned_registrations", - columns: table => new - { - discord_id_or_lodestone_auth = table.Column(type: "character varying(100)", maxLength: 100, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_banned_registrations", x => x.discord_id_or_lodestone_auth); - }); - - migrationBuilder.CreateTable( - name: "banned_users", - columns: table => new - { - character_identification = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - reason = table.Column(type: "text", nullable: true), - banned_uid = table.Column(type: "text", nullable: true), - timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_banned_users", x => x.character_identification); - }); - - migrationBuilder.CreateTable( - name: "forbidden_upload_entries", - columns: table => new - { - hash = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), - forbidden_by = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_forbidden_upload_entries", x => x.hash); - }); - - migrationBuilder.CreateTable( - name: "users", - columns: table => new - { - uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), - timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true), - is_moderator = table.Column(type: "boolean", nullable: false), - is_admin = table.Column(type: "boolean", nullable: false), - last_logged_in = table.Column(type: "timestamp with time zone", nullable: false), - alias = table.Column(type: "character varying(15)", maxLength: 15, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_users", x => x.uid); - }); - - migrationBuilder.CreateTable( - name: "auth", - columns: table => new - { - hashed_key = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - user_uid = table.Column(type: "character varying(10)", nullable: true), - mark_for_ban = table.Column(type: "boolean", nullable: false), - is_banned = table.Column(type: "boolean", nullable: false), - primary_user_uid = table.Column(type: "character varying(10)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_auth", x => x.hashed_key); - table.ForeignKey( - name: "fk_auth_users_primary_user_uid", - column: x => x.primary_user_uid, - principalTable: "users", - principalColumn: "uid"); - table.ForeignKey( - name: "fk_auth_users_user_uid", - column: x => x.user_uid, - principalTable: "users", - principalColumn: "uid"); - }); - - migrationBuilder.CreateTable( - name: "chara_data", - columns: table => new - { - id = table.Column(type: "text", nullable: false), - uploader_uid = table.Column(type: "character varying(10)", nullable: false), - created_date = table.Column(type: "timestamp with time zone", nullable: false), - updated_date = table.Column(type: "timestamp with time zone", nullable: false), - description = table.Column(type: "text", nullable: true), - access_type = table.Column(type: "integer", nullable: false), - share_type = table.Column(type: "integer", nullable: false), - expiry_date = table.Column(type: "timestamp with time zone", nullable: true), - glamourer_data = table.Column(type: "text", nullable: true), - customize_data = table.Column(type: "text", nullable: true), - manipulation_data = table.Column(type: "text", nullable: true), - download_count = table.Column(type: "integer", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_chara_data", x => new { x.id, x.uploader_uid }); - table.ForeignKey( - name: "fk_chara_data_users_uploader_uid", - column: x => x.uploader_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "client_pairs", - columns: table => new - { - user_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), - other_user_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), - timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_client_pairs", x => new { x.user_uid, x.other_user_uid }); - table.ForeignKey( - name: "fk_client_pairs_users_other_user_uid", - column: x => x.other_user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_client_pairs_users_user_uid", - column: x => x.user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "file_caches", - columns: table => new - { - hash = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), - uploader_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: true), - uploaded = table.Column(type: "boolean", nullable: false), - upload_date = table.Column(type: "timestamp with time zone", nullable: false), - timestamp = table.Column(type: "bytea", rowVersion: true, nullable: true), - size = table.Column(type: "bigint", nullable: false), - raw_size = table.Column(type: "bigint", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_file_caches", x => x.hash); - table.ForeignKey( - name: "fk_file_caches_users_uploader_uid", - column: x => x.uploader_uid, - principalTable: "users", - principalColumn: "uid"); - }); - - migrationBuilder.CreateTable( - name: "groups", - columns: table => new - { - gid = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), - owner_uid = table.Column(type: "character varying(10)", nullable: true), - alias = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), - invites_enabled = table.Column(type: "boolean", nullable: false), - hashed_password = table.Column(type: "text", nullable: true), - prefer_disable_sounds = table.Column(type: "boolean", nullable: false), - prefer_disable_animations = table.Column(type: "boolean", nullable: false), - prefer_disable_vfx = table.Column(type: "boolean", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_groups", x => x.gid); - table.ForeignKey( - name: "fk_groups_users_owner_uid", - column: x => x.owner_uid, - principalTable: "users", - principalColumn: "uid"); - }); - - migrationBuilder.CreateTable( - name: "lodestone_auth", - columns: table => new - { - discord_id = table.Column(type: "numeric(20,0)", nullable: false), - hashed_lodestone_id = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - lodestone_auth_string = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - user_uid = table.Column(type: "character varying(10)", nullable: true), - started_at = table.Column(type: "timestamp with time zone", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_lodestone_auth", x => x.discord_id); - table.ForeignKey( - name: "fk_lodestone_auth_users_user_uid", - column: x => x.user_uid, - principalTable: "users", - principalColumn: "uid"); - }); - - migrationBuilder.CreateTable( - name: "user_default_preferred_permissions", - columns: table => new - { - user_uid = table.Column(type: "character varying(10)", maxLength: 10, nullable: false), - disable_individual_animations = table.Column(type: "boolean", nullable: false), - disable_individual_sounds = table.Column(type: "boolean", nullable: false), - disable_individual_vfx = table.Column(type: "boolean", nullable: false), - disable_group_animations = table.Column(type: "boolean", nullable: false), - disable_group_sounds = table.Column(type: "boolean", nullable: false), - disable_group_vfx = table.Column(type: "boolean", nullable: false), - individual_is_sticky = table.Column(type: "boolean", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_user_default_preferred_permissions", x => x.user_uid); - table.ForeignKey( - name: "fk_user_default_preferred_permissions_users_user_uid", - column: x => x.user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_permission_sets", - columns: table => new - { - user_uid = table.Column(type: "character varying(10)", nullable: false), - other_user_uid = table.Column(type: "character varying(10)", nullable: false), - sticky = table.Column(type: "boolean", nullable: false), - is_paused = table.Column(type: "boolean", nullable: false), - disable_animations = table.Column(type: "boolean", nullable: false), - disable_vfx = table.Column(type: "boolean", nullable: false), - disable_sounds = table.Column(type: "boolean", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_user_permission_sets", x => new { x.user_uid, x.other_user_uid }); - table.ForeignKey( - name: "fk_user_permission_sets_users_other_user_uid", - column: x => x.other_user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_user_permission_sets_users_user_uid", - column: x => x.user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "user_profile_data", - columns: table => new - { - user_uid = table.Column(type: "character varying(10)", nullable: false), - base64profile_image = table.Column(type: "text", nullable: true), - flagged_for_report = table.Column(type: "boolean", nullable: false), - is_nsfw = table.Column(type: "boolean", nullable: false), - profile_disabled = table.Column(type: "boolean", nullable: false), - user_description = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_user_profile_data", x => x.user_uid); - table.ForeignKey( - name: "fk_user_profile_data_users_user_uid", - column: x => x.user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "chara_data_file_swaps", - columns: table => new - { - parent_id = table.Column(type: "text", nullable: false), - parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), - game_path = table.Column(type: "text", nullable: false), - file_path = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_chara_data_file_swaps", x => new { x.parent_id, x.parent_uploader_uid, x.game_path }); - table.ForeignKey( - name: "fk_chara_data_file_swaps_chara_data_parent_id_parent_uploader_", - columns: x => new { x.parent_id, x.parent_uploader_uid }, - principalTable: "chara_data", - principalColumns: new[] { "id", "uploader_uid" }, - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "chara_data_orig_files", - columns: table => new - { - parent_id = table.Column(type: "text", nullable: false), - parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), - game_path = table.Column(type: "text", nullable: false), - hash = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_chara_data_orig_files", x => new { x.parent_id, x.parent_uploader_uid, x.game_path }); - table.ForeignKey( - name: "fk_chara_data_orig_files_chara_data_parent_id_parent_uploader_", - columns: x => new { x.parent_id, x.parent_uploader_uid }, - principalTable: "chara_data", - principalColumns: new[] { "id", "uploader_uid" }, - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "chara_data_poses", - columns: table => new - { - id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - parent_id = table.Column(type: "text", nullable: false), - parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), - description = table.Column(type: "text", nullable: true), - pose_data = table.Column(type: "text", nullable: true), - world_data = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_chara_data_poses", x => new { x.parent_id, x.parent_uploader_uid, x.id }); - table.ForeignKey( - name: "fk_chara_data_poses_chara_data_parent_id_parent_uploader_uid", - columns: x => new { x.parent_id, x.parent_uploader_uid }, - principalTable: "chara_data", - principalColumns: new[] { "id", "uploader_uid" }, - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "chara_data_files", - columns: table => new - { - game_path = table.Column(type: "text", nullable: false), - parent_id = table.Column(type: "text", nullable: false), - parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), - file_cache_hash = table.Column(type: "character varying(40)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_chara_data_files", x => new { x.parent_id, x.parent_uploader_uid, x.game_path }); - table.ForeignKey( - name: "fk_chara_data_files_chara_data_parent_id_parent_uploader_uid", - columns: x => new { x.parent_id, x.parent_uploader_uid }, - principalTable: "chara_data", - principalColumns: new[] { "id", "uploader_uid" }, - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_chara_data_files_files_file_cache_hash", - column: x => x.file_cache_hash, - principalTable: "file_caches", - principalColumn: "hash", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "chara_data_allowance", - columns: table => new - { - id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - parent_id = table.Column(type: "text", nullable: false), - parent_uploader_uid = table.Column(type: "character varying(10)", nullable: false), - allowed_user_uid = table.Column(type: "character varying(10)", nullable: true), - allowed_group_gid = table.Column(type: "character varying(20)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_chara_data_allowance", x => new { x.parent_id, x.parent_uploader_uid, x.id }); - table.ForeignKey( - name: "fk_chara_data_allowance_chara_data_parent_id_parent_uploader_u", - columns: x => new { x.parent_id, x.parent_uploader_uid }, - principalTable: "chara_data", - principalColumns: new[] { "id", "uploader_uid" }, - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_chara_data_allowance_groups_allowed_group_gid", - column: x => x.allowed_group_gid, - principalTable: "groups", - principalColumn: "gid", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_chara_data_allowance_users_allowed_user_uid", - column: x => x.allowed_user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "group_bans", - columns: table => new - { - group_gid = table.Column(type: "character varying(20)", nullable: false), - banned_user_uid = table.Column(type: "character varying(10)", nullable: false), - banned_by_uid = table.Column(type: "character varying(10)", nullable: true), - banned_on = table.Column(type: "timestamp with time zone", nullable: false), - banned_reason = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("pk_group_bans", x => new { x.group_gid, x.banned_user_uid }); - table.ForeignKey( - name: "fk_group_bans_groups_group_gid", - column: x => x.group_gid, - principalTable: "groups", - principalColumn: "gid", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_group_bans_users_banned_by_uid", - column: x => x.banned_by_uid, - principalTable: "users", - principalColumn: "uid"); - table.ForeignKey( - name: "fk_group_bans_users_banned_user_uid", - column: x => x.banned_user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "group_pair_preferred_permissions", - columns: table => new - { - group_gid = table.Column(type: "character varying(20)", nullable: false), - user_uid = table.Column(type: "character varying(10)", nullable: false), - is_paused = table.Column(type: "boolean", nullable: false), - disable_animations = table.Column(type: "boolean", nullable: false), - disable_sounds = table.Column(type: "boolean", nullable: false), - disable_vfx = table.Column(type: "boolean", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_group_pair_preferred_permissions", x => new { x.user_uid, x.group_gid }); - table.ForeignKey( - name: "fk_group_pair_preferred_permissions_groups_group_gid", - column: x => x.group_gid, - principalTable: "groups", - principalColumn: "gid", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_group_pair_preferred_permissions_users_user_uid", - column: x => x.user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "group_pairs", - columns: table => new - { - group_gid = table.Column(type: "character varying(20)", nullable: false), - group_user_uid = table.Column(type: "character varying(10)", nullable: false), - is_pinned = table.Column(type: "boolean", nullable: false), - is_moderator = table.Column(type: "boolean", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_group_pairs", x => new { x.group_gid, x.group_user_uid }); - table.ForeignKey( - name: "fk_group_pairs_groups_group_gid", - column: x => x.group_gid, - principalTable: "groups", - principalColumn: "gid", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "fk_group_pairs_users_group_user_uid", - column: x => x.group_user_uid, - principalTable: "users", - principalColumn: "uid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "group_temp_invites", - columns: table => new - { - group_gid = table.Column(type: "character varying(20)", nullable: false), - invite = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - expiration_date = table.Column(type: "timestamp with time zone", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_group_temp_invites", x => new { x.group_gid, x.invite }); - table.ForeignKey( - name: "fk_group_temp_invites_groups_group_gid", - column: x => x.group_gid, - principalTable: "groups", - principalColumn: "gid", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "ix_auth_primary_user_uid", - table: "auth", - column: "primary_user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_auth_user_uid", - table: "auth", - column: "user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_id", - table: "chara_data", - column: "id"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_uploader_uid", - table: "chara_data", - column: "uploader_uid"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_allowance_allowed_group_gid", - table: "chara_data_allowance", - column: "allowed_group_gid"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_allowance_allowed_user_uid", - table: "chara_data_allowance", - column: "allowed_user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_allowance_parent_id", - table: "chara_data_allowance", - column: "parent_id"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_file_swaps_parent_id", - table: "chara_data_file_swaps", - column: "parent_id"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_files_file_cache_hash", - table: "chara_data_files", - column: "file_cache_hash"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_files_parent_id", - table: "chara_data_files", - column: "parent_id"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_orig_files_parent_id", - table: "chara_data_orig_files", - column: "parent_id"); - - migrationBuilder.CreateIndex( - name: "ix_chara_data_poses_parent_id", - table: "chara_data_poses", - column: "parent_id"); - - migrationBuilder.CreateIndex( - name: "ix_client_pairs_other_user_uid", - table: "client_pairs", - column: "other_user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_client_pairs_user_uid", - table: "client_pairs", - column: "user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_file_caches_uploader_uid", - table: "file_caches", - column: "uploader_uid"); - - migrationBuilder.CreateIndex( - name: "ix_group_bans_banned_by_uid", - table: "group_bans", - column: "banned_by_uid"); - - migrationBuilder.CreateIndex( - name: "ix_group_bans_banned_user_uid", - table: "group_bans", - column: "banned_user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_group_bans_group_gid", - table: "group_bans", - column: "group_gid"); - - migrationBuilder.CreateIndex( - name: "ix_group_pair_preferred_permissions_group_gid", - table: "group_pair_preferred_permissions", - column: "group_gid"); - - migrationBuilder.CreateIndex( - name: "ix_group_pair_preferred_permissions_user_uid", - table: "group_pair_preferred_permissions", - column: "user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_group_pairs_group_gid", - table: "group_pairs", - column: "group_gid"); - - migrationBuilder.CreateIndex( - name: "ix_group_pairs_group_user_uid", - table: "group_pairs", - column: "group_user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_group_temp_invites_group_gid", - table: "group_temp_invites", - column: "group_gid"); - - migrationBuilder.CreateIndex( - name: "ix_group_temp_invites_invite", - table: "group_temp_invites", - column: "invite"); - - migrationBuilder.CreateIndex( - name: "ix_groups_owner_uid", - table: "groups", - column: "owner_uid"); - - migrationBuilder.CreateIndex( - name: "ix_lodestone_auth_user_uid", - table: "lodestone_auth", - column: "user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_user_default_preferred_permissions_user_uid", - table: "user_default_preferred_permissions", - column: "user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_user_permission_sets_other_user_uid", - table: "user_permission_sets", - column: "other_user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_user_permission_sets_user_uid", - table: "user_permission_sets", - column: "user_uid"); - - migrationBuilder.CreateIndex( - name: "ix_user_permission_sets_user_uid_other_user_uid_is_paused", - table: "user_permission_sets", - columns: new[] { "user_uid", "other_user_uid", "is_paused" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "auth"); - - migrationBuilder.DropTable( - name: "banned_registrations"); - - migrationBuilder.DropTable( - name: "banned_users"); - - migrationBuilder.DropTable( - name: "chara_data_allowance"); - - migrationBuilder.DropTable( - name: "chara_data_file_swaps"); - - migrationBuilder.DropTable( - name: "chara_data_files"); - - migrationBuilder.DropTable( - name: "chara_data_orig_files"); - - migrationBuilder.DropTable( - name: "chara_data_poses"); - - migrationBuilder.DropTable( - name: "client_pairs"); - - migrationBuilder.DropTable( - name: "forbidden_upload_entries"); - - migrationBuilder.DropTable( - name: "group_bans"); - - migrationBuilder.DropTable( - name: "group_pair_preferred_permissions"); - - migrationBuilder.DropTable( - name: "group_pairs"); - - migrationBuilder.DropTable( - name: "group_temp_invites"); - - migrationBuilder.DropTable( - name: "lodestone_auth"); - - migrationBuilder.DropTable( - name: "user_default_preferred_permissions"); - - migrationBuilder.DropTable( - name: "user_permission_sets"); - - migrationBuilder.DropTable( - name: "user_profile_data"); - - migrationBuilder.DropTable( - name: "file_caches"); - - migrationBuilder.DropTable( - name: "chara_data"); - - migrationBuilder.DropTable( - name: "groups"); - - migrationBuilder.DropTable( - name: "users"); - } - } -} diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.Designer.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.Designer.cs similarity index 99% rename from LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.Designer.cs rename to LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.Designer.cs index 840c97b..726257a 100644 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905161830_AddBannedUid.Designer.cs +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace LightlessSyncServer.Migrations { [DbContext(typeof(LightlessDbContext))] - [Migration("20250905161830_AddBannedUid")] + [Migration("20250905190334_AddBannedUid")] partial class AddBannedUid { /// diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.cs new file mode 100644 index 0000000..0286706 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LightlessSyncServer.Migrations +{ + /// + public partial class AddBannedUid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/LightlessSyncServer/LightlessSyncShared/LightlessSyncServer/Migrations/LightlessDbContextModelSnapshot.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/LightlessDbContextModelSnapshot.cs similarity index 100% rename from LightlessSyncServer/LightlessSyncShared/LightlessSyncServer/Migrations/LightlessDbContextModelSnapshot.cs rename to LightlessSyncServer/LightlessSyncShared/Migrations/LightlessDbContextModelSnapshot.cs -- 2.49.1 From 176f0e7e561479e028b802bb4890cebb3c4ea05a Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 14:14:37 -0500 Subject: [PATCH 07/14] push fix for banning scrubs --- LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index 100efcc..44113a9 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -225,7 +225,7 @@ public class LightlessModule : InteractionModuleBase } } - [SlashCommand("markUidforBan", "ADMIN ONLY: ban a user by their uid")] + [SlashCommand("markforban", "ADMIN ONLY: ban a user by their uid")] public async Task MarkUidForBan([Summary("uid", "uid to ban")] string uid) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", -- 2.49.1 From 56bc277436f530a5ae65a77b426bae36870ac99b Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 14:29:37 -0500 Subject: [PATCH 08/14] readding banned column --- ...gner.cs => 20250905192853_AddBannedUid.Designer.cs} | 2 +- ..._AddBannedUid.cs => 20250905192853_AddBannedUid.cs} | 10 ++++++++-- .../LightlessSyncShared/Models/Banned.cs | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) rename LightlessSyncServer/LightlessSyncShared/Migrations/{20250905190334_AddBannedUid.Designer.cs => 20250905192853_AddBannedUid.Designer.cs} (99%) rename LightlessSyncServer/LightlessSyncShared/Migrations/{20250905190334_AddBannedUid.cs => 20250905192853_AddBannedUid.cs} (59%) diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.Designer.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905192853_AddBannedUid.Designer.cs similarity index 99% rename from LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.Designer.cs rename to LightlessSyncServer/LightlessSyncShared/Migrations/20250905192853_AddBannedUid.Designer.cs index 726257a..5c56f33 100644 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.Designer.cs +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905192853_AddBannedUid.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace LightlessSyncServer.Migrations { [DbContext(typeof(LightlessDbContext))] - [Migration("20250905190334_AddBannedUid")] + [Migration("20250905192853_AddBannedUid")] partial class AddBannedUid { /// diff --git a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.cs b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905192853_AddBannedUid.cs similarity index 59% rename from LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.cs rename to LightlessSyncServer/LightlessSyncShared/Migrations/20250905192853_AddBannedUid.cs index 0286706..0467a67 100644 --- a/LightlessSyncServer/LightlessSyncShared/Migrations/20250905190334_AddBannedUid.cs +++ b/LightlessSyncServer/LightlessSyncShared/Migrations/20250905192853_AddBannedUid.cs @@ -10,13 +10,19 @@ namespace LightlessSyncServer.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { - + migrationBuilder.AddColumn( + name: "banned_uid", + table: "banned_users", + type: "text", + nullable: true); } /// protected override void Down(MigrationBuilder migrationBuilder) { - + migrationBuilder.DropColumn( + name: "banned_uid", + table: "banned_users"); } } } diff --git a/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs b/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs index bc09e55..4071f56 100644 --- a/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs +++ b/LightlessSyncServer/LightlessSyncShared/Models/Banned.cs @@ -7,8 +7,8 @@ public class Banned [Key] [MaxLength(100)] public string CharacterIdentification { get; set; } - public string Reason { get; set; } public string BannedUid { get; set; } + public string Reason { get; set; } [Timestamp] public byte[] Timestamp { get; set; } } -- 2.49.1 From 332f7f7bb2e664a4119fe693615dfcc1e1b235e3 Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 14:52:03 -0500 Subject: [PATCH 09/14] rewriting routs --- .../Controllers/UserController.cs | 13 +++++++------ .../LightlessSyncServices/Discord/MareModule.cs | 9 ++++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs index 5d11e47..c84ff49 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore; namespace LightlessSyncAuthService.Controllers; [Route(LightlessAuth.User)] +[Authorize(Policy = "Internal")] public class UserController : Controller { protected readonly ILogger Logger; @@ -17,8 +18,8 @@ public class UserController : Controller LightlessDbContextFactory = lightlessDbContext; } - [Authorize(Policy = "Internal")] - [HttpPost(LightlessAuth.Ban_Uid)] + [Route(LightlessAuth.Ban_Uid)] + [HttpPost] public async Task MarkForBanUid(string uid) { using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); @@ -35,8 +36,8 @@ public class UserController : Controller await dbContext.SaveChangesAsync(); } - [Authorize(Policy = "Internal")] - [HttpPost(LightlessAuth.User_Unban_Uid)] + [Route(LightlessAuth.User_Unban_Uid)] + [HttpPost] public async Task UnBanUserByUid(string uid) { using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); @@ -66,8 +67,8 @@ public class UserController : Controller await dbContext.SaveChangesAsync(); } - [Authorize(Policy = "Internal")] - [HttpPost(LightlessAuth.User_Unban_Discord)] + [Route(LightlessAuth.User_Unban_Discord)] + [HttpPost] public async Task UnBanUserByDiscordId(string discordId) { Logger.LogInformation("Unbanning user with discordId: {discordId}", discordId); diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index 44113a9..c5cd528 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -106,7 +106,9 @@ public class LightlessModule : InteractionModuleBase using HttpClient c = new HttpClient(); c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); - + var testUri = new Uri(_lightlessServicesConfiguration.GetValue + (nameof(ServicesConfiguration.MainServerAddress)), "/msgc/sendMessage"); + _logger.LogInformation("UnbanByDiscord:URI:{uri}", testUri); await c.PostAsJsonAsync( new Uri(_lightlessServicesConfiguration.GetValue(nameof(ServicesConfiguration.MainServerAddress)), "/msgc/sendMessage"), new ClientMessage(messageType, message, uid ?? string.Empty) @@ -152,6 +154,7 @@ public class LightlessModule : InteractionModuleBase try { using HttpClient c = new HttpClient(); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"), new { discordId }) @@ -193,6 +196,9 @@ public class LightlessModule : InteractionModuleBase try { using HttpClient c = new HttpClient(); + var testUri = new Uri(_lightlessServicesConfiguration.GetValue + (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"); + _logger.LogInformation("UnbanByDiscord:URI:{uri}", testUri); c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanUID"), new { uid }) @@ -234,6 +240,7 @@ public class LightlessModule : InteractionModuleBase try { using HttpClient c = new HttpClient(); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/ban"), new { uid }) -- 2.49.1 From 9cd77d2b5529b9c8c368325b75d471f75ef8b7c6 Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 15:20:43 -0500 Subject: [PATCH 10/14] moving bancontroller --- .../Controllers/UserController.cs | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs diff --git a/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs new file mode 100644 index 0000000..c84ff49 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs @@ -0,0 +1,98 @@ +using LightlessSync.API.Routes; +using LightlessSyncShared.Data; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace LightlessSyncAuthService.Controllers; + +[Route(LightlessAuth.User)] +[Authorize(Policy = "Internal")] +public class UserController : Controller +{ + protected readonly ILogger Logger; + protected readonly IDbContextFactory LightlessDbContextFactory; + public UserController(ILogger logger, IDbContextFactory lightlessDbContext) + { + Logger = logger; + LightlessDbContextFactory = lightlessDbContext; + } + + [Route(LightlessAuth.Ban_Uid)] + [HttpPost] + public async Task MarkForBanUid(string uid) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Banning user with UID {UID}", uid); + + //Mark User as banned, and not marked for ban + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); + if (auth != null) + { + auth.MarkForBan = true; + } + + await dbContext.SaveChangesAsync(); + } + + [Route(LightlessAuth.User_Unban_Uid)] + [HttpPost] + public async Task UnBanUserByUid(string uid) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Unbanning user with UID {UID}", uid); + + //Mark User as not banned, and not marked for ban (if marked) + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); + if (auth != null) + { + auth.IsBanned = false; + auth.MarkForBan = false; + } + + // Remove all bans associated with this user + var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == uid); + dbContext.BannedUsers.RemoveRange(bannedFromLightlessIds); + + // Remove all character/discord bans associated with this user + var lodestoneAuths = dbContext.LodeStoneAuth.Where(l => l.User != null && l.User.UID == uid).ToList(); + foreach (var lodestoneAuth in lodestoneAuths) + { + var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == lodestoneAuth.HashedLodestoneId || b.DiscordIdOrLodestoneAuth == lodestoneAuth.DiscordId.ToString()); + dbContext.BannedRegistrations.RemoveRange(bannedRegs); + } + + await dbContext.SaveChangesAsync(); + } + + [Route(LightlessAuth.User_Unban_Discord)] + [HttpPost] + public async Task UnBanUserByDiscordId(string discordId) + { + Logger.LogInformation("Unbanning user with discordId: {discordId}", discordId); + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + var userByDiscord = await dbContext.LodeStoneAuth.Include(l => l.User).FirstOrDefaultAsync(l => l.DiscordId.ToString() == discordId); + + if (userByDiscord?.User == null) + { + Logger.LogInformation("Unbanning user with discordId: {discordId} but no user found", discordId); + return; + } + var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == discordId || b.DiscordIdOrLodestoneAuth == userByDiscord.HashedLodestoneId); + //Mark User as not banned, and not marked for ban (if marked) + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == userByDiscord.User.UID); + if (auth != null) + { + auth.IsBanned = false; + auth.MarkForBan = false; + } + // Remove all bans associated with this user + var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == auth.UserUID || b.BannedUid == auth.PrimaryUserUID); + dbContext.BannedUsers.RemoveRange(bannedFromLightlessIds); + + await dbContext.SaveChangesAsync(); + } +} \ No newline at end of file -- 2.49.1 From 42ed164c54c770e7c5c25be9db2b758cdfad4ac8 Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 16:02:00 -0500 Subject: [PATCH 11/14] Registering Controller --- .../Controllers/UserController.cs | 98 ------------------- .../LightlessSyncAuthService/Startup.cs | 5 +- .../LightlessSyncServer/Startup.cs | 41 ++++---- 3 files changed, 22 insertions(+), 122 deletions(-) delete mode 100644 LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs diff --git a/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs deleted file mode 100644 index c84ff49..0000000 --- a/LightlessSyncServer/LightlessSyncAuthService/Controllers/UserController.cs +++ /dev/null @@ -1,98 +0,0 @@ -using LightlessSync.API.Routes; -using LightlessSyncShared.Data; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; - -namespace LightlessSyncAuthService.Controllers; - -[Route(LightlessAuth.User)] -[Authorize(Policy = "Internal")] -public class UserController : Controller -{ - protected readonly ILogger Logger; - protected readonly IDbContextFactory LightlessDbContextFactory; - public UserController(ILogger logger, IDbContextFactory lightlessDbContext) - { - Logger = logger; - LightlessDbContextFactory = lightlessDbContext; - } - - [Route(LightlessAuth.Ban_Uid)] - [HttpPost] - public async Task MarkForBanUid(string uid) - { - using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); - - Logger.LogInformation("Banning user with UID {UID}", uid); - - //Mark User as banned, and not marked for ban - var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); - if (auth != null) - { - auth.MarkForBan = true; - } - - await dbContext.SaveChangesAsync(); - } - - [Route(LightlessAuth.User_Unban_Uid)] - [HttpPost] - public async Task UnBanUserByUid(string uid) - { - using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); - - Logger.LogInformation("Unbanning user with UID {UID}", uid); - - //Mark User as not banned, and not marked for ban (if marked) - var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); - if (auth != null) - { - auth.IsBanned = false; - auth.MarkForBan = false; - } - - // Remove all bans associated with this user - var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == uid); - dbContext.BannedUsers.RemoveRange(bannedFromLightlessIds); - - // Remove all character/discord bans associated with this user - var lodestoneAuths = dbContext.LodeStoneAuth.Where(l => l.User != null && l.User.UID == uid).ToList(); - foreach (var lodestoneAuth in lodestoneAuths) - { - var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == lodestoneAuth.HashedLodestoneId || b.DiscordIdOrLodestoneAuth == lodestoneAuth.DiscordId.ToString()); - dbContext.BannedRegistrations.RemoveRange(bannedRegs); - } - - await dbContext.SaveChangesAsync(); - } - - [Route(LightlessAuth.User_Unban_Discord)] - [HttpPost] - public async Task UnBanUserByDiscordId(string discordId) - { - Logger.LogInformation("Unbanning user with discordId: {discordId}", discordId); - using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); - - var userByDiscord = await dbContext.LodeStoneAuth.Include(l => l.User).FirstOrDefaultAsync(l => l.DiscordId.ToString() == discordId); - - if (userByDiscord?.User == null) - { - Logger.LogInformation("Unbanning user with discordId: {discordId} but no user found", discordId); - return; - } - var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == discordId || b.DiscordIdOrLodestoneAuth == userByDiscord.HashedLodestoneId); - //Mark User as not banned, and not marked for ban (if marked) - var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == userByDiscord.User.UID); - if (auth != null) - { - auth.IsBanned = false; - auth.MarkForBan = false; - } - // Remove all bans associated with this user - var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == auth.UserUID || b.BannedUid == auth.PrimaryUserUID); - dbContext.BannedUsers.RemoveRange(bannedFromLightlessIds); - - await dbContext.SaveChangesAsync(); - } -} \ No newline at end of file diff --git a/LightlessSyncServer/LightlessSyncAuthService/Startup.cs b/LightlessSyncServer/LightlessSyncAuthService/Startup.cs index 2f81451..20d8d89 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Startup.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Startup.cs @@ -3,8 +3,6 @@ using LightlessSyncShared.Metrics; using LightlessSyncShared.Services; using LightlessSyncShared.Utils; using Microsoft.AspNetCore.Mvc.Controllers; -using StackExchange.Redis.Extensions.Core.Configuration; -using StackExchange.Redis.Extensions.System.Text.Json; using StackExchange.Redis; using System.Net; using LightlessSyncAuthService.Services; @@ -17,7 +15,6 @@ using LightlessSyncShared.Data; using Microsoft.EntityFrameworkCore; using Prometheus; using LightlessSyncShared.Utils.Configuration; -using StackExchange.Redis.Extensions.Core.Abstractions; namespace LightlessSyncAuthService; @@ -88,7 +85,7 @@ public class Startup services.AddControllers().ConfigureApplicationPartManager(a => { a.FeatureProviders.Remove(a.FeatureProviders.OfType().First()); - a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(JwtController), typeof(OAuthController), typeof(UserController))); + a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(JwtController), typeof(OAuthController))); }); } diff --git a/LightlessSyncServer/LightlessSyncServer/Startup.cs b/LightlessSyncServer/LightlessSyncServer/Startup.cs index 4a2a2ba..d9bab3f 100644 --- a/LightlessSyncServer/LightlessSyncServer/Startup.cs +++ b/LightlessSyncServer/LightlessSyncServer/Startup.cs @@ -1,29 +1,30 @@ -using Microsoft.EntityFrameworkCore; -using LightlessSyncServer.Hubs; -using Microsoft.AspNetCore.Http.Connections; -using Microsoft.AspNetCore.SignalR; -using Microsoft.AspNetCore.Authorization; using AspNetCoreRateLimit; +using LightlessSync.API.SignalR; +using LightlessSyncAuthService.Controllers; +using LightlessSyncServer.Controllers; +using LightlessSyncServer.Hubs; +using LightlessSyncServer.Services; using LightlessSyncShared.Data; using LightlessSyncShared.Metrics; -using LightlessSyncServer.Services; -using LightlessSyncShared.Utils; +using LightlessSyncShared.RequirementHandlers; using LightlessSyncShared.Services; -using Prometheus; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.IdentityModel.Tokens; -using System.Text; -using StackExchange.Redis; -using StackExchange.Redis.Extensions.Core.Configuration; -using System.Net; -using StackExchange.Redis.Extensions.System.Text.Json; -using LightlessSync.API.SignalR; +using LightlessSyncShared.Utils; +using LightlessSyncShared.Utils.Configuration; using MessagePack; using MessagePack.Resolvers; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Mvc.Controllers; -using LightlessSyncServer.Controllers; -using LightlessSyncShared.RequirementHandlers; -using LightlessSyncShared.Utils.Configuration; +using Microsoft.AspNetCore.SignalR; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Prometheus; +using StackExchange.Redis; +using StackExchange.Redis.Extensions.Core.Configuration; +using StackExchange.Redis.Extensions.System.Text.Json; +using System.Net; +using System.Text; namespace LightlessSyncServer; @@ -71,7 +72,7 @@ public class Startup a.FeatureProviders.Remove(a.FeatureProviders.OfType().First()); if (lightlessConfig.GetValue(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null) { - a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(LightlessServerConfigurationController), typeof(LightlessBaseConfigurationController), typeof(ClientMessageController))); + a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(LightlessServerConfigurationController), typeof(LightlessBaseConfigurationController), typeof(ClientMessageController), typeof(UserController))); } else { -- 2.49.1 From f6b33425b5de6a06e9ab3f17e311ac799d1443ac Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 16:17:15 -0500 Subject: [PATCH 12/14] Body fixes --- .../LightlessSyncServer/Controllers/UserController.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs index c84ff49..d6c04c1 100644 --- a/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs +++ b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs @@ -20,7 +20,7 @@ public class UserController : Controller [Route(LightlessAuth.Ban_Uid)] [HttpPost] - public async Task MarkForBanUid(string uid) + public async Task MarkForBanUid([FromBody] string uid) { using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); @@ -38,7 +38,7 @@ public class UserController : Controller [Route(LightlessAuth.User_Unban_Uid)] [HttpPost] - public async Task UnBanUserByUid(string uid) + public async Task UnBanUserByUid([FromBody] string uid) { using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); @@ -69,7 +69,7 @@ public class UserController : Controller [Route(LightlessAuth.User_Unban_Discord)] [HttpPost] - public async Task UnBanUserByDiscordId(string discordId) + public async Task UnBanUserByDiscordId([FromBody] string discordId) { Logger.LogInformation("Unbanning user with discordId: {discordId}", discordId); using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); -- 2.49.1 From 9631f521bc0ae9646897d4827f778496a84f49e0 Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 16:41:00 -0500 Subject: [PATCH 13/14] DTOs --- LightlessAPI | 2 +- .../Controllers/UserController.cs | 29 ++++++++++--------- .../Discord/MareModule.cs | 9 +++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/LightlessAPI b/LightlessAPI index 4918a2c..4ce70be 160000 --- a/LightlessAPI +++ b/LightlessAPI @@ -1 +1 @@ -Subproject commit 4918a2c4e321a79c8320e1b31aec36ddceacbb45 +Subproject commit 4ce70bee8354d0c96d73e65312d39a826810dc60 diff --git a/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs index d6c04c1..0084566 100644 --- a/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs +++ b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs @@ -1,4 +1,5 @@ -using LightlessSync.API.Routes; +using LightlessSync.API.Dto.User; +using LightlessSync.API.Routes; using LightlessSyncShared.Data; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -20,14 +21,14 @@ public class UserController : Controller [Route(LightlessAuth.Ban_Uid)] [HttpPost] - public async Task MarkForBanUid([FromBody] string uid) + public async Task MarkForBanUid([FromBody] BanRequest request) { using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); - Logger.LogInformation("Banning user with UID {UID}", uid); + Logger.LogInformation("Banning user with UID {UID}", request.Uid); //Mark User as banned, and not marked for ban - var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == request.Uid); if (auth != null) { auth.MarkForBan = true; @@ -38,14 +39,14 @@ public class UserController : Controller [Route(LightlessAuth.User_Unban_Uid)] [HttpPost] - public async Task UnBanUserByUid([FromBody] string uid) + public async Task UnBanUserByUid([FromBody] UnbanRequest request) { using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); - Logger.LogInformation("Unbanning user with UID {UID}", uid); + Logger.LogInformation("Unbanning user with UID {UID}", request.Uid); //Mark User as not banned, and not marked for ban (if marked) - var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == uid); + var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == request.Uid); if (auth != null) { auth.IsBanned = false; @@ -53,11 +54,11 @@ public class UserController : Controller } // Remove all bans associated with this user - var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == uid); + var bannedFromLightlessIds = dbContext.BannedUsers.Where(b => b.BannedUid == request.Uid); dbContext.BannedUsers.RemoveRange(bannedFromLightlessIds); // Remove all character/discord bans associated with this user - var lodestoneAuths = dbContext.LodeStoneAuth.Where(l => l.User != null && l.User.UID == uid).ToList(); + var lodestoneAuths = dbContext.LodeStoneAuth.Where(l => l.User != null && l.User.UID == request.Uid).ToList(); foreach (var lodestoneAuth in lodestoneAuths) { var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == lodestoneAuth.HashedLodestoneId || b.DiscordIdOrLodestoneAuth == lodestoneAuth.DiscordId.ToString()); @@ -69,19 +70,19 @@ public class UserController : Controller [Route(LightlessAuth.User_Unban_Discord)] [HttpPost] - public async Task UnBanUserByDiscordId([FromBody] string discordId) + public async Task UnBanUserByDiscordId([FromBody] UnbanRequest request) { - Logger.LogInformation("Unbanning user with discordId: {discordId}", discordId); + Logger.LogInformation("Unbanning user with discordId: {discordId}", request.DiscordId); using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); - var userByDiscord = await dbContext.LodeStoneAuth.Include(l => l.User).FirstOrDefaultAsync(l => l.DiscordId.ToString() == discordId); + var userByDiscord = await dbContext.LodeStoneAuth.Include(l => l.User).FirstOrDefaultAsync(l => l.DiscordId.ToString() == request.DiscordId); if (userByDiscord?.User == null) { - Logger.LogInformation("Unbanning user with discordId: {discordId} but no user found", discordId); + Logger.LogInformation("Unbanning user with discordId: {discordId} but no user found", request.DiscordId); return; } - var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == discordId || b.DiscordIdOrLodestoneAuth == userByDiscord.HashedLodestoneId); + var bannedRegs = dbContext.BannedRegistrations.Where(b => b.DiscordIdOrLodestoneAuth == request.DiscordId || b.DiscordIdOrLodestoneAuth == userByDiscord.HashedLodestoneId); //Mark User as not banned, and not marked for ban (if marked) var auth = await dbContext.Auth.FirstOrDefaultAsync(f => f.UserUID == userByDiscord.User.UID); if (auth != null) diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index c5cd528..d706401 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -9,6 +9,7 @@ using LightlessSyncShared.Services; using StackExchange.Redis; using LightlessSync.API.Data.Enum; using LightlessSyncShared.Utils.Configuration; +using LightlessSync.API.Dto.User; namespace LightlessSyncServices.Discord; @@ -146,7 +147,7 @@ public class LightlessModule : InteractionModuleBase } [SlashCommand("unbanbydiscord", "ADMIN ONLY: Unban a user by their discord ID")] - public async Task UnbanByDiscord([Summary("discord_id", "Discord ID to unban")] ulong discordId) + public async Task UnbanByDiscord([Summary("discord_id", "Discord ID to unban")] string discordId) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", Context.Interaction.User.Id, nameof(UnbanByDiscord), @@ -157,7 +158,7 @@ public class LightlessModule : InteractionModuleBase c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue - (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"), new { discordId }) + (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"), new UnbanRequest(string.Empty, discordId)) .ConfigureAwait(false); var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); if (discordChannelForMessages != null) @@ -201,7 +202,7 @@ public class LightlessModule : InteractionModuleBase _logger.LogInformation("UnbanByDiscord:URI:{uri}", testUri); c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue - (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanUID"), new { uid }) + (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanUID"), new UnbanRequest(uid, string.Empty)) .ConfigureAwait(false); var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); if (discordChannelForMessages != null) @@ -243,7 +244,7 @@ public class LightlessModule : InteractionModuleBase c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue - (nameof(ServicesConfiguration.MainServerAddress)), "/user/ban"), new { uid }) + (nameof(ServicesConfiguration.MainServerAddress)), "/user/ban"), new BanRequest(uid)) .ConfigureAwait(false); var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); if (discordChannelForMessages != null) -- 2.49.1 From 3d758f58f8fa8ed442314343ec47fcb447d50a69 Mon Sep 17 00:00:00 2001 From: defnotken Date: Fri, 5 Sep 2025 16:52:06 -0500 Subject: [PATCH 14/14] cleaning up logs --- .../LightlessSyncServices/Discord/MareModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index d706401..48d1c03 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -109,7 +109,7 @@ public class LightlessModule : InteractionModuleBase c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); var testUri = new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/msgc/sendMessage"); - _logger.LogInformation("UnbanByDiscord:URI:{uri}", testUri); + await c.PostAsJsonAsync( new Uri(_lightlessServicesConfiguration.GetValue(nameof(ServicesConfiguration.MainServerAddress)), "/msgc/sendMessage"), new ClientMessage(messageType, message, uid ?? string.Empty) @@ -199,7 +199,7 @@ public class LightlessModule : InteractionModuleBase using HttpClient c = new HttpClient(); var testUri = new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"); - _logger.LogInformation("UnbanByDiscord:URI:{uri}", testUri); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanUID"), new UnbanRequest(uid, string.Empty)) -- 2.49.1