diff --git a/apps/server-net/.editorconfig b/apps/server-net/.editorconfig new file mode 100644 index 0000000..a078cf2 --- /dev/null +++ b/apps/server-net/.editorconfig @@ -0,0 +1,6 @@ +root = true + +[*.cs] +csharp_prefer_braces = true:warning +csharp_style_namespace_declarations = file_scoped:warning +dotnet_diagnostic.IDE0011.severity = warning diff --git a/apps/server-net/FormatFixer/FormatFixer.csproj b/apps/server-net/FormatFixer/FormatFixer.csproj new file mode 100644 index 0000000..ed9781c --- /dev/null +++ b/apps/server-net/FormatFixer/FormatFixer.csproj @@ -0,0 +1,10 @@ + + + + Exe + net10.0 + enable + enable + + + diff --git a/apps/server-net/FormatFixer/Program.cs b/apps/server-net/FormatFixer/Program.cs new file mode 100644 index 0000000..0fedeb3 --- /dev/null +++ b/apps/server-net/FormatFixer/Program.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; + +namespace FormatFixer +{ + class Program + { + static void Main(string[] args) + { + var srcPath = @"e:\GIT\forkmessager\apps\server-net\src"; + var files = Directory.GetFiles(srcPath, "*.cs", SearchOption.AllDirectories); + foreach (var file in files) + { + var lines = File.ReadAllLines(file); + bool changed = false; + for (int i = 0; i < lines.Length; i++) + { + var line = lines[i]; + var stripped = line.TrimStart(); + if ((stripped.StartsWith("if (") || stripped.StartsWith("if(") || + stripped.StartsWith("foreach (") || stripped.StartsWith("foreach(")) + && stripped.EndsWith(";")) + { + // Check if it's already a block + if (stripped.Contains("{")) continue; + + int parenCount = 0; + bool inString = false; + int firstParenIdx = line.IndexOf('('); + int condEndIdx = -1; + + for (int j = firstParenIdx; j < line.Length; j++) + { + char c = line[j]; + if (c == '"' && line[j - 1] != '\\') + { + inString = !inString; + } + else if (!inString) + { + if (c == '(') parenCount++; + else if (c == ')') + { + parenCount--; + if (parenCount == 0) + { + condEndIdx = j; + break; + } + } + } + } + + if (condEndIdx != -1) + { + var statement = line.Substring(condEndIdx + 1).Trim(); + if (!string.IsNullOrEmpty(statement) && !statement.StartsWith("{") && statement.EndsWith(";")) + { + var indent = line.Substring(0, line.Length - line.TrimStart().Length); + var newLine1 = line.Substring(0, condEndIdx + 1); + var newLine2 = indent + "{"; + var newLine3 = indent + " " + statement; + var newLine4 = indent + "}"; + + lines[i] = newLine1 + Environment.NewLine + newLine2 + Environment.NewLine + newLine3 + Environment.NewLine + newLine4; + changed = true; + } + } + } + } + if (changed) + { + File.WriteAllText(file, string.Join(Environment.NewLine, lines)); + Console.WriteLine("Fixed: " + file); + } + } + Console.WriteLine("Formatting complete."); + } + } +} diff --git a/apps/server-net/src/Host/Application/Admin/Commands/CleanRun/CleanRunCommand.cs b/apps/server-net/src/Host/Application/Admin/Commands/CleanRun/CleanRunCommand.cs index cdb026e..11be342 100644 --- a/apps/server-net/src/Host/Application/Admin/Commands/CleanRun/CleanRunCommand.cs +++ b/apps/server-net/src/Host/Application/Admin/Commands/CleanRun/CleanRunCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Collections.Generic; using System.Threading; @@ -57,9 +57,18 @@ internal sealed class CleanRunCommandHandler : ICommandHandler !string.IsNullOrEmpty(u.Avatar)) .Select(u => u.Avatar!); - foreach (var u in activeMessageUrls) validUrls.Add(u!); - foreach (var u in activeChatUrls) validUrls.Add(u); - foreach (var u in activeUserUrls) validUrls.Add(u); + foreach (var u in activeMessageUrls) + { + validUrls.Add(u!); + } + foreach (var u in activeChatUrls) + { + validUrls.Add(u); + } + foreach (var u in activeUserUrls) + { + validUrls.Add(u); + } var validFileIds = validUrls .Where(u => u.Contains("/api/files/")) @@ -82,4 +91,4 @@ internal sealed class CleanRunCommandHandler : ICommandHandler> Handle(ResetUserPasswordCommand request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } if (string.IsNullOrWhiteSpace(request.NewPassword)) return Result.Failure(new Error("InvalidPassword", "Password cannot be empty")); @@ -37,4 +40,4 @@ internal sealed class ResetUserPasswordCommandHandler : ICommandHandler !string.IsNullOrEmpty(u.Avatar)) .Select(u => u.Avatar!); - foreach (var u in activeMessageUrls) validUrls.Add(u!); - foreach (var u in activeChatUrls) validUrls.Add(u); - foreach (var u in activeUserUrls) validUrls.Add(u); + foreach (var u in activeMessageUrls) + { + validUrls.Add(u!); + } + foreach (var u in activeChatUrls) + { + validUrls.Add(u); + } + foreach (var u in activeUserUrls) + { + validUrls.Add(u); + } var validFileIds = validUrls .Where(u => u.Contains("/api/files/")) @@ -84,4 +93,4 @@ internal sealed class CleanDryRunQueryHandler : IQueryHandler> Handle(GetUserDetailsQuery request, CancellationToken cancellationToken) { var targetUser = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (targetUser == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (targetUser == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } var messagesCount = await _chatsDbContext.Messages.CountAsync(m => m.SenderId == request.UserId, cancellationToken); @@ -69,4 +72,4 @@ internal sealed class GetUserDetailsQueryHandler : IQueryHandler> Handle(AddStoryReactionCommand request, CancellationToken cancellationToken) { var story = await _context.Stories.FindAsync(new object[] { request.StoryId }, cancellationToken); - if (story == null) return Result.Failure(new Error("Story.NotFound", "Story not found")); + if (story == null) + { + return Result.Failure(new Error("Story.NotFound", "Story not found")); + } var existing = await _context.StoryReactions .FirstOrDefaultAsync(r => r.StoryId == request.StoryId && r.UserId == request.UserId && r.Emoji == request.Emoji, cancellationToken); - if (existing != null) return Result.Success(new MessageResponse("Reaction already exists")); + if (existing != null) + { + return Result.Success(new MessageResponse("Reaction already exists")); + } var reaction = new StoryReaction(request.StoryId, request.UserId, request.Emoji); _context.StoryReactions.Add(reaction); @@ -103,7 +109,10 @@ internal sealed class AddStoryReactionCommandHandler : ICommandHandler "🖼 Фото", @@ -119,10 +128,13 @@ internal sealed class AddStoryReactionCommandHandler : ICommandHandler m.UserId == userId2)); - if (personalChat != null) return personalChat.Id; + if (personalChat != null) + { + return personalChat.Id; + } var command = new Knot.Modules.Chats.Application.Chats.Create.CreateChatCommand(string.Empty, ChatType.Personal, new List { userId1, userId2 }); var result = await _sender.Send(command, cancellationToken); return result.Value; } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Application/Stories/Commands/AddStoryReply/AddStoryReplyCommand.cs b/apps/server-net/src/Host/Application/Stories/Commands/AddStoryReply/AddStoryReplyCommand.cs index 88656a4..7e77d23 100644 --- a/apps/server-net/src/Host/Application/Stories/Commands/AddStoryReply/AddStoryReplyCommand.cs +++ b/apps/server-net/src/Host/Application/Stories/Commands/AddStoryReply/AddStoryReplyCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -47,7 +47,10 @@ internal sealed class AddStoryReplyCommandHandler : ICommandHandler> Handle(AddStoryReplyCommand request, CancellationToken cancellationToken) { var story = await _context.Stories.FindAsync(new object[] { request.StoryId }, cancellationToken); - if (story == null) return Result.Failure(new Error("Story.NotFound", "Story not found")); + if (story == null) + { + return Result.Failure(new Error("Story.NotFound", "Story not found")); + } var reply = new StoryReply(request.StoryId, request.UserId, request.Content); _context.StoryReplies.Add(reply); @@ -89,7 +92,10 @@ internal sealed class AddStoryReplyCommandHandler : ICommandHandler "�� Фото", @@ -105,10 +111,13 @@ internal sealed class AddStoryReplyCommandHandler : ICommandHandler m.UserId == userId2)); - if (personalChat != null) return personalChat.Id; + if (personalChat != null) + { + return personalChat.Id; + } var command = new Knot.Modules.Chats.Application.Chats.Create.CreateChatCommand(string.Empty, ChatType.Personal, new List { userId1, userId2 }); var result = await _sender.Send(command, cancellationToken); return result.Value; } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Application/Stories/Commands/DeleteStory/DeleteStoryCommand.cs b/apps/server-net/src/Host/Application/Stories/Commands/DeleteStory/DeleteStoryCommand.cs index 04de990..2724e5c 100644 --- a/apps/server-net/src/Host/Application/Stories/Commands/DeleteStory/DeleteStoryCommand.cs +++ b/apps/server-net/src/Host/Application/Stories/Commands/DeleteStory/DeleteStoryCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; using MediatR; @@ -22,12 +22,18 @@ internal sealed class DeleteStoryCommandHandler : ICommandHandler> Handle(DeleteStoryCommand request, CancellationToken cancellationToken) { var story = await _context.Stories.FindAsync(new object[] { request.StoryId }, cancellationToken); - if (story == null) return Result.Failure(new Error("Story.NotFound", "Story not found")); - if (story.UserId != request.UserId) return Result.Failure(new Error("Unauthorized", "Unauthorized")); + if (story == null) + { + return Result.Failure(new Error("Story.NotFound", "Story not found")); + } + if (story.UserId != request.UserId) + { + return Result.Failure(new Error("Unauthorized", "Unauthorized")); + } _context.Stories.Remove(story); await _context.SaveChangesAsync(cancellationToken); return Result.Success(new MessageResponse("Story deleted")); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Application/Stories/Commands/RemoveStoryReaction/RemoveStoryReactionCommand.cs b/apps/server-net/src/Host/Application/Stories/Commands/RemoveStoryReaction/RemoveStoryReactionCommand.cs index 5f8416b..98f6547 100644 --- a/apps/server-net/src/Host/Application/Stories/Commands/RemoveStoryReaction/RemoveStoryReactionCommand.cs +++ b/apps/server-net/src/Host/Application/Stories/Commands/RemoveStoryReaction/RemoveStoryReactionCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -26,11 +26,14 @@ internal sealed class RemoveStoryReactionCommandHandler : ICommandHandler r.StoryId == request.StoryId && r.UserId == request.UserId && r.Emoji == request.Emoji, cancellationToken); - if (reaction == null) return Result.Success(new MessageResponse("Reaction not found")); + if (reaction == null) + { + return Result.Success(new MessageResponse("Reaction not found")); + } _context.StoryReactions.Remove(reaction); await _context.SaveChangesAsync(cancellationToken); return Result.Success(new MessageResponse("Reaction removed")); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Application/Stories/Commands/ViewStory/ViewStoryCommand.cs b/apps/server-net/src/Host/Application/Stories/Commands/ViewStory/ViewStoryCommand.cs index 73a4945..05ce334 100644 --- a/apps/server-net/src/Host/Application/Stories/Commands/ViewStory/ViewStoryCommand.cs +++ b/apps/server-net/src/Host/Application/Stories/Commands/ViewStory/ViewStoryCommand.cs @@ -36,7 +36,10 @@ internal sealed class ViewStoryCommandHandler : ICommandHandler s.Viewers) .FirstOrDefaultAsync(s => s.Id == request.StoryId, cancellationToken); - if (story == null) return Result.Failure(new Error("Story.NotFound", "Story not found")); + if (story == null) + { + return Result.Failure(new Error("Story.NotFound", "Story not found")); + } if (story.UserId == request.UserId) { @@ -70,4 +73,4 @@ internal sealed class ViewStoryCommandHandler : ICommandHandler { - if (r.User.Id == request.UserId) return 0; + if (r.User.Id == request.UserId) + { + return 0; + } return 1; }).ToList()); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Application/Stories/Queries/GetStoryReplies/GetStoryRepliesQuery.cs b/apps/server-net/src/Host/Application/Stories/Queries/GetStoryReplies/GetStoryRepliesQuery.cs index 4f9f6ef..50e9402 100644 --- a/apps/server-net/src/Host/Application/Stories/Queries/GetStoryReplies/GetStoryRepliesQuery.cs +++ b/apps/server-net/src/Host/Application/Stories/Queries/GetStoryReplies/GetStoryRepliesQuery.cs @@ -31,14 +31,23 @@ internal sealed class GetStoryRepliesQueryHandler : IQueryHandler s.Replies) .FirstOrDefaultAsync(s => s.Id == request.StoryId, cancellationToken); - if (story == null) return Result.Failure>(new Error("Story.NotFound", "Story not found")); - if (story.UserId != request.UserId) return Result.Failure>(new Error("Unauthorized", "Unauthorized")); + if (story == null) + { + return Result.Failure>(new Error("Story.NotFound", "Story not found")); + } + if (story.UserId != request.UserId) + { + return Result.Failure>(new Error("Unauthorized", "Unauthorized")); + } var replies = new List(); foreach (var reply in story.Replies.OrderBy(r => r.CreatedAt)) { var user = await _userRepository.GetByIdAsync(reply.UserId, cancellationToken); - if (user == null) continue; + if (user == null) + { + continue; + } replies.Add(new StoryReplyDto( reply.Id, @@ -53,4 +62,4 @@ internal sealed class GetStoryRepliesQueryHandler : IQueryHandler s.Viewers) .FirstOrDefaultAsync(s => s.Id == request.StoryId, cancellationToken); - if (story == null) return Result.Failure>(new Error("Story.NotFound", "Story not found")); - if (story.UserId != request.UserId) return Result.Failure>(new Error("Unauthorized", "Unauthorized")); + if (story == null) + { + return Result.Failure>(new Error("Story.NotFound", "Story not found")); + } + if (story.UserId != request.UserId) + { + return Result.Failure>(new Error("Unauthorized", "Unauthorized")); + } var viewerIds = story.Viewers.Select(v => v.UserId).ToList(); var viewers = new List(); @@ -40,7 +46,10 @@ internal sealed class GetStoryViewersQueryHandler : IQueryHandler v.UserId == viewerId); @@ -55,4 +64,4 @@ internal sealed class GetStoryViewersQueryHandler : IQueryHandler(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } var result = new StoryGroupDto( new StoryUserDto(user.Id, user.Username, user.DisplayName, user.Avatar), @@ -59,4 +62,4 @@ internal sealed class GetUserStoriesQueryHandler : IQueryHandler GetUserDetails(Guid id, CancellationToken ct) { var result = await _sender.Send(new GetUserDetailsQuery(id), ct); - if (result.IsFailure) return NotFound("User not found"); + if (result.IsFailure) + { + return NotFound("User not found"); + } return Ok(result.Value); } @@ -104,4 +107,4 @@ public class AdminController : ControllerBase var result = await _sender.Send(new CleanRunCommand(fileStorage, identityDb), ct); return Ok(result.Value); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Controllers/AuthController.cs b/apps/server-net/src/Host/Controllers/AuthController.cs index 7d48ae4..b1fbe48 100644 --- a/apps/server-net/src/Host/Controllers/AuthController.cs +++ b/apps/server-net/src/Host/Controllers/AuthController.cs @@ -33,7 +33,10 @@ public sealed class AuthController : ControllerBase public async Task GetMe([FromServices] IUserContext userContext, CancellationToken ct) { var result = await _sender.Send(new GetMeQuery(userContext.UserId), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(new { User = result.Value.User }); } @@ -44,4 +47,4 @@ public sealed class AuthController : ControllerBase if (result.IsFailure) return Unauthorized(new { error = result.Error.Code ?? result.Error.Description }); return Ok(result.Value); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Controllers/ChatsController.cs b/apps/server-net/src/Host/Controllers/ChatsController.cs index 6ec8d0d..a7aadc5 100644 --- a/apps/server-net/src/Host/Controllers/ChatsController.cs +++ b/apps/server-net/src/Host/Controllers/ChatsController.cs @@ -41,7 +41,10 @@ public sealed class ChatsController : ControllerBase public async Task GetChats(CancellationToken ct) { var result = await _sender.Send(new GetChatsQuery(_userContext.UserId), ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } return Ok(result.Value); } @@ -50,7 +53,10 @@ public sealed class ChatsController : ControllerBase { var command = new CreateChatCommand(request.Name, request.Type, request.MemberIds); var result = await _sender.Send(command, ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -61,7 +67,10 @@ public sealed class ChatsController : ControllerBase { var command = new CreateChatCommand(string.Empty, ChatType.Personal, new List { _userContext.UserId, request.UserId }); var result = await _sender.Send(command, ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -79,7 +88,10 @@ public sealed class ChatsController : ControllerBase var command = new CreateChatCommand(request.Name, ChatType.Group, memberIds); var result = await _sender.Send(command, ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -89,7 +101,10 @@ public sealed class ChatsController : ControllerBase public async Task GetOrCreateFavorites(CancellationToken ct) { var result = await _sender.Send(new GetOrCreateFavoritesCommand(_userContext.UserId), ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -99,7 +114,10 @@ public sealed class ChatsController : ControllerBase public async Task UpdateChat(Guid id, [FromBody] UpdateChatRequest request, CancellationToken ct) { var result = await _sender.Send(new UpdateChatCommand(id, _userContext.UserId, request.Name, request.Description), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -111,7 +129,10 @@ public sealed class ChatsController : ControllerBase var result = await _sender.Send(new LeaveOrDeleteChatCommand(id, _userContext.UserId), ct); if (result.IsFailure) { - if (result.Error.Code == "Unauthorized") return Forbid(); + if (result.Error.Code == "Unauthorized") + { + return Forbid(); + } return NotFound(); } return Ok(result.Value); @@ -121,7 +142,10 @@ public sealed class ChatsController : ControllerBase public async Task ClearChat(Guid id, CancellationToken ct) { var result = await _sender.Send(new ClearChatCommand(id, _userContext.UserId), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(result.Value); } @@ -129,7 +153,10 @@ public sealed class ChatsController : ControllerBase public async Task TogglePin(Guid id, CancellationToken ct) { var result = await _sender.Send(new TogglePinCommand(id, _userContext.UserId), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(result.Value); } @@ -137,7 +164,10 @@ public sealed class ChatsController : ControllerBase public async Task AddMembers(Guid id, [FromBody] AddMembersRequest request, CancellationToken ct) { var result = await _sender.Send(new AddMembersCommand(id, _userContext.UserId, request.UserIds.ToList()), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -147,7 +177,10 @@ public sealed class ChatsController : ControllerBase public async Task RemoveMember(Guid id, Guid userId, CancellationToken ct) { var result = await _sender.Send(new RemoveMemberCommand(id, _userContext.UserId, userId), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -156,12 +189,18 @@ public sealed class ChatsController : ControllerBase [HttpPost("{id:guid}/avatar")] public async Task UploadGroupAvatar(Guid id, Microsoft.AspNetCore.Http.IFormFile avatar, CancellationToken ct) { - if (avatar == null || avatar.Length == 0) return BadRequest("No file"); + if (avatar == null || avatar.Length == 0) + { + return BadRequest("No file"); + } using var stream = avatar.OpenReadStream(); var result = await _sender.Send(new UploadGroupAvatarCommand(id, _userContext.UserId, avatar.FileName, avatar.ContentType, stream), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -170,12 +209,18 @@ public sealed class ChatsController : ControllerBase [HttpPost("{id:guid}/avatar/crop")] public async Task CropGroupAvatar(Guid id, [FromForm] Microsoft.AspNetCore.Http.IFormFile avatar, [FromForm] int x, [FromForm] int y, [FromForm] int width, [FromForm] int height, CancellationToken ct) { - if (avatar == null || avatar.Length == 0) return BadRequest("No file"); + if (avatar == null || avatar.Length == 0) + { + return BadRequest("No file"); + } using var stream = avatar.OpenReadStream(); var result = await _sender.Send(new CropGroupAvatarCommand(id, _userContext.UserId, avatar.FileName, avatar.ContentType, stream, x, y, width, height), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); @@ -185,9 +230,12 @@ public sealed class ChatsController : ControllerBase public async Task RemoveGroupAvatar(Guid id, CancellationToken ct) { var result = await _sender.Send(new RemoveGroupAvatarCommand(id, _userContext.UserId), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct); return Ok(chatResult.Value); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Controllers/FriendsController.cs b/apps/server-net/src/Host/Controllers/FriendsController.cs index ee45036..af0da69 100644 --- a/apps/server-net/src/Host/Controllers/FriendsController.cs +++ b/apps/server-net/src/Host/Controllers/FriendsController.cs @@ -27,7 +27,10 @@ public sealed class FriendsController : ControllerBase public async Task GetFriends(CancellationToken ct) { var result = await _sender.Send(new GetFriendsQuery(_userContext.UserId), ct); - if (result.IsFailure) return BadRequest(result.Error); + if (result.IsFailure) + { + return BadRequest(result.Error); + } return Ok(result.Value); } @@ -35,7 +38,10 @@ public sealed class FriendsController : ControllerBase public async Task GetRequests(CancellationToken ct) { var result = await _sender.Send(new GetIncomingRequestsQuery(_userContext.UserId), ct); - if (result.IsFailure) return BadRequest(result.Error); + if (result.IsFailure) + { + return BadRequest(result.Error); + } return Ok(result.Value); } @@ -43,7 +49,10 @@ public sealed class FriendsController : ControllerBase public async Task GetOutgoingRequests(CancellationToken ct) { var result = await _sender.Send(new GetOutgoingRequestsQuery(_userContext.UserId), ct); - if (result.IsFailure) return BadRequest(result.Error); + if (result.IsFailure) + { + return BadRequest(result.Error); + } return Ok(result.Value); } @@ -51,7 +60,10 @@ public sealed class FriendsController : ControllerBase public async Task SendRequest([FromBody] Host.Models.SendFriendRequest request, CancellationToken ct) { var result = await _sender.Send(new SendFriendRequestCommand(_userContext.UserId, request.FriendId), ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } return Ok(new { status = "pending" }); } @@ -59,7 +71,10 @@ public sealed class FriendsController : ControllerBase public async Task AcceptRequest(Guid id, CancellationToken ct) { var result = await _sender.Send(new AcceptFriendRequestCommand(_userContext.UserId, id), ct); - if (result.IsFailure) return NotFound(result.Error.Description); + if (result.IsFailure) + { + return NotFound(result.Error.Description); + } return Ok(new { id = result.Value }); } @@ -67,7 +82,10 @@ public sealed class FriendsController : ControllerBase public async Task DeclineRequest(Guid id, CancellationToken ct) { var result = await _sender.Send(new DeclineFriendRequestCommand(_userContext.UserId, id), ct); - if (result.IsFailure) return NotFound(result.Error.Description); + if (result.IsFailure) + { + return NotFound(result.Error.Description); + } return Ok(new Knot.Shared.Kernel.SuccessResponse(true)); } @@ -75,7 +93,10 @@ public sealed class FriendsController : ControllerBase public async Task GetStatus(Guid userId, CancellationToken ct) { var result = await _sender.Send(new GetFriendshipStatusQuery(_userContext.UserId, userId), ct); - if (result.IsFailure) return BadRequest(result.Error); + if (result.IsFailure) + { + return BadRequest(result.Error); + } return Ok(result.Value); } @@ -83,7 +104,10 @@ public sealed class FriendsController : ControllerBase public async Task RemoveFriend(Guid id, CancellationToken ct) { var result = await _sender.Send(new RemoveFriendCommand(_userContext.UserId, id), ct); - if (result.IsFailure) return NotFound(result.Error.Description); + if (result.IsFailure) + { + return NotFound(result.Error.Description); + } return Ok(new Knot.Shared.Kernel.SuccessResponse(true)); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Controllers/MessagesController.cs b/apps/server-net/src/Host/Controllers/MessagesController.cs index 9ff06ec..bb9b34e 100644 --- a/apps/server-net/src/Host/Controllers/MessagesController.cs +++ b/apps/server-net/src/Host/Controllers/MessagesController.cs @@ -34,7 +34,10 @@ public sealed class MessagesController : ControllerBase public async Task GetMessages(Guid chatId, [FromQuery] string? cursor, CancellationToken ct = default) { var result = await _sender.Send(new GetMessagesQuery(_userContext.UserId, chatId, cursor), ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } return Ok(result.Value); } @@ -42,21 +45,30 @@ public sealed class MessagesController : ControllerBase public async Task GetSearch([FromQuery] string q, [FromQuery] Guid? chatId, CancellationToken ct) { var result = await _sender.Send(new SearchMessagesQuery(_userContext.UserId, q, chatId), ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } return Ok(result.Value); } [HttpPost("upload")] public async Task UploadFile(IFormFile file, CancellationToken ct) { - if (file == null || file.Length == 0) return BadRequest("No file uploaded"); + if (file == null || file.Length == 0) + { + return BadRequest("No file uploaded"); + } using var stream = file.OpenReadStream(); var result = await _sender.Send(new UploadFileCommand(file.FileName, file.ContentType, file.Length, stream), ct); if (result.IsFailure) { - if (result.Error.Code == "File.TooLarge") return StatusCode(413, result.Error.Description); + if (result.Error.Code == "File.TooLarge") + { + return StatusCode(413, result.Error.Description); + } return BadRequest(result.Error.Description); } @@ -67,7 +79,10 @@ public sealed class MessagesController : ControllerBase public async Task GetSharedMedia(Guid chatId, [FromQuery] string? type, CancellationToken ct) { var result = await _sender.Send(new GetSharedMediaQuery(_userContext.UserId, chatId, type), ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } return Ok(result.Value); } @@ -89,8 +104,11 @@ public sealed class MessagesController : ControllerBase var result = await _sender.Send(command, ct); - if (result.IsFailure) return BadRequest(result.Error.Description); + if (result.IsFailure) + { + return BadRequest(result.Error.Description); + } return Ok(result.Value); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Controllers/StoriesController.cs b/apps/server-net/src/Host/Controllers/StoriesController.cs index f2e9644..3ea3174 100644 --- a/apps/server-net/src/Host/Controllers/StoriesController.cs +++ b/apps/server-net/src/Host/Controllers/StoriesController.cs @@ -51,7 +51,10 @@ public sealed class StoriesController : ControllerBase public async Task GetUserStories(Guid userId, CancellationToken ct) { var result = await _sender.Send(new GetUserStoriesQuery(_userContext.UserId, userId), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(result.Value); } @@ -59,7 +62,10 @@ public sealed class StoriesController : ControllerBase public async Task ViewStory(Guid id, CancellationToken ct) { var result = await _sender.Send(new ViewStoryCommand(_userContext.UserId, id), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(result.Value); } @@ -69,7 +75,10 @@ public sealed class StoriesController : ControllerBase var result = await _sender.Send(new GetStoryViewersQuery(_userContext.UserId, id), ct); if (result.IsFailure) { - if (result.Error.Code == "Unauthorized") return Forbid(); + if (result.Error.Code == "Unauthorized") + { + return Forbid(); + } return NotFound(); } return Ok(result.Value); @@ -79,7 +88,10 @@ public sealed class StoriesController : ControllerBase public async Task AddReaction(Guid id, [FromBody] AddStoryReactionRequest request, CancellationToken ct) { var result = await _sender.Send(new AddStoryReactionCommand(_userContext.UserId, id, request.Emoji), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(result.Value); } @@ -87,7 +99,10 @@ public sealed class StoriesController : ControllerBase public async Task RemoveReaction(Guid id, [FromBody] RemoveStoryReactionRequest request, CancellationToken ct) { var result = await _sender.Send(new RemoveStoryReactionCommand(_userContext.UserId, id, request.Emoji), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(result.Value); } @@ -95,7 +110,10 @@ public sealed class StoriesController : ControllerBase public async Task AddReply(Guid id, [FromBody] AddStoryReplyRequest request, CancellationToken ct) { var result = await _sender.Send(new AddStoryReplyCommand(_userContext.UserId, id, request.Content), ct); - if (result.IsFailure) return NotFound(); + if (result.IsFailure) + { + return NotFound(); + } return Ok(result.Value); } @@ -105,7 +123,10 @@ public sealed class StoriesController : ControllerBase var result = await _sender.Send(new GetStoryRepliesQuery(_userContext.UserId, id), ct); if (result.IsFailure) { - if (result.Error.Code == "Unauthorized") return Forbid(); + if (result.Error.Code == "Unauthorized") + { + return Forbid(); + } return NotFound(); } return Ok(result.Value); @@ -117,9 +138,12 @@ public sealed class StoriesController : ControllerBase var result = await _sender.Send(new DeleteStoryCommand(_userContext.UserId, id), ct); if (result.IsFailure) { - if (result.Error.Code == "Unauthorized") return Forbid(); + if (result.Error.Code == "Unauthorized") + { + return Forbid(); + } return NotFound(); } return Ok(result.Value); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Controllers/UsersController.cs b/apps/server-net/src/Host/Controllers/UsersController.cs index 29141fe..ac68fd8 100644 --- a/apps/server-net/src/Host/Controllers/UsersController.cs +++ b/apps/server-net/src/Host/Controllers/UsersController.cs @@ -31,7 +31,10 @@ public sealed class UsersController : ControllerBase public async Task Search([FromQuery] string q, CancellationToken ct) { var result = await _sender.Send(new SearchUsersQuery(q), ct); - if (result.IsFailure) return BadRequest(result.Error); + if (result.IsFailure) + { + return BadRequest(result.Error); + } return Ok(result.Value); } @@ -39,7 +42,10 @@ public sealed class UsersController : ControllerBase public async Task UpdateSettings([FromBody] UpdateSettingsRequest request, CancellationToken ct) { var result = await _sender.Send(new UpdateSettingsCommand(_userContext.UserId, request.HideStoryViews), ct); - if (result.IsFailure) return NotFound(result.Error); + if (result.IsFailure) + { + return NotFound(result.Error); + } return Ok(result.Value); } @@ -47,7 +53,10 @@ public sealed class UsersController : ControllerBase public async Task UploadAvatar(IFormFile avatar, CancellationToken ct) { var fileToUpload = avatar ?? Request.Form.Files.FirstOrDefault(); - if (fileToUpload == null || fileToUpload.Length == 0) return BadRequest("No file uploaded"); + if (fileToUpload == null || fileToUpload.Length == 0) + { + return BadRequest("No file uploaded"); + } using var stream = fileToUpload.OpenReadStream(); var command = new UploadAvatarCommand( @@ -58,14 +67,20 @@ public sealed class UsersController : ControllerBase ); var result = await _sender.Send(command, ct); - if (result.IsFailure) return NotFound(result.Error); + if (result.IsFailure) + { + return NotFound(result.Error); + } return Ok(result.Value); } [HttpPost("avatar/crop")] public async Task CropAvatar([FromForm] IFormFile avatar, [FromForm] int x, [FromForm] int y, [FromForm] int width, [FromForm] int height, CancellationToken ct) { - if (avatar == null || avatar.Length == 0) return BadRequest("No file uploaded"); + if (avatar == null || avatar.Length == 0) + { + return BadRequest("No file uploaded"); + } using var stream = avatar.OpenReadStream(); var command = new CropAvatarCommand( @@ -77,7 +92,10 @@ public sealed class UsersController : ControllerBase ); var result = await _sender.Send(command, ct); - if (result.IsFailure) return NotFound(result.Error); + if (result.IsFailure) + { + return NotFound(result.Error); + } return Ok(result.Value); } @@ -85,7 +103,10 @@ public sealed class UsersController : ControllerBase public async Task DeleteAvatar(CancellationToken ct) { var result = await _sender.Send(new DeleteAvatarCommand(_userContext.UserId), ct); - if (result.IsFailure) return NotFound(result.Error); + if (result.IsFailure) + { + return NotFound(result.Error); + } return Ok(result.Value); } @@ -93,7 +114,10 @@ public sealed class UsersController : ControllerBase public async Task UpdateProfile([FromBody] UpdateProfileRequest request, CancellationToken ct) { var result = await _sender.Send(new UpdateProfileCommand(_userContext.UserId, request.DisplayName, request.Bio, request.Birthday), ct); - if (result.IsFailure) return NotFound(result.Error); + if (result.IsFailure) + { + return NotFound(result.Error); + } return Ok(result.Value); } @@ -101,7 +125,10 @@ public sealed class UsersController : ControllerBase public async Task GetUser(Guid id, CancellationToken ct) { var result = await _sender.Send(new GetUserQuery(id), ct); - if (result.IsFailure) return NotFound(result.Error); + if (result.IsFailure) + { + return NotFound(result.Error); + } return Ok(result.Value); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Host/Endpoints/FederationEndpoints.cs b/apps/server-net/src/Host/Endpoints/FederationEndpoints.cs index a331f74..b8e8276 100644 --- a/apps/server-net/src/Host/Endpoints/FederationEndpoints.cs +++ b/apps/server-net/src/Host/Endpoints/FederationEndpoints.cs @@ -21,12 +21,21 @@ public sealed class FederationEndpoints : ICarterModule group.MapPost("/handshake", async ([FromBody] Host.Application.Federation.Commands.HandshakeRequest request, ISender sender, CancellationToken ct) => { var result = await sender.Send(new Host.Application.Federation.Commands.HandshakeFederationCommand(request), ct); - if (result.IsSuccess) return Results.Ok(result.Value); + if (result.IsSuccess) + { + return Results.Ok(result.Value); + } - if (result.Error.Code == "Unauthorized") return Results.Forbid(); - if (result.Error.Code == Knot.Shared.Kernel.Constants.Errors.DisabledByAdmin) return Results.StatusCode(503); + if (result.Error.Code == "Unauthorized") + { + return Results.Forbid(); + } + if (result.Error.Code == Knot.Shared.Kernel.Constants.Errors.DisabledByAdmin) + { + return Results.StatusCode(503); + } return Results.BadRequest(new { error = result.Error.Description }); }); } -} +} \ No newline at end of file diff --git a/apps/server-net/src/Modules/Chats/Application/Chats/Avatar/Avatar.cs b/apps/server-net/src/Modules/Chats/Application/Chats/Avatar/Avatar.cs index e9f501a..03447ac 100644 --- a/apps/server-net/src/Modules/Chats/Application/Chats/Avatar/Avatar.cs +++ b/apps/server-net/src/Modules/Chats/Application/Chats/Avatar/Avatar.cs @@ -32,7 +32,9 @@ internal sealed class UploadGroupAvatarCommandHandler : ICommandHandler m.UserId == request.UserId)) + { return Result.Failure(new Error("Chat.NotFound", "Chat not found or access denied")); + } var fileId = await _fileStorage.UploadFileAsync(request.FileStream, request.FileName, request.ContentType); var url = $"/api/files/{fileId}"; @@ -64,7 +66,9 @@ internal sealed class CropGroupAvatarCommandHandler : ICommandHandler m.UserId == request.UserId)) + { return Result.Failure(new Error("Chat.NotFound", "Chat not found or access denied")); + } string url; @@ -112,7 +116,9 @@ internal sealed class RemoveGroupAvatarCommandHandler : ICommandHandler m.UserId == request.UserId)) + { return Result.Failure(new Error("Chat.NotFound", "Chat not found or access denied")); + } chat.UpdateAvatar(null); _chatRepository.Update(chat); diff --git a/apps/server-net/src/Modules/Chats/Application/Chats/Clear/ClearChat.cs b/apps/server-net/src/Modules/Chats/Application/Chats/Clear/ClearChat.cs index 5f9b6b0..6463e25 100644 --- a/apps/server-net/src/Modules/Chats/Application/Chats/Clear/ClearChat.cs +++ b/apps/server-net/src/Modules/Chats/Application/Chats/Clear/ClearChat.cs @@ -24,7 +24,9 @@ internal sealed class ClearChatCommandHandler : ICommandHandler m.UserId == request.UserId)) + { return Result.Failure(new Error("Chat.NotFound", "Chat not found or access denied")); + } // Currently a placeholder return Result.Success(new MessageResponse("Cleared")); diff --git a/apps/server-net/src/Modules/Chats/Application/Chats/GetChatById/GetChatById.cs b/apps/server-net/src/Modules/Chats/Application/Chats/GetChatById/GetChatById.cs index 613c527..a8f73db 100644 --- a/apps/server-net/src/Modules/Chats/Application/Chats/GetChatById/GetChatById.cs +++ b/apps/server-net/src/Modules/Chats/Application/Chats/GetChatById/GetChatById.cs @@ -29,7 +29,10 @@ internal sealed class GetChatByIdQueryHandler : IQueryHandler> Handle(GetChatByIdQuery request, CancellationToken cancellationToken) { var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken); - if (chat == null) return Result.Success(null); + if (chat == null) + { + return Result.Success(null); + } if (!chat.Members.Any(m => m.UserId == request.UserId)) { @@ -37,14 +40,20 @@ internal sealed class GetChatByIdQueryHandler : IQueryHandler(); - foreach (var m in chat.Members) userIdsToFetch.Add(m.UserId); + foreach (var m in chat.Members) + { + userIdsToFetch.Add(m.UserId); + } var chatMessages = await _messageRepository.GetChatMessagesAsync(chat.Id, 1, 0, cancellationToken); var mFirst = chatMessages.FirstOrDefault(); if (mFirst != null) { userIdsToFetch.Add(mFirst.SenderId); - foreach (var r in mFirst.Reactions) userIdsToFetch.Add(r.UserId); + foreach (var r in mFirst.Reactions) + { + userIdsToFetch.Add(r.UserId); + } } var usersInfo = await _userProvider.GetUsersInfoAsync(userIdsToFetch, cancellationToken); diff --git a/apps/server-net/src/Modules/Chats/Application/Chats/GetChats/GetChats.cs b/apps/server-net/src/Modules/Chats/Application/Chats/GetChats/GetChats.cs index 392161e..9ac35b1 100644 --- a/apps/server-net/src/Modules/Chats/Application/Chats/GetChats/GetChats.cs +++ b/apps/server-net/src/Modules/Chats/Application/Chats/GetChats/GetChats.cs @@ -36,14 +36,20 @@ internal sealed class GetChatsQueryHandler : IQueryHandler(); - foreach (var m in c.Members) userIdsToFetch.Add(m.UserId); + foreach (var m in c.Members) + { + userIdsToFetch.Add(m.UserId); + } var chatMessages = await _messageRepository.GetChatMessagesAsync(c.Id, 1, 0, cancellationToken); var mFirst = chatMessages.FirstOrDefault(); if (mFirst != null) { userIdsToFetch.Add(mFirst.SenderId); - foreach (var r in mFirst.Reactions) userIdsToFetch.Add(r.UserId); + foreach (var r in mFirst.Reactions) + { + userIdsToFetch.Add(r.UserId); + } } var usersInfo = await _userProvider.GetUsersInfoAsync(userIdsToFetch, cancellationToken); diff --git a/apps/server-net/src/Modules/Chats/Application/Chats/LeaveOrDelete/LeaveOrDeleteChat.cs b/apps/server-net/src/Modules/Chats/Application/Chats/LeaveOrDelete/LeaveOrDeleteChat.cs index 1a8edaa..1f0c0c0 100644 --- a/apps/server-net/src/Modules/Chats/Application/Chats/LeaveOrDelete/LeaveOrDeleteChat.cs +++ b/apps/server-net/src/Modules/Chats/Application/Chats/LeaveOrDelete/LeaveOrDeleteChat.cs @@ -25,10 +25,15 @@ internal sealed class LeaveOrDeleteChatCommandHandler : ICommandHandler> Handle(LeaveOrDeleteChatCommand request, CancellationToken cancellationToken) { var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken); - if (chat == null) return Result.Success(new SuccessResponse(true)); + if (chat == null) + { + return Result.Success(new SuccessResponse(true)); + } if (!chat.Members.Any(m => m.UserId == request.UserId)) + { return Result.Failure(new Error("Unauthorized", "Access denied")); + } if (chat.Type == ChatType.Group) { @@ -39,7 +44,7 @@ internal sealed class LeaveOrDeleteChatCommandHandler : ICommandHandler m.UserId == request.UserId)) + { return Result.Failure(new Error("Chat.NotFound", "Chat not found or access denied")); + } foreach (var userId in request.UserIdsToAdd) { @@ -57,7 +59,9 @@ internal sealed class RemoveMemberCommandHandler : ICommandHandler m.UserId == request.UserId)) + { return Result.Failure(new Error("Chat.NotFound", "Chat not found or access denied")); + } chat.RemoveMember(request.UserIdToRemove); _chatRepository.Update(chat); diff --git a/apps/server-net/src/Modules/Chats/Application/Chats/TogglePin/TogglePin.cs b/apps/server-net/src/Modules/Chats/Application/Chats/TogglePin/TogglePin.cs index 0739448..22337bd 100644 --- a/apps/server-net/src/Modules/Chats/Application/Chats/TogglePin/TogglePin.cs +++ b/apps/server-net/src/Modules/Chats/Application/Chats/TogglePin/TogglePin.cs @@ -27,11 +27,15 @@ internal sealed class TogglePinCommandHandler : ICommandHandler(new Error("Chat.NotFound", "Chat not found")); + } var member = chat.Members.FirstOrDefault(m => m.UserId == request.UserId); if (member == null) + { return Result.Failure(new Error("Chat.NotFound", "Member not found")); + } member.TogglePin(); _chatRepository.Update(chat); diff --git a/apps/server-net/src/Modules/Chats/Application/Chats/Update/UpdateChat.cs b/apps/server-net/src/Modules/Chats/Application/Chats/Update/UpdateChat.cs index 393c1e5..4c89b3f 100644 --- a/apps/server-net/src/Modules/Chats/Application/Chats/Update/UpdateChat.cs +++ b/apps/server-net/src/Modules/Chats/Application/Chats/Update/UpdateChat.cs @@ -25,12 +25,21 @@ internal sealed class UpdateChatCommandHandler : ICommandHandler> Handle(UpdateChatCommand request, CancellationToken cancellationToken) { var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken); - if (chat == null || !chat.Members.Any(m => m.UserId == request.UserId)) + if (chat == null || !chat.Members.Any(m => m.UserId == request.UserId)) + { return Result.Failure(new Error("Chat.NotFound", "Chat not found or access denied")); + } + + if (request.Name != null) + { + chat.UpdateName(request.Name); + } + + if (request.Description != null) + { + chat.UpdateDescription(request.Description); + } - if (request.Name != null) chat.UpdateName(request.Name); - if (request.Description != null) chat.UpdateDescription(request.Description); - _chatRepository.Update(chat); await _uow.SaveChangesAsync(cancellationToken); diff --git a/apps/server-net/src/Modules/Chats/Application/DTOs/SendMessageRequest.cs b/apps/server-net/src/Modules/Chats/Application/DTOs/SendMessageRequest.cs index 01d66e8..7cbfa31 100644 --- a/apps/server-net/src/Modules/Chats/Application/DTOs/SendMessageRequest.cs +++ b/apps/server-net/src/Modules/Chats/Application/DTOs/SendMessageRequest.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; namespace Knot.Modules.Chats.Application.DTOs; public sealed record SendMessageRequest( - string? Content, - string Type, + string? Content, + string Type, List? Attachments = null, Guid? ReplyToId = null, string? Quote = null, diff --git a/apps/server-net/src/Modules/Chats/Application/Messages/Delete/DeleteMessagesCommand.cs b/apps/server-net/src/Modules/Chats/Application/Messages/Delete/DeleteMessagesCommand.cs index 25fc868..4e66696 100644 --- a/apps/server-net/src/Modules/Chats/Application/Messages/Delete/DeleteMessagesCommand.cs +++ b/apps/server-net/src/Modules/Chats/Application/Messages/Delete/DeleteMessagesCommand.cs @@ -20,7 +20,7 @@ public sealed class DeleteMessagesCommandHandler : ICommandHandler _hubContext; public DeleteMessagesCommandHandler( - IMessageRepository messageRepository, + IMessageRepository messageRepository, IChatsUnitOfWork unitOfWork, IHubContext hubContext) { @@ -34,7 +34,10 @@ public sealed class DeleteMessagesCommandHandler : ICommandHandler { + var filteredMedia = m.Media.Where(media => + { var mediaType = media.Type?.ToLower() ?? "file"; var isGif = mediaType == "image" && (media.Url.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase) || media.Url.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)); - if (filterType == "media") return (mediaType == "image" || mediaType == "video") && !isGif; - if (filterType == "gifs") return isGif; - if (filterType == "files") return mediaType != "image" && mediaType != "video" && mediaType != "link"; + if (filterType == "media") + { + return (mediaType == "image" || mediaType == "video") && !isGif; + } + + if (filterType == "gifs") + { + return isGif; + } + + if (filterType == "files") + { + return mediaType != "image" && mediaType != "video" && mediaType != "link"; + } + return true; }).ToList(); diff --git a/apps/server-net/src/Modules/Chats/Application/Messages/Read/ReadMessagesCommandHandler.cs b/apps/server-net/src/Modules/Chats/Application/Messages/Read/ReadMessagesCommandHandler.cs index 5da1166..3dd9147 100644 --- a/apps/server-net/src/Modules/Chats/Application/Messages/Read/ReadMessagesCommandHandler.cs +++ b/apps/server-net/src/Modules/Chats/Application/Messages/Read/ReadMessagesCommandHandler.cs @@ -26,7 +26,7 @@ public sealed class ReadMessagesCommandHandler : ICommandHandler> Handle(UploadFileCommand request, CancellationToken cancellationToken) { - if (request.Length == 0) return Result.Failure(new Error("File.Empty", "No file uploaded")); + if (request.Length == 0) + { + return Result.Failure(new Error("File.Empty", "No file uploaded")); + } var maxMb = _settingsService.Current.MaxFileSizeMb; if (request.Length > maxMb * 1024 * 1024) + { return Result.Failure(new Error("File.TooLarge", $"File exceeds the maximum allowed size of {maxMb}MB.")); + } var fileId = await _fileStorage.UploadFileAsync(request.FileStream, request.FileName, request.ContentType); - + return Result.Success(new UploadFileResponseDto("/api/files/" + fileId, request.FileName, request.Length)); } } diff --git a/apps/server-net/src/Modules/Chats/Application/TelegramImport/AnalyzeImportCommand.cs b/apps/server-net/src/Modules/Chats/Application/TelegramImport/AnalyzeImportCommand.cs index c95ec2f..ed4861a 100644 --- a/apps/server-net/src/Modules/Chats/Application/TelegramImport/AnalyzeImportCommand.cs +++ b/apps/server-net/src/Modules/Chats/Application/TelegramImport/AnalyzeImportCommand.cs @@ -27,10 +27,14 @@ internal sealed class AnalyzeImportCommandHandler : ICommandHandler> Handle(AnalyzeImportCommand request, CancellationToken cancellationToken) { if (request.FileStream == null || request.FileStream.Length == 0) + { return Result.Failure(new Error("File.Empty", "No file uploaded")); - + } + if (!request.FileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) + { return Result.Failure(new Error("File.InvalidExtension", "Must be a ZIP archive")); + } var token = Guid.NewGuid(); var tempPath = Path.Combine(Path.GetTempPath(), $"{token}.zip"); @@ -54,7 +58,10 @@ internal sealed class AnalyzeImportCommandHandler : ICommandHandler> Handle(ExecuteImportCommand request, CancellationToken cancellationToken) { if (!TelegramImportState.TempZips.TryGetValue(request.Token, out var tempPath)) + { return Result.Failure(new Error("Import.Expired", "Session not found or expired")); + } if (!System.IO.File.Exists(tempPath)) + { return Result.Failure(new Error("Import.Missing", "ZIP file lost")); + } var myId = request.CurrentUserId; var targetUserIds = request.Mapping.Values.Distinct().Where(id => id != Guid.Empty).ToList(); - if (!targetUserIds.Contains(myId)) targetUserIds.Add(myId); + if (!targetUserIds.Contains(myId)) + { + targetUserIds.Add(myId); + } Guid chatId = Guid.Empty; var chatMembers = targetUserIds; @@ -71,7 +78,7 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler c.Type == ChatType.Personal && c.Members.All(m => chatMembers.Contains(m.UserId)) && c.Members.Count == chatMembers.Count); - + if (personalChat != null) { chatId = personalChat.Id; @@ -79,10 +86,18 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler id != myId); - if (friendId == Guid.Empty) friendId = myId; + if (friendId == Guid.Empty) + { + friendId = myId; + } + var command = new CreateChatCommand(string.Empty, ChatType.Personal, new List { myId, friendId }); var res = await _sender.Send(command, cancellationToken); - if (res.IsFailure) return Result.Failure(new Error("Import.CreateChatFailed", res.Error.Description ?? res.Error.Code)); + if (res.IsFailure) + { + return Result.Failure(new Error("Import.CreateChatFailed", res.Error.Description ?? res.Error.Code)); + } + chatId = res.Value; } } @@ -90,7 +105,11 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler(new Error("Import.CreateChatFailed", res.Error.Description ?? res.Error.Code)); + if (res.IsFailure) + { + return Result.Failure(new Error("Import.CreateChatFailed", res.Error.Description ?? res.Error.Code)); + } + chatId = res.Value; } @@ -100,7 +119,7 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler e.FullName.EndsWith(".html", StringComparison.OrdinalIgnoreCase) && e.Name.StartsWith("messages", StringComparison.OrdinalIgnoreCase)) - .OrderBy(e => + .OrderBy(e => { var name = e.Name.ToLower().Replace("messages", "").Replace(".html", ""); return string.IsNullOrEmpty(name) ? 0 : int.TryParse(name, out var num) ? num : 999999; @@ -119,10 +138,16 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler .text") ?? node.QuerySelector(".text:not(.forwarded .text)")) : node.QuerySelector(".text"); @@ -168,7 +200,7 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler" + html + ""); content = tempDoc.Body?.TextContent.Trim() ?? ""; } - + DateTime createdAt = lastCreatedAt; var titleNodes = node.QuerySelectorAll("[title]"); bool parsed = false; @@ -178,11 +210,11 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler= 10 && char.IsDigit(dateStr[0]) && char.IsDigit(dateStr[1])) { var cleanStr = dateStr.Replace("UTC", "", StringComparison.OrdinalIgnoreCase).Trim(); - + if (DateTimeOffset.TryParseExact(cleanStr, "dd.MM.yyyy HH:mm:ss zzz", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var dto)) { createdAt = dto.UtcDateTime; @@ -223,10 +255,13 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler" + fHtml + ""); fwdContent = tempDoc.Body?.TextContent.Trim() ?? ""; } - + if (forwardedFromId == null) { - content = string.IsNullOrEmpty(content) - ? $"[Переслано от {fwdName}]:\n{fwdContent}" + content = string.IsNullOrEmpty(content) + ? $"[Переслано от {fwdName}]:\n{fwdContent}" : $"{content}\n\n[Переслано от {fwdName}]:\n{fwdContent}"; } else if (string.IsNullOrEmpty(content)) @@ -282,7 +317,7 @@ internal sealed class ExecuteImportCommandHandler : ICommandHandler(options => options.UseNpgsql(connectionString)); @@ -30,7 +30,7 @@ public static class DependencyInjection services.AddScoped(); // Регистрация MediatR для этого модуля - services.AddMediatR(config => + services.AddMediatR(config => config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly)); return services; diff --git a/apps/server-net/src/Modules/Chats/Domain/Chat.cs b/apps/server-net/src/Modules/Chats/Domain/Chat.cs index 834fe59..2977dce 100644 --- a/apps/server-net/src/Modules/Chats/Domain/Chat.cs +++ b/apps/server-net/src/Modules/Chats/Domain/Chat.cs @@ -80,7 +80,11 @@ public sealed class Chat : AggregateRoot public void AddMember(Guid userId, string role = "member") { - if (_members.Any(m => m.UserId == userId)) return; + if (_members.Any(m => m.UserId == userId)) + { + return; + } + _members.Add(new ChatMember(Id, userId, role)); RaiseDomainEvent(new ChatMemberAddedDomainEvent(Id, userId)); } @@ -88,7 +92,10 @@ public sealed class Chat : AggregateRoot public void RemoveMember(Guid userId) { var member = _members.FirstOrDefault(m => m.UserId == userId); - if (member != null) _members.Remove(member); + if (member != null) + { + _members.Remove(member); + } } public void UpdateName(string name) => Name = name; diff --git a/apps/server-net/src/Modules/Chats/Domain/ReadReceipt.cs b/apps/server-net/src/Modules/Chats/Domain/ReadReceipt.cs index e5dae44..1bf5a5f 100644 --- a/apps/server-net/src/Modules/Chats/Domain/ReadReceipt.cs +++ b/apps/server-net/src/Modules/Chats/Domain/ReadReceipt.cs @@ -7,7 +7,7 @@ public sealed class ReadReceipt : Entity public Guid MessageId { get; private set; } public Guid UserId { get; private set; } public DateTime ReadAt { get; private set; } - + // Для EF Core private ReadReceipt() : base(Guid.Empty) { } diff --git a/apps/server-net/src/Modules/Chats/Infrastructure/Handlers/ChatCreatedDomainEventHandler.cs b/apps/server-net/src/Modules/Chats/Infrastructure/Handlers/ChatCreatedDomainEventHandler.cs index 5b27349..27aa7a5 100644 --- a/apps/server-net/src/Modules/Chats/Infrastructure/Handlers/ChatCreatedDomainEventHandler.cs +++ b/apps/server-net/src/Modules/Chats/Infrastructure/Handlers/ChatCreatedDomainEventHandler.cs @@ -16,7 +16,7 @@ public sealed class ChatCreatedDomainEventHandler : INotificationHandler hubContext, + IHubContext hubContext, IChatRepository chatRepository, IUserDisplayNameProvider displayNameProvider) { @@ -52,7 +52,7 @@ public sealed class ChatCreatedDomainEventHandler : INotificationHandler hubContext, + IHubContext hubContext, IMessageRepository messageRepository, IUserDisplayNameProvider displayNameProvider) { @@ -29,10 +29,13 @@ public sealed class MessageSentDomainEventHandler : INotificationHandler new { - m.Id, - m.Type, - m.Url, + Media = message.Media.Select(m => new + { + m.Id, + m.Type, + m.Url, Filename = m.Filename, - Size = m.Size + Size = m.Size }).ToList(), Sender = senderObj, ReadBy = new List(), diff --git a/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/ChatRepository.cs b/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/ChatRepository.cs index 65a2f65..10f1935 100644 --- a/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/ChatRepository.cs +++ b/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/ChatRepository.cs @@ -38,9 +38,9 @@ public sealed class ChatRepository : IChatRepository { return await _dbContext.Chats .Include(c => c.Members) - .FirstOrDefaultAsync(c => - c.Type == ChatType.Favorites && - c.Members.Any(m => m.UserId == userId), + .FirstOrDefaultAsync(c => + c.Type == ChatType.Favorites && + c.Members.Any(m => m.UserId == userId), cancellationToken); } diff --git a/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/MessageRepository.cs b/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/MessageRepository.cs index 812c5c0..902dc09 100644 --- a/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/MessageRepository.cs +++ b/apps/server-net/src/Modules/Chats/Infrastructure/Persistence/MessageRepository.cs @@ -104,14 +104,20 @@ public sealed class MessageRepository : IMessageRepository .AnyAsync(m => m.Id == messageId, cancellationToken); - if (!messageExists) return false; + if (!messageExists) + { + return false; + } // Проверяем, есть ли уже такая реакция var existingReaction = await _dbContext.Reactions .FirstOrDefaultAsync(r => r.MessageId == messageId && r.UserId == userId && r.Emoji == emoji, cancellationToken); - if (existingReaction != null) return true; // Уже существует + if (existingReaction != null) + { + return true; // Уже существует + } // Добавляем новую реакцию напрямую var reaction = new Reaction(messageId, userId, emoji); @@ -128,7 +134,10 @@ public sealed class MessageRepository : IMessageRepository .FirstOrDefaultAsync(r => r.MessageId == messageId && r.UserId == userId && r.Emoji == emoji, cancellationToken); - if (reaction == null) return false; + if (reaction == null) + { + return false; + } _dbContext.Reactions.Remove(reaction); diff --git a/apps/server-net/src/Modules/Chats/Infrastructure/SignalR/ChatHub.cs b/apps/server-net/src/Modules/Chats/Infrastructure/SignalR/ChatHub.cs index b6e7160..c5c48ad 100644 --- a/apps/server-net/src/Modules/Chats/Infrastructure/SignalR/ChatHub.cs +++ b/apps/server-net/src/Modules/Chats/Infrastructure/SignalR/ChatHub.cs @@ -518,19 +518,20 @@ public sealed class ChatHub : Hub if (participants.TryGetValue(userId, out var info)) { // Update local state if needed (e.g. muted status) - participants[userId] = info with - { + participants[userId] = info with + { IsMuted = request.IsMuted, - IsVideoOff = request.IsVideoOff + IsVideoOff = request.IsVideoOff }; } } - await Clients.Group(request.ChatId).SendAsync("group_call_status_updated", new { - chatId = request.ChatId, - userId = Context.UserIdentifier, - isMuted = request.IsMuted, - isVideoOff = request.IsVideoOff + await Clients.Group(request.ChatId).SendAsync("group_call_status_updated", new + { + chatId = request.ChatId, + userId = Context.UserIdentifier, + isMuted = request.IsMuted, + isVideoOff = request.IsVideoOff }); } @@ -544,19 +545,20 @@ public sealed class ChatHub : Hub if (participants.TryGetValue(userId, out var info)) { // Update local state if needed (e.g. muted status) - participants[userId] = info with - { + participants[userId] = info with + { IsMuted = isMuted, - IsVideoOff = isVideoOff + IsVideoOff = isVideoOff }; } } - await Clients.Group(chatId).SendAsync("group_call_status_updated", new { - chatId = chatId, - userId = Context.UserIdentifier, - isMuted = isMuted, - isVideoOff = isVideoOff + await Clients.Group(chatId).SendAsync("group_call_status_updated", new + { + chatId = chatId, + userId = Context.UserIdentifier, + isMuted = isMuted, + isVideoOff = isVideoOff }); } diff --git a/apps/server-net/src/Modules/Identity/Application/Friends/AcceptFriendRequest.cs b/apps/server-net/src/Modules/Identity/Application/Friends/AcceptFriendRequest.cs index 2cc2358..639d6a4 100644 --- a/apps/server-net/src/Modules/Identity/Application/Friends/AcceptFriendRequest.cs +++ b/apps/server-net/src/Modules/Identity/Application/Friends/AcceptFriendRequest.cs @@ -22,8 +22,10 @@ internal sealed class AcceptFriendRequestCommandHandler : ICommandHandler> Handle(AcceptFriendRequestCommand request, CancellationToken cancellationToken) { var friendship = await _context.Friendships.FindAsync(new object[] { request.FriendshipId }, cancellationToken); - if (friendship == null || friendship.FriendId != request.UserId) + if (friendship == null || friendship.FriendId != request.UserId) + { return Result.Failure(new Error("Friends.NotFound", "Request not found")); + } friendship.Accept(); await _unitOfWork.SaveChangesAsync(cancellationToken); diff --git a/apps/server-net/src/Modules/Identity/Application/Friends/DeclineFriendRequest.cs b/apps/server-net/src/Modules/Identity/Application/Friends/DeclineFriendRequest.cs index 82992fd..f6bdc4b 100644 --- a/apps/server-net/src/Modules/Identity/Application/Friends/DeclineFriendRequest.cs +++ b/apps/server-net/src/Modules/Identity/Application/Friends/DeclineFriendRequest.cs @@ -22,8 +22,10 @@ internal sealed class DeclineFriendRequestCommandHandler : ICommandHandler Handle(DeclineFriendRequestCommand request, CancellationToken cancellationToken) { var friendship = await _context.Friendships.FindAsync(new object[] { request.FriendshipId }, cancellationToken); - if (friendship == null || friendship.FriendId != request.UserId) + if (friendship == null || friendship.FriendId != request.UserId) + { return Result.Failure(new Error("Friends.NotFound", "Request not found")); + } friendship.Decline(); await _unitOfWork.SaveChangesAsync(cancellationToken); diff --git a/apps/server-net/src/Modules/Identity/Application/Friends/FriendshipStatusResponse.cs b/apps/server-net/src/Modules/Identity/Application/Friends/FriendshipStatusResponse.cs index bff4353..05062d2 100644 --- a/apps/server-net/src/Modules/Identity/Application/Friends/FriendshipStatusResponse.cs +++ b/apps/server-net/src/Modules/Identity/Application/Friends/FriendshipStatusResponse.cs @@ -3,7 +3,7 @@ using System; namespace Knot.Modules.Identity.Application.Friends; public record FriendshipStatusResponse( - string Status, - Guid? FriendshipId = null, + string Status, + Guid? FriendshipId = null, string? Direction = null ); diff --git a/apps/server-net/src/Modules/Identity/Application/Friends/GetFriends.cs b/apps/server-net/src/Modules/Identity/Application/Friends/GetFriends.cs index 594d213..ac99079 100644 --- a/apps/server-net/src/Modules/Identity/Application/Friends/GetFriends.cs +++ b/apps/server-net/src/Modules/Identity/Application/Friends/GetFriends.cs @@ -36,7 +36,10 @@ internal sealed class GetFriendsQueryHandler : IQueryHandler f.UserId == id || f.FriendId == id); diff --git a/apps/server-net/src/Modules/Identity/Application/Friends/GetFriendshipStatus.cs b/apps/server-net/src/Modules/Identity/Application/Friends/GetFriendshipStatus.cs index e759644..b34dae5 100644 --- a/apps/server-net/src/Modules/Identity/Application/Friends/GetFriendshipStatus.cs +++ b/apps/server-net/src/Modules/Identity/Application/Friends/GetFriendshipStatus.cs @@ -20,15 +20,19 @@ internal sealed class GetFriendshipStatusQueryHandler : IQueryHandler> Handle(GetFriendshipStatusQuery request, CancellationToken cancellationToken) { - if (request.CurrentUserId == request.TargetUserId) + if (request.CurrentUserId == request.TargetUserId) + { return Result.Success(new FriendshipStatusResponse("self")); + } var fs = await _context.Friendships - .FirstOrDefaultAsync(f => (f.UserId == request.CurrentUserId && f.FriendId == request.TargetUserId) || + .FirstOrDefaultAsync(f => (f.UserId == request.CurrentUserId && f.FriendId == request.TargetUserId) || (f.UserId == request.TargetUserId && f.FriendId == request.CurrentUserId), cancellationToken); - if (fs == null) + if (fs == null) + { return Result.Success(new FriendshipStatusResponse("none")); + } return Result.Success(new FriendshipStatusResponse( fs.Status.ToString().ToLowerInvariant(), diff --git a/apps/server-net/src/Modules/Identity/Application/Friends/GetIncomingRequests.cs b/apps/server-net/src/Modules/Identity/Application/Friends/GetIncomingRequests.cs index a3e2a9b..e6b6e1d 100644 --- a/apps/server-net/src/Modules/Identity/Application/Friends/GetIncomingRequests.cs +++ b/apps/server-net/src/Modules/Identity/Application/Friends/GetIncomingRequests.cs @@ -33,7 +33,10 @@ internal sealed class GetIncomingRequestsQueryHandler : IQueryHandler Handle(SendFriendRequestCommand request, CancellationToken cancellationToken) { - if (request.UserId == request.FriendId) + if (request.UserId == request.FriendId) + { return Result.Failure(new Error("Friends.Self", "Cannot add yourself")); + } var existing = await _context.Friendships - .FirstOrDefaultAsync(f => (f.UserId == request.UserId && f.FriendId == request.FriendId) || + .FirstOrDefaultAsync(f => (f.UserId == request.UserId && f.FriendId == request.FriendId) || (f.UserId == request.FriendId && f.FriendId == request.UserId), cancellationToken); - if (existing != null) + if (existing != null) + { return Result.Failure(new Error("Friends.Exists", "Friendship already exists")); + } var friendship = Friendship.Create(request.UserId, request.FriendId); _context.Friendships.Add(friendship); diff --git a/apps/server-net/src/Modules/Identity/Application/Users/Avatar/CropAvatar.cs b/apps/server-net/src/Modules/Identity/Application/Users/Avatar/CropAvatar.cs index 9d585ab..f931fc0 100644 --- a/apps/server-net/src/Modules/Identity/Application/Users/Avatar/CropAvatar.cs +++ b/apps/server-net/src/Modules/Identity/Application/Users/Avatar/CropAvatar.cs @@ -25,7 +25,10 @@ internal sealed class CropAvatarCommandHandler : ICommandHandler> Handle(CropAvatarCommand request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } string avatarUrl; diff --git a/apps/server-net/src/Modules/Identity/Application/Users/Avatar/DeleteAvatar.cs b/apps/server-net/src/Modules/Identity/Application/Users/Avatar/DeleteAvatar.cs index c049efb..c7ddd3f 100644 --- a/apps/server-net/src/Modules/Identity/Application/Users/Avatar/DeleteAvatar.cs +++ b/apps/server-net/src/Modules/Identity/Application/Users/Avatar/DeleteAvatar.cs @@ -20,7 +20,10 @@ internal sealed class DeleteAvatarCommandHandler : ICommandHandler> Handle(DeleteAvatarCommand request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } user.UpdateAvatar(null); await _unitOfWork.SaveChangesAsync(cancellationToken); diff --git a/apps/server-net/src/Modules/Identity/Application/Users/Avatar/UploadAvatar.cs b/apps/server-net/src/Modules/Identity/Application/Users/Avatar/UploadAvatar.cs index 021e983..c87fe71 100644 --- a/apps/server-net/src/Modules/Identity/Application/Users/Avatar/UploadAvatar.cs +++ b/apps/server-net/src/Modules/Identity/Application/Users/Avatar/UploadAvatar.cs @@ -23,7 +23,10 @@ internal sealed class UploadAvatarCommandHandler : ICommandHandler> Handle(UploadAvatarCommand request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } var fileId = await _fileStorage.UploadFileAsync(request.FileStream, request.FileName, request.ContentType); var avatarUrl = $"/api/files/{fileId}"; diff --git a/apps/server-net/src/Modules/Identity/Application/Users/GetMe/GetMe.cs b/apps/server-net/src/Modules/Identity/Application/Users/GetMe/GetMe.cs index 0b8780d..b6075dd 100644 --- a/apps/server-net/src/Modules/Identity/Application/Users/GetMe/GetMe.cs +++ b/apps/server-net/src/Modules/Identity/Application/Users/GetMe/GetMe.cs @@ -19,7 +19,10 @@ internal sealed class GetMeQueryHandler : IQueryHandler> Handle(GetMeQuery request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } var response = new AuthResponseDto( string.Empty, diff --git a/apps/server-net/src/Modules/Identity/Application/Users/GetUser/GetUser.cs b/apps/server-net/src/Modules/Identity/Application/Users/GetUser/GetUser.cs index 34bde91..aa4e5f6 100644 --- a/apps/server-net/src/Modules/Identity/Application/Users/GetUser/GetUser.cs +++ b/apps/server-net/src/Modules/Identity/Application/Users/GetUser/GetUser.cs @@ -18,7 +18,10 @@ internal sealed class GetUserQueryHandler : IQueryHandler> Handle(GetUserQuery request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.Id, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } var dto = new UserProfileDto( user.Id, diff --git a/apps/server-net/src/Modules/Identity/Application/Users/Register/RegisterUserCommandHandler.cs b/apps/server-net/src/Modules/Identity/Application/Users/Register/RegisterUserCommandHandler.cs index 9c136b7..7db1105 100644 --- a/apps/server-net/src/Modules/Identity/Application/Users/Register/RegisterUserCommandHandler.cs +++ b/apps/server-net/src/Modules/Identity/Application/Users/Register/RegisterUserCommandHandler.cs @@ -28,8 +28,8 @@ public sealed class RegisterUserCommandHandler : ICommandHandler> Handle(UpdateProfileCommand request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } user.UpdateProfile(request.DisplayName ?? user.DisplayName, request.Bio, request.Birthday); await _unitOfWork.SaveChangesAsync(cancellationToken); diff --git a/apps/server-net/src/Modules/Identity/Application/Users/UpdateSettings/UpdateSettings.cs b/apps/server-net/src/Modules/Identity/Application/Users/UpdateSettings/UpdateSettings.cs index 2614157..0ec1a4b 100644 --- a/apps/server-net/src/Modules/Identity/Application/Users/UpdateSettings/UpdateSettings.cs +++ b/apps/server-net/src/Modules/Identity/Application/Users/UpdateSettings/UpdateSettings.cs @@ -20,7 +20,10 @@ internal sealed class UpdateSettingsCommandHandler : ICommandHandler> Handle(UpdateSettingsCommand request, CancellationToken cancellationToken) { var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken); - if (user == null) return Result.Failure(new Error("User.NotFound", "User not found")); + if (user == null) + { + return Result.Failure(new Error("User.NotFound", "User not found")); + } user.UpdateSettings(request.HideStoryViews ?? user.HideStoryViews); await _unitOfWork.SaveChangesAsync(cancellationToken); diff --git a/apps/server-net/src/Modules/Identity/DependencyInjection.cs b/apps/server-net/src/Modules/Identity/DependencyInjection.cs index 47f2dfb..6bc1447 100644 --- a/apps/server-net/src/Modules/Identity/DependencyInjection.cs +++ b/apps/server-net/src/Modules/Identity/DependencyInjection.cs @@ -20,7 +20,7 @@ public static class DependencyInjection { // Настройка базы данных string connectionString = configuration.GetConnectionString("DefaultConnection")!; - + services.AddDbContext(options => options.UseNpgsql(connectionString)); @@ -32,7 +32,7 @@ public static class DependencyInjection services.AddScoped(); // Регистрация MediatR для этого модуля - services.AddMediatR(config => + services.AddMediatR(config => config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly)); return services; diff --git a/apps/server-net/src/Modules/Identity/Domain/Story.cs b/apps/server-net/src/Modules/Identity/Domain/Story.cs index 50f8848..8662b26 100644 --- a/apps/server-net/src/Modules/Identity/Domain/Story.cs +++ b/apps/server-net/src/Modules/Identity/Domain/Story.cs @@ -40,20 +40,31 @@ public class Story : Entity public void AddViewer(Guid userId) { - if (_viewers.Any(v => v.UserId == userId)) return; + if (_viewers.Any(v => v.UserId == userId)) + { + return; + } + _viewers.Add(new StoryViewer(Id, userId)); } public void AddReaction(Guid userId, string emoji) { - if (_reactions.Any(r => r.UserId == userId && r.Emoji == emoji)) return; + if (_reactions.Any(r => r.UserId == userId && r.Emoji == emoji)) + { + return; + } + _reactions.Add(new StoryReaction(Id, userId, emoji)); } public void RemoveReaction(Guid userId, string emoji) { var reaction = _reactions.FirstOrDefault(r => r.UserId == userId && r.Emoji == emoji); - if (reaction != null) _reactions.Remove(reaction); + if (reaction != null) + { + _reactions.Remove(reaction); + } } public void AddReply(Guid userId, string content) diff --git a/apps/server-net/src/Modules/Identity/Domain/User.cs b/apps/server-net/src/Modules/Identity/Domain/User.cs index fc64fdd..1744493 100644 --- a/apps/server-net/src/Modules/Identity/Domain/User.cs +++ b/apps/server-net/src/Modules/Identity/Domain/User.cs @@ -17,7 +17,7 @@ public sealed class User : AggregateRoot public DateTime CreatedAt { get; private set; } public bool HideStoryViews { get; private set; } - private User(Guid id, string username, string passwordHash, string displayName, string? email, string? bio = null) + private User(Guid id, string username, string passwordHash, string displayName, string? email, string? bio = null) : base(id) { Username = username; diff --git a/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/IdentityDbContext.cs b/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/IdentityDbContext.cs index 8a66bb2..7d566e9 100644 --- a/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/IdentityDbContext.cs +++ b/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/IdentityDbContext.cs @@ -101,7 +101,7 @@ public sealed class IdentityDbContext : DbContext, IIdentityUnitOfWork, Knot.Mod { builder.ToTable("StoryReplies"); builder.HasKey(r => r.Id); - + builder.Property(r => r.Content) .IsRequired() .HasMaxLength(500) diff --git a/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/UserRepository.cs b/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/UserRepository.cs index 98f2616..c81efc9 100644 --- a/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/UserRepository.cs +++ b/apps/server-net/src/Modules/Identity/Infrastructure/Persistence/UserRepository.cs @@ -38,7 +38,7 @@ public sealed class UserRepository : IUserRepository public async Task> SearchUsersAsync(string query, CancellationToken cancellationToken = default) { return await _context.Users - .Where(u => u.Username.ToLower().Contains(query.ToLower()) || + .Where(u => u.Username.ToLower().Contains(query.ToLower()) || (u.DisplayName != null && u.DisplayName.ToLower().Contains(query.ToLower()))) .Take(20) .ToListAsync(cancellationToken); diff --git a/apps/server-net/src/Modules/Identity/Infrastructure/Services/UserDisplayNameProvider.cs b/apps/server-net/src/Modules/Identity/Infrastructure/Services/UserDisplayNameProvider.cs index 744d6c4..04b9af8 100644 --- a/apps/server-net/src/Modules/Identity/Infrastructure/Services/UserDisplayNameProvider.cs +++ b/apps/server-net/src/Modules/Identity/Infrastructure/Services/UserDisplayNameProvider.cs @@ -21,7 +21,11 @@ public sealed class UserDisplayNameProvider : IUserDisplayNameProvider public async Task GetUserInfoAsync(Guid userId, CancellationToken ct = default) { var user = await _userRepository.GetByIdAsync(userId, ct); - if (user == null) return null; + if (user == null) + { + return null; + } + return new UserInfo(user.Id, user.Username, user.DisplayName, user.Avatar); } diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/DependencyInjection.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/DependencyInjection.cs index b720123..da55b8a 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/DependencyInjection.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/DependencyInjection.cs @@ -21,9 +21,9 @@ public static class DependencyInjection services.AddScoped(); // Настройка шифрования - var masterKey = configuration["KNOT_MASTER_ENCRYPTION_KEY"] + var masterKey = configuration["KNOT_MASTER_ENCRYPTION_KEY"] ?? throw new ArgumentNullException("KNOT_MASTER_ENCRYPTION_KEY is missing in env."); - + services.AddSingleton(new AesEncryptionService(masterKey)); // Настройка MinIO (S3) @@ -38,7 +38,7 @@ public static class DependencyInjection .WithSSL(false) .Build()); - services.AddScoped(provider => + services.AddScoped(provider => { var minioClient = provider.GetRequiredService(); var encService = provider.GetRequiredService(); @@ -46,10 +46,10 @@ public static class DependencyInjection }); // Настройка System Database - var connectionString = configuration.GetConnectionString("DefaultConnection") + var connectionString = configuration.GetConnectionString("DefaultConnection") ?? configuration["DATABASE_URL"] ?? throw new ArgumentNullException("Database connection string not found."); - + services.AddDbContext(options => options.UseNpgsql(connectionString)); diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/AdminAuthMiddleware.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/AdminAuthMiddleware.cs index fbcfa8e..818636e 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/AdminAuthMiddleware.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/AdminAuthMiddleware.cs @@ -40,7 +40,7 @@ public class AdminAuthMiddleware var authHeader = AuthenticationHeaderValue.Parse(context.Request.Headers["Authorization"]); var credentialBytes = Convert.FromBase64String(authHeader.Parameter ?? string.Empty); var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':', 2); - + var username = credentials[0]; var password = credentials[1]; diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/ExceptionHandlingMiddleware.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/ExceptionHandlingMiddleware.cs index 4f2bfc8..5b1e994 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/ExceptionHandlingMiddleware.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Middleware/ExceptionHandlingMiddleware.cs @@ -32,7 +32,7 @@ public sealed class ExceptionHandlingMiddleware private static async Task HandleExceptionAsync(HttpContext context, Exception exception) { context.Response.ContentType = "application/json"; - + var (statusCode, message) = exception switch { UnauthorizedAccessException => (HttpStatusCode.Unauthorized, "Unauthorized access."), diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Persistence/SystemDbContextFactory.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Persistence/SystemDbContextFactory.cs index b43a94b..4f2e635 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Persistence/SystemDbContextFactory.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Persistence/SystemDbContextFactory.cs @@ -22,8 +22,8 @@ public class SystemDbContextFactory : IDesignTimeDbContextFactory(); - var connectionString = configuration.GetConnectionString("DefaultConnection") - ?? configuration["DATABASE_URL"] + var connectionString = configuration.GetConnectionString("DefaultConnection") + ?? configuration["DATABASE_URL"] ?? "Host=localhost;Port=5432;Database=knot_db;Username=knot;Password=knot_pass"; builder.UseNpgsql(connectionString); diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Security/AesEncryptionService.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Security/AesEncryptionService.cs index 9545213..ca14d2c 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Security/AesEncryptionService.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Security/AesEncryptionService.cs @@ -29,17 +29,22 @@ public class AesEncryptionService : IEncryptionService } if (_key.Length != 32) + { throw new ArgumentException("Мастер-ключ должен быть ровно 32 байта для AES-256."); + } } // Сообщения: AES-256-GCM public string EncryptMessage(string plainText) { - if (string.IsNullOrEmpty(plainText)) return plainText; + if (string.IsNullOrEmpty(plainText)) + { + return plainText; + } var nonce = new byte[12]; RandomNumberGenerator.Fill(nonce); - + var plainBytes = Encoding.UTF8.GetBytes(plainText); var cipherBytes = new byte[plainBytes.Length]; var tag = new byte[16]; @@ -53,10 +58,16 @@ public class AesEncryptionService : IEncryptionService public string DecryptMessage(string cipherText) { - if (string.IsNullOrEmpty(cipherText)) return cipherText; + if (string.IsNullOrEmpty(cipherText)) + { + return cipherText; + } var parts = cipherText.Split(':'); - if (parts.Length != 3) return cipherText; + if (parts.Length != 3) + { + return cipherText; + } try { diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsService.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsService.cs index 5426df5..40226c9 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsService.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsService.cs @@ -49,28 +49,31 @@ public class StatisticsService : IStatisticsService long totalDiskSpace = 5L * 1024 * 1024 * 1024 * 1024; // Fallback long freeSpace = 0; - try + try { var drive = new System.IO.DriveInfo("/"); - if(drive.IsReady) + if (drive.IsReady) { totalDiskSpace = drive.TotalSize; freeSpace = drive.AvailableFreeSpace; - } - else + } + else { drive = new System.IO.DriveInfo(System.IO.Directory.GetCurrentDirectory()); totalDiskSpace = drive.TotalSize; freeSpace = drive.AvailableFreeSpace; } - } + } catch { } var usedSpace = latestStat?.TotalFilesSize ?? 0; - + long onlineUsersCount = _cache.TryGetValue("Global_OnlineUsersCount", out int count) ? count : 0; long offlineUsersCount = totalUsers - onlineUsersCount; - if(offlineUsersCount < 0) offlineUsersCount = 0; + if (offlineUsersCount < 0) + { + offlineUsersCount = 0; + } var stats = new DashboardStatsDto { @@ -78,7 +81,7 @@ public class StatisticsService : IStatisticsService StorageLimitBytes = freeSpace > 0 ? usedSpace + freeSpace : totalDiskSpace, OnlineUsers = onlineUsersCount, OfflineUsers = offlineUsersCount, - TotalUsers = totalUsers, + TotalUsers = totalUsers, ActivityTimeline = history }; @@ -97,7 +100,10 @@ internal static class SqlExtensions { cmd.CommandText = "SELECT COUNT(*) FROM identity.\"Users\""; if (cmd.Connection?.State != System.Data.ConnectionState.Open) + { await ((System.Data.Common.DbConnection)cmd.Connection!).OpenAsync(); + } + var result = await ((System.Data.Common.DbCommand)cmd).ExecuteScalarAsync(); return Convert.ToInt64(result); } diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsWorker.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsWorker.cs index 21fcc1a..72f3992 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsWorker.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Statistics/StatisticsWorker.cs @@ -30,7 +30,7 @@ public class StatisticsWorker : BackgroundService // Simplified gathering for daily stats var today = DateTime.UtcNow.Date; var stat = await db.DailyStats.FirstOrDefaultAsync(s => s.Date == today, stoppingToken); - + if (stat == null) { stat = new DailyStat { Date = today }; @@ -41,10 +41,10 @@ public class StatisticsWorker : BackgroundService var cmd = conn.CreateCommand(); stat.ActiveUsers = await cmd.QueryTotalUsersAsync(); - + long dbSize = 0; long filesSize = 0; - try + try { // 1. Database size itself cmd.CommandText = "SELECT pg_database_size(current_database());"; @@ -59,7 +59,7 @@ public class StatisticsWorker : BackgroundService catch { } stat.TotalFilesSize = dbSize + filesSize; // Database size + MinIO files size - + await db.SaveChangesAsync(stoppingToken); } catch diff --git a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Storage/S3FileStorageService.cs b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Storage/S3FileStorageService.cs index ca1ef25..177ad2f 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Storage/S3FileStorageService.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Infrastructure/Storage/S3FileStorageService.cs @@ -118,9 +118,20 @@ public class S3FileStorageService : IFileStorageService var statArgs = new StatObjectArgs().WithBucket(_bucketName).WithObject(fileId); var stat = await _minioClient.StatObjectAsync(statArgs).ConfigureAwait(false); - if (stat.MetaData.ContainsKey("Contenttype")) contentType = stat.MetaData["Contenttype"]; - if (stat.MetaData.ContainsKey("Originalfilename")) fileName = stat.MetaData["Originalfilename"]; - if (stat.MetaData.ContainsKey("Iv")) ivBase64 = stat.MetaData["Iv"]; + if (stat.MetaData.ContainsKey("Contenttype")) + { + contentType = stat.MetaData["Contenttype"]; + } + + if (stat.MetaData.ContainsKey("Originalfilename")) + { + fileName = stat.MetaData["Originalfilename"]; + } + + if (stat.MetaData.ContainsKey("Iv")) + { + ivBase64 = stat.MetaData["Iv"]; + } // Загружаем во временный файл (так как CryptoStream требует правильного чтения/записи) var getObjArgs = new GetObjectArgs() @@ -171,7 +182,7 @@ public class S3FileStorageService : IFileStorageService try { var listArgs = new ListObjectsArgs().WithBucket(_bucketName).WithRecursive(true); - + await foreach (var item in _minioClient.ListObjectsEnumAsync(listArgs).ConfigureAwait(false)) { result.Add((item.Key, (long)item.Size)); diff --git a/apps/server-net/src/Shared/Knot.Shared.Kernel/Configuration/SystemSettingsDto.cs b/apps/server-net/src/Shared/Knot.Shared.Kernel/Configuration/SystemSettingsDto.cs index 60bf0b2..7314e02 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Kernel/Configuration/SystemSettingsDto.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Kernel/Configuration/SystemSettingsDto.cs @@ -22,7 +22,7 @@ public class SystemSettingsDto // Confederation public bool EnableConfederation { get; set; } = false; public List AllowedDomains { get; set; } = new(); - + // Auth public bool EnableRegistration { get; set; } = true; } diff --git a/apps/server-net/src/Shared/Knot.Shared.Kernel/Constants/Klipy.cs b/apps/server-net/src/Shared/Knot.Shared.Kernel/Constants/Klipy.cs index 8238383..3bfcbce 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Kernel/Constants/Klipy.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Kernel/Constants/Klipy.cs @@ -4,12 +4,12 @@ public static class Klipy { public const string ApiUrlCo = "https://api.klipy.co/api/v1/{0}/{1}?page=1&per_page=30&{2}&customer_id={3}"; public const string ApiUrlCom = "https://api.klipy.com/api/v1/{0}/{1}?page=1&per_page=30&{2}&customer_id={3}"; - + public const string ResourceTrending = "gifs/trending"; public const string ResourceSearch = "gifs/search"; - + public const int TrendingCacheMinutes = 60; public const int SearchCacheMinutes = 15; - + public const string DefaultCustomerId = "anonymous"; } diff --git a/apps/server-net/src/Shared/Knot.Shared.Kernel/Entity.cs b/apps/server-net/src/Shared/Knot.Shared.Kernel/Entity.cs index 6fcff36..276b954 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Kernel/Entity.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Kernel/Entity.cs @@ -21,8 +21,16 @@ public abstract class Entity : IEquatable> public bool Equals(Entity? other) { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; + if (other is null) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + return Id.Equals(other.Id); } diff --git a/apps/server-net/src/Shared/Knot.Shared.Kernel/ICommand.cs b/apps/server-net/src/Shared/Knot.Shared.Kernel/ICommand.cs index c3b984a..407cd3a 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Kernel/ICommand.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Kernel/ICommand.cs @@ -7,7 +7,9 @@ public interface ICommand : IRequest { } public interface ICommand : IRequest> { } public interface ICommandHandler : IRequestHandler - where TCommand : ICommand { } + where TCommand : ICommand +{ } public interface ICommandHandler : IRequestHandler> - where TCommand : ICommand { } + where TCommand : ICommand +{ } diff --git a/apps/server-net/src/Shared/Knot.Shared.Kernel/Result.cs b/apps/server-net/src/Shared/Knot.Shared.Kernel/Result.cs index e7ba91b..4ab7843 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Kernel/Result.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Kernel/Result.cs @@ -20,9 +20,14 @@ public class Result protected Result(bool isSuccess, Error error) { if (isSuccess && error != Error.None) + { throw new InvalidOperationException(); + } + if (!isSuccess && error == Error.None) + { throw new InvalidOperationException(); + } IsSuccess = isSuccess; Error = error; diff --git a/apps/server-net/src/Shared/Knot.Shared.Kernel/Security/IEncryptionService.cs b/apps/server-net/src/Shared/Knot.Shared.Kernel/Security/IEncryptionService.cs index b705164..aa58dc7 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Kernel/Security/IEncryptionService.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Kernel/Security/IEncryptionService.cs @@ -10,7 +10,7 @@ public interface IEncryptionService // Создает поток шифрования для потоковой передачи файлов "на лету" Stream CreateEncryptionStream(Stream unencryptedOutputStream, out byte[] iv); - + // Создает поток дешифрования для чтения файлов "на лету" Stream CreateDecryptionStream(Stream encryptedInputStream, byte[] iv); } diff --git a/apps/server-net/src/Shared/Knot.Shared.Kernel/ValueObject.cs b/apps/server-net/src/Shared/Knot.Shared.Kernel/ValueObject.cs index bc4e874..1687b7d 100644 --- a/apps/server-net/src/Shared/Knot.Shared.Kernel/ValueObject.cs +++ b/apps/server-net/src/Shared/Knot.Shared.Kernel/ValueObject.cs @@ -15,7 +15,11 @@ public abstract class ValueObject : IEquatable public bool Equals(ValueObject? other) { - if (other is null) return false; + if (other is null) + { + return false; + } + return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); } diff --git a/apps/server-net/tests/Knot.Modules.Chats.UnitTests/GetOrCreateFavoritesCommandHandlerTests.cs b/apps/server-net/tests/Knot.Modules.Chats.UnitTests/GetOrCreateFavoritesCommandHandlerTests.cs index 12f374f..9b007da 100644 --- a/apps/server-net/tests/Knot.Modules.Chats.UnitTests/GetOrCreateFavoritesCommandHandlerTests.cs +++ b/apps/server-net/tests/Knot.Modules.Chats.UnitTests/GetOrCreateFavoritesCommandHandlerTests.cs @@ -27,7 +27,7 @@ public class GetOrCreateFavoritesCommandHandlerTests // Arrange var userId = Guid.NewGuid(); var existingChat = Chat.Create("Избранное", ChatType.Favorites); - + _chatRepository.GetFavoritesAsync(userId, Arg.Any()) .Returns(existingChat); @@ -39,7 +39,7 @@ public class GetOrCreateFavoritesCommandHandlerTests // Assert result.IsSuccess.Should().BeTrue(); result.Value.Should().Be(existingChat.Id); - + _chatRepository.DidNotReceive().Add(Arg.Any()); await _unitOfWork.DidNotReceive().SaveChangesAsync(Arg.Any()); } @@ -60,12 +60,12 @@ public class GetOrCreateFavoritesCommandHandlerTests // Assert result.IsSuccess.Should().BeTrue(); result.Value.Should().NotBeEmpty(); - - _chatRepository.Received(1).Add(Arg.Is(c => - c.Type == ChatType.Favorites && + + _chatRepository.Received(1).Add(Arg.Is(c => + c.Type == ChatType.Favorites && c.Name == "Избранное" && c.Members.Any(m => m.UserId == userId))); - + await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any()); } } diff --git a/apps/server-net/tests/Knot.Modules.Identity.UnitTests/LoginUserCommandHandlerTests.cs b/apps/server-net/tests/Knot.Modules.Identity.UnitTests/LoginUserCommandHandlerTests.cs index 0bc8af8..ee1d486 100644 --- a/apps/server-net/tests/Knot.Modules.Identity.UnitTests/LoginUserCommandHandlerTests.cs +++ b/apps/server-net/tests/Knot.Modules.Identity.UnitTests/LoginUserCommandHandlerTests.cs @@ -29,12 +29,12 @@ public class LoginUserCommandHandlerTests var password = "password123"; var passwordHash = BCrypt.Net.BCrypt.HashPassword(password); var user = User.Create("testuser", passwordHash, "Test User"); - + var command = new LoginUserCommand("testuser", password); - + _userRepository.GetByUsernameAsync(command.Username, Arg.Any()) .Returns(user); - + _tokenProvider.Generate(user).Returns("valid-jwt-token"); // Act @@ -68,9 +68,9 @@ public class LoginUserCommandHandlerTests var correctPassword = "correctPassword"; var passwordHash = BCrypt.Net.BCrypt.HashPassword(correctPassword); var user = User.Create("testuser", passwordHash, "Test User"); - + var command = new LoginUserCommand("testuser", "wrongPassword"); - + _userRepository.GetByUsernameAsync(command.Username, Arg.Any()) .Returns(user); diff --git a/apps/server-net/tests/Knot.Modules.Identity.UnitTests/RegisterUserCommandHandlerTests.cs b/apps/server-net/tests/Knot.Modules.Identity.UnitTests/RegisterUserCommandHandlerTests.cs index da0caa7..ef6447b 100644 --- a/apps/server-net/tests/Knot.Modules.Identity.UnitTests/RegisterUserCommandHandlerTests.cs +++ b/apps/server-net/tests/Knot.Modules.Identity.UnitTests/RegisterUserCommandHandlerTests.cs @@ -35,12 +35,12 @@ public class RegisterUserCommandHandlerTests // Assert result.IsSuccess.Should().BeTrue(); result.Value.Should().NotBeEmpty(); - - _userRepository.Received(1).Add(Arg.Is(u => - u.Username == command.Username && + + _userRepository.Received(1).Add(Arg.Is(u => + u.Username == command.Username && u.DisplayName == command.DisplayName && u.Email == command.Email)); - + await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any()); } @@ -58,7 +58,7 @@ public class RegisterUserCommandHandlerTests // Assert result.IsFailure.Should().BeTrue(); result.Error.Code.Should().Be("Identity.UsernameNotUnique"); - + _userRepository.DidNotReceive().Add(Arg.Any()); await _unitOfWork.DidNotReceive().SaveChangesAsync(Arg.Any()); }