From c30190704ffbbff0668aa3da9950680fe364f8da Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Sun, 19 Oct 2025 17:53:20 +0200 Subject: [PATCH] Changed get/set profile with more safe handling --- .../Hubs/LightlessHub.Groups.cs | 103 +++++++++--------- .../LightlessSyncServer/Utils/Extensions.cs | 32 +++++- 2 files changed, 76 insertions(+), 59 deletions(-) diff --git a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Groups.cs b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Groups.cs index d489c8e..adbe44d 100644 --- a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Groups.cs +++ b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Groups.cs @@ -745,23 +745,34 @@ public partial class LightlessHub var cancellationToken = RequestAbortedToken; - var data = await DbContext.GroupProfiles - .FirstOrDefaultAsync(g => g.Group.GID == dto.Group.GID || g.Group.Alias == dto.Group.AliasOrGID, cancellationToken) - .ConfigureAwait(false); - - var profileDto = new GroupProfileDto(dto.Group, Description: null, Tags: null, PictureBase64: null, IsNsfw: false, IsDisabled: false); - - if (data is not null) + if (dto?.Group == null) { - _logger.LogCallInfo(LightlessHubLogger.Args($"GroupGetProfile: dto={dto?.GID}, groupProfile.Group={(data?.Group != null)}")); - - if (data.Group != null) - { - profileDto = data.ToDTO(); - } + _logger.LogCallWarning(LightlessHubLogger.Args("GroupGetProfile: dto.Group is null")); + return new GroupProfileDto(Group: null, Description: null, Tags: null, PictureBase64: null, IsNsfw: false, IsDisabled: false); } - return profileDto; + var data = await DbContext.GroupProfiles + .Include(gp => gp.Group) + .FirstOrDefaultAsync( + g => g.Group.GID == dto.Group.GID || g.Group.Alias == dto.Group.AliasOrGID, + cancellationToken + ) + .ConfigureAwait(false); + + if (data == null) + { + return new GroupProfileDto(dto.Group, Description: null, Tags: null, PictureBase64: null, IsNsfw: false, IsDisabled: false); + } + + try + { + return data.ToDTO(); + } + catch (Exception ex) + { + _logger.LogCallWarning(LightlessHubLogger.Args(ex, "GroupGetProfile: failed to map GroupProfileDto for {Group}", dto.Group.GID ?? dto.Group.AliasOrGID)); + return new GroupProfileDto(dto.Group, Description: null, Tags: null, PictureBase64: null, IsNsfw: false, IsDisabled: false); + } } [Authorize(Policy = "Identified")] @@ -769,6 +780,8 @@ public partial class LightlessHub { _logger.LogCallInfo(LightlessHubLogger.Args(dto)); + var cancellationToken = RequestAbortedToken; + if (dto.Group == null) return; var (hasRights, group) = await TryValidateGroupModeratorOrOwner(dto.Group.GID).ConfigureAwait(false); @@ -776,57 +789,39 @@ public partial class LightlessHub var groupProfileDb = await DbContext.GroupProfiles .FirstOrDefaultAsync(g => g.Group.GID == dto.Group.GID || g.Group.Alias == dto.Group.GID, - RequestAbortedToken) + cancellationToken) .ConfigureAwait(false); - if (groupProfileDb != null) + if (groupProfileDb == null) { - var groupPairs = DbContext.GroupPairs.Where(p => p.GroupGID == groupProfileDb.GroupGID).Select(p => p.GroupUserUID).ToList(); - - if (string.Equals("", dto.PictureBase64, StringComparison.OrdinalIgnoreCase)) + groupProfileDb = new GroupProfile { - groupProfileDb.Base64GroupProfileImage = null; - } - else if (dto.PictureBase64 != null) - { - groupProfileDb.Base64GroupProfileImage = dto.PictureBase64; - } - - if (dto.Tags != null) - { - groupProfileDb.Tags = dto.Tags; - } - - if (dto.Description != null) - { - groupProfileDb.Description = dto.Description; - } - - if (dto.IsNsfw != null) - { - groupProfileDb.IsNSFW = dto.IsNsfw.Value; - } - - await Clients.Users(groupPairs).Client_GroupSendProfile(groupProfileDb.ToDTO()).ConfigureAwait(false); + GroupGID = dto.Group.GID, + ProfileDisabled = false, + IsNSFW = dto.IsNsfw ?? false, + }; + groupProfileDb.UpdateProfileFromDto(dto); + await DbContext.GroupProfiles.AddAsync(groupProfileDb, cancellationToken).ConfigureAwait(false); } else { - var groupProfile = new GroupProfile - { - GroupGID = dto.Group.GID, - Description = dto.Description, - Tags = dto.Tags, - Base64GroupProfileImage = dto.PictureBase64, - IsNSFW = false, - ProfileDisabled = false, - }; + groupProfileDb.UpdateProfileFromDto(dto); - await DbContext.GroupProfiles.AddAsync(groupProfile, - RequestAbortedToken) + var userIds = await DbContext.GroupPairs + .Where(p => p.GroupGID == groupProfileDb.GroupGID) + .Select(p => p.GroupUserUID) + .ToListAsync(cancellationToken) .ConfigureAwait(false); + + if (userIds.Count > 0) + { + var profileDto = groupProfileDb.ToDTO(); + await Clients.Users(userIds).Client_GroupSendProfile(profileDto) + .ConfigureAwait(false); + } } - await DbContext.SaveChangesAsync(RequestAbortedToken).ConfigureAwait(false); + await DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } [Authorize(Policy = "Identified")] diff --git a/LightlessSyncServer/LightlessSyncServer/Utils/Extensions.cs b/LightlessSyncServer/LightlessSyncServer/Utils/Extensions.cs index 2e4d62f..f0cc026 100644 --- a/LightlessSyncServer/LightlessSyncServer/Utils/Extensions.cs +++ b/LightlessSyncServer/LightlessSyncServer/Utils/Extensions.cs @@ -9,14 +9,27 @@ namespace LightlessSyncServer.Utils; public static class Extensions { + public static void UpdateProfileFromDto(this GroupProfile profile, GroupProfileDto dto) + { + if (profile == null || dto == null) return; + + profile.Base64GroupProfileImage = string.IsNullOrWhiteSpace(dto.PictureBase64) ? null : dto.PictureBase64; + if (dto.Tags != null) profile.Tags = dto.Tags; + if (dto.Description != null) profile.Description = dto.Description; + if (dto.IsNsfw.HasValue) profile.IsNSFW = dto.IsNsfw.Value; + } + public static GroupProfileDto ToDTO(this GroupProfile groupProfile) { - ArgumentNullException.ThrowIfNull(groupProfile); + if (groupProfile == null) + { + return new GroupProfileDto(Group: null, Description: null, Tags: null, PictureBase64: null, IsNsfw: false, IsDisabled: false); + } - return groupProfile.Group == null - ? throw new InvalidOperationException("GroupProfile.Group is null when converting to DTO.") - : new GroupProfileDto( - groupProfile.Group.ToGroupData(), + var groupData = groupProfile.Group?.ToGroupData(); + + return new GroupProfileDto( + groupData, groupProfile.Description, groupProfile.Tags, groupProfile.Base64GroupProfileImage, @@ -27,16 +40,25 @@ public static class Extensions public static GroupData ToGroupData(this Group group) { + if (group == null) + return null; + return new GroupData(group.GID, group.Alias, group.CreatedDate); } public static UserData ToUserData(this GroupPair pair) { + if (pair == null) + return null; + return new UserData(pair.GroupUser.UID, pair.GroupUser.Alias); } public static UserData ToUserData(this User user) { + if (user == null) + return null; + return new UserData(user.UID, user.Alias); }