From b85ca7cdd6a5726a6419c5c374214c4fee5ad276 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:31:51 +0300 Subject: [PATCH 01/52] Added serilog nuget package Signed-off-by: BelugaChan --- MethodologyMain.API/MethodologyMain.API.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MethodologyMain.API/MethodologyMain.API.csproj b/MethodologyMain.API/MethodologyMain.API.csproj index af8b76e..2134571 100644 --- a/MethodologyMain.API/MethodologyMain.API.csproj +++ b/MethodologyMain.API/MethodologyMain.API.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -17,6 +17,7 @@ + From 84f2866ccaceb5d6ad227772b3e55ceda85a7b6f Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:33:08 +0300 Subject: [PATCH 02/52] Added new log logic Signed-off-by: BelugaChan --- .../Controllers/TeamController.cs | 285 +++++++++++------- 1 file changed, 180 insertions(+), 105 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 6dc5ad0..c3d5382 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -4,7 +4,9 @@ using Microsoft.AspNetCore.Mvc; using System.Security.Claims; using MethodologyMain.Application.Interface; - +using AuthMetodology.Infrastructure.Interfaces; +using AuthMetodology.Infrastructure.Models; +using Serilog.Events; namespace MethodologyMain.API.Controllers { [ApiController] @@ -12,10 +14,11 @@ namespace MethodologyMain.API.Controllers public class TeamController : ControllerBase { private readonly ITeamService _teamService; - - public TeamController(ITeamService teamService) + private readonly ILogQueueService logQueueService; + public TeamController(ITeamService teamService, ILogQueueService logQueueService) { _teamService = teamService; + this.logQueueService = logQueueService; } // Создание команды @@ -23,31 +26,47 @@ public TeamController(ITeamService teamService) //[Authorize] public async Task> CreateTeam([FromBody] CreateTeamDto dto) { - try - { - Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена - var team = await _teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId); - return CreatedAtAction(nameof(GetTeam), new { id = team.Id }, team); - } - catch (InvalidOperationException ex) + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - return BadRequest(ex.Message); - } + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "POST api/Team was called", + TimeStamp = DateTime.UtcNow + }); + Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена + var team = await _teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId); + return CreatedAtAction(nameof(GetTeam), new { id = team.Id }, team); + //try + //{ + + //} + //catch (InvalidOperationException ex) + //{ + // return BadRequest(ex.Message); + //} } // Получение информации о команде [HttpGet("{id}")] public async Task> GetTeam(Guid id) { - try - { - var team = await _teamService.GetTeamByIdAsync(id); - return Ok(team); - } - catch (KeyNotFoundException) + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - return NotFound(); - } + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/Team/id was called", + TimeStamp = DateTime.UtcNow + }); + var team = await _teamService.GetTeamByIdAsync(id); + return Ok(team); + //try + //{ + + //} + //catch (KeyNotFoundException) + //{ + // return NotFound(); + //} } // Удаление команды @@ -55,22 +74,30 @@ public async Task> GetTeam(Guid id) //[Authorize] public async Task DeleteTeam(Guid id) { - try + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - Guid currentUserId = GetCurrentUserId(); - bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "DELETE api/Team/id was called", + TimeStamp = DateTime.UtcNow + }); + Guid currentUserId = GetCurrentUserId(); + bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора - await _teamService.DeleteTeamAsync(id, currentUserId, isAdmin); - return NoContent(); - } - catch (KeyNotFoundException) - { - return NotFound(); - } - catch (UnauthorizedAccessException ex) - { - return Forbid(ex.Message); - } + await _teamService.DeleteTeamAsync(id, currentUserId, isAdmin); + return NoContent(); + //try + //{ + + //} + //catch (KeyNotFoundException) + //{ + // return NotFound(); + //} + //catch (UnauthorizedAccessException ex) + //{ + // return Forbid(ex.Message); + //} } // Добавление пользователя в команду @@ -78,24 +105,32 @@ public async Task DeleteTeam(Guid id) //[Authorize] public async Task AddMember(Guid id, [FromBody] AddUserDto dto) { - try + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - Guid currentUserId = GetCurrentUserId(); - await _teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId); - return NoContent(); - } - catch (KeyNotFoundException) - { - return NotFound(); - } - catch (UnauthorizedAccessException ex) - { - return Forbid(ex.Message); - } - catch (InvalidOperationException ex) - { - return BadRequest(ex.Message); - } + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "POST api/Team/id/members was called", + TimeStamp = DateTime.UtcNow + }); + Guid currentUserId = GetCurrentUserId(); + await _teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId); + return NoContent(); + //try + //{ + + //} + //catch (KeyNotFoundException) + //{ + // return NotFound(); + //} + //catch (UnauthorizedAccessException ex) + //{ + // return Forbid(ex.Message); + //} + //catch (InvalidOperationException ex) + //{ + // return BadRequest(ex.Message); + //} } // Удаление пользователя из команды @@ -103,39 +138,55 @@ public async Task AddMember(Guid id, [FromBody] AddUserDto dto) //[Authorize] public async Task RemoveMember(Guid id, Guid userId) { - try - { - Guid currentUserId = GetCurrentUserId(); - await _teamService.RemoveUserFromTeamAsync(id, userId, currentUserId); - return NoContent(); - } - catch (KeyNotFoundException) - { - return NotFound(); - } - catch (UnauthorizedAccessException ex) + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - return Forbid(ex.Message); - } - catch (InvalidOperationException ex) - { - return BadRequest(ex.Message); - } + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "DELETE api/Team/id/members/userId was called", + TimeStamp = DateTime.UtcNow + }); + Guid currentUserId = GetCurrentUserId(); + await _teamService.RemoveUserFromTeamAsync(id, userId, currentUserId); + return NoContent(); + //try + //{ + + //} + //catch (KeyNotFoundException) + //{ + // return NotFound(); + //} + //catch (UnauthorizedAccessException ex) + //{ + // return Forbid(ex.Message); + //} + //catch (InvalidOperationException ex) + //{ + // return BadRequest(ex.Message); + //} } // Получение списка участников команды [HttpGet("{id}/members")] public async Task>> GetTeamMembers(Guid id) { - try + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - var members = await _teamService.GetTeamMembersAsync(id); - return Ok(members); - } - catch (KeyNotFoundException) - { - return NotFound(); - } + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/Team/id/members was called", + TimeStamp = DateTime.UtcNow + }); + var members = await _teamService.GetTeamMembersAsync(id); + return Ok(members); + //try + //{ + + //} + //catch (KeyNotFoundException) + //{ + // return NotFound(); + //} } // Передача прав капитана @@ -143,30 +194,45 @@ public async Task>> GetTeamMembers(Guid id) //[Authorize] public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto) { - try - { - Guid currentUserId = GetCurrentUserId(); - await _teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId); - return NoContent(); - } - catch (KeyNotFoundException) + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - return NotFound(); - } - catch (UnauthorizedAccessException ex) - { - return Forbid(ex.Message); - } - catch (InvalidOperationException ex) - { - return BadRequest(ex.Message); - } + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "PUT api/Team/id/captain was called", + TimeStamp = DateTime.UtcNow + }); + Guid currentUserId = GetCurrentUserId(); + await _teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId); + return NoContent(); + //try + //{ + + //} + //catch (KeyNotFoundException) + //{ + // return NotFound(); + //} + //catch (UnauthorizedAccessException ex) + //{ + // return Forbid(ex.Message); + //} + //catch (InvalidOperationException ex) + //{ + // return BadRequest(ex.Message); + //} } // Получение списка команд для события [HttpGet("event/{eventId}")] public async Task>> GetTeamsByEvent(Guid eventId) { + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/Team/event/eventId was called", + TimeStamp = DateTime.UtcNow + }); var teams = await _teamService.GetTeamsByEventIdAsync(eventId); return Ok(teams); } @@ -176,22 +242,31 @@ public async Task>> GetTeamsByEvent(Guid eventId) //[Authorize] public async Task> GetUserTeamForEvent(Guid eventId) { - try + await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { - Guid currentUserId = GetCurrentUserId(); - var team = await _teamService.GetUserTeamForEventAsync(currentUserId, eventId); - - if (team == null) - { - return NotFound(); - } + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/Team/event/eventId/user was called", + TimeStamp = DateTime.UtcNow + }); + Guid currentUserId = GetCurrentUserId(); + var team = await _teamService.GetUserTeamForEventAsync(currentUserId, eventId); - return Ok(team); - } - catch (Exception ex) + if (team == null) { - return BadRequest(ex.Message); + return NotFound(); } + + return Ok(team); + + //try + //{ + + //} + //catch (Exception ex) + //{ + // return BadRequest(ex.Message); + //} } // Вспомогательный метод для получения ID текущего пользователя From 307ea1ff4d3712f5dd25f36935664edc304029e8 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:33:45 +0300 Subject: [PATCH 03/52] Added new middleware for handling exceptions Signed-off-by: BelugaChan --- .../Middleware/ExceptionMiddleware.cs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 MethodologyMain.API/Middleware/ExceptionMiddleware.cs diff --git a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs new file mode 100644 index 0000000..ea35fe2 --- /dev/null +++ b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs @@ -0,0 +1,47 @@ +using AuthMetodology.Infrastructure.Interfaces; +using MethodologyMain.Application.Exceptions; +using Serilog.Events; + +namespace MethodologyMain.API.Middleware +{ + public class ExceptionMiddleware + { + private readonly RequestDelegate next; + private readonly ILogQueueService logQueueService; + public ExceptionMiddleware(RequestDelegate next, ILogQueueService logQueueService) + { + this.next = next; + this.logQueueService = logQueueService; + } + + public async Task InvokeAsync(HttpContext context) + { + try + { + await next(context); + } + catch (Exception ex) + { + await logQueueService.SendLogEventAsync(new AuthMetodology.Infrastructure.Models.RabbitMqLogPublish { + ServiceName = "Main service", + LogLevel = LogEventLevel.Error, + Message = $"Exception was thrown.\nMessage: {ex.Message}\nSource: {ex.Source}", + TimeStamp = DateTime.UtcNow + }); + await HandleExceptionAsync(ex,context); + } + } + + private async Task HandleExceptionAsync(Exception ex, HttpContext context) + { + ExceptionResponse response = ex switch + { + MemberAlreadyInTeamException _ => new ExceptionResponse("Пользователь уже состоит в команде для данного события", System.Net.HttpStatusCode.Conflict), + TeamNotFoundException _ => new ExceptionResponse("Команда не найдена", System.Net.HttpStatusCode.Conflict), + UnauthorizedAccessException _ => new ExceptionResponse(ex.Message, System.Net.HttpStatusCode.Unauthorized), + InvalidOperationException _ => new ExceptionResponse(ex.Message,System.Net.HttpStatusCode.Conflict), + UserNotFoundException _ => new ExceptionResponse("Пользователь не найден",System.Net.HttpStatusCode.Conflict), + }; + } + } +} From e13c4c531bcc7c60504d7607c843c1cdaf39e2d4 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:34:12 +0300 Subject: [PATCH 04/52] Added new model class for exception response --- MethodologyMain.API/Middleware/ExceptionResponse.cs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 MethodologyMain.API/Middleware/ExceptionResponse.cs diff --git a/MethodologyMain.API/Middleware/ExceptionResponse.cs b/MethodologyMain.API/Middleware/ExceptionResponse.cs new file mode 100644 index 0000000..403ff12 --- /dev/null +++ b/MethodologyMain.API/Middleware/ExceptionResponse.cs @@ -0,0 +1,6 @@ +using System.Net; + +namespace MethodologyMain.API.Middleware +{ + public record ExceptionResponse(string Message, HttpStatusCode Code); +} From 9c619ed3d18eff4b3599300d71fa488f7abe93dd Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:35:39 +0300 Subject: [PATCH 05/52] Added some test configuration which connects with logging and rabbitMq Signed-off-by: BelugaChan --- MethodologyMain.API/appsettings.json | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/MethodologyMain.API/appsettings.json b/MethodologyMain.API/appsettings.json index 2567da7..ca2b892 100644 --- a/MethodologyMain.API/appsettings.json +++ b/MethodologyMain.API/appsettings.json @@ -8,6 +8,40 @@ "AllowedHosts": "*", "ConnectionStrings": { "PostgresConnection": "Host=localhost;Port=5432;Database=postgres;Username=postgres;Password=Password" + }, + "RabbitMqOptions": { + "Host": "localhost", + "Port": "5672" + }, + "Serilog": { + "Using": [ + "Serilog.Sinks.Grafana.Loki" + ], + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft.Hosting.Lifetime": "Warning", + "Microsoft.EntityFrameworkCore": "Warning" + } + }, + "WriteTo": [ + { + "Name": "GrafanaLoki", + "Args": { + "uri": "http://localhost:3100", + "labels": [ + { + "key": "AuthApp", + "value": "My Main App" + } + ], + "propertiesAsLabels": [ + "AuthApp" + ] + } + } + ] } + } From 608afb39988b0273a2a4e811e501e371e3eabbae Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:37:01 +0300 Subject: [PATCH 06/52] Registered new services in DI container and added configuration for RabbitMqOptions and exception middleware Signed-off-by: BelugaChan --- MethodologyMain.API/Program.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index a401bba..6f2dfc0 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -2,6 +2,10 @@ using MethodTeams.Services; using System.Text.Json.Serialization; using MethodologyMain.Application.Interface; +using MethodologyMain.API.Middleware; +using AuthMetodology.Infrastructure.Models; +using AuthMetodology.Infrastructure.Interfaces; +using MethodologyMain.Infrastructure.Services; var builder = WebApplication.CreateBuilder(args); @@ -14,7 +18,12 @@ }); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); + +builder.Services.Configure(builder.Configuration.GetSection(nameof(RabbitMqOptions))); + builder.Services.AddScoped(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddDbContext(); var app = builder.Build(); @@ -31,4 +40,6 @@ app.MapControllers(); +app.UseMiddleware(); + app.Run(); From 61ebf6d2c86662a1090a9b188cba07ed83191cb3 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:38:04 +0300 Subject: [PATCH 07/52] Added new custom exception classes Signed-off-by: BelugaChan --- .../MemberAlreadyInTeamException.cs | 22 +++++++++++++++++++ .../Exceptions/TeamNotFoundException.cs | 13 +++++++++++ .../Exceptions/UserNotFoundException.cs | 19 ++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 MethodologyMain.Application/Exceptions/MemberAlreadyInTeamException.cs create mode 100644 MethodologyMain.Application/Exceptions/TeamNotFoundException.cs create mode 100644 MethodologyMain.Application/Exceptions/UserNotFoundException.cs diff --git a/MethodologyMain.Application/Exceptions/MemberAlreadyInTeamException.cs b/MethodologyMain.Application/Exceptions/MemberAlreadyInTeamException.cs new file mode 100644 index 0000000..4588b3f --- /dev/null +++ b/MethodologyMain.Application/Exceptions/MemberAlreadyInTeamException.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Application.Exceptions +{ + public class MemberAlreadyInTeamException : Exception + { + public MemberAlreadyInTeamException() + { + + } + + public MemberAlreadyInTeamException(string message) + : base(message) + { + + } + } +} diff --git a/MethodologyMain.Application/Exceptions/TeamNotFoundException.cs b/MethodologyMain.Application/Exceptions/TeamNotFoundException.cs new file mode 100644 index 0000000..f898077 --- /dev/null +++ b/MethodologyMain.Application/Exceptions/TeamNotFoundException.cs @@ -0,0 +1,13 @@ +namespace MethodologyMain.Application.Exceptions +{ + public class TeamNotFoundException : Exception + { + public TeamNotFoundException() { } + + public TeamNotFoundException(string message) + :base(message) + { + + } + } +} diff --git a/MethodologyMain.Application/Exceptions/UserNotFoundException.cs b/MethodologyMain.Application/Exceptions/UserNotFoundException.cs new file mode 100644 index 0000000..07357b5 --- /dev/null +++ b/MethodologyMain.Application/Exceptions/UserNotFoundException.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Application.Exceptions +{ + public class UserNotFoundException : Exception + { + public UserNotFoundException() { } + + public UserNotFoundException(string message) + :base(message) + { + + } + } +} From 4db4ffd144e0ce37b3b5da67f20253b096f36d36 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:38:45 +0300 Subject: [PATCH 08/52] Updated exception thrown logic Signed-off-by: BelugaChan --- .../Services/TeamService.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index 52c8466..c7d7f52 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -3,6 +3,7 @@ using MethodologyMain.Persistence.Interfaces; using MethodologyMain.Application.Interface; using MethodologyMain.Logic.Entities; +using MethodologyMain.Application.Exceptions; namespace MethodTeams.Services { @@ -20,7 +21,7 @@ public async Task CreateTeamAsync(string name, string description, G // Проверка, что у пользователя нет другой команды для этого if (await teamRepo.CheckUserTeamInHackAsync(captainId, HackathonId)) { - throw new InvalidOperationException("Пользователь уже состоит в команде для данного события"); + throw new MemberAlreadyInTeamException(); } // Создание команды var team = new TeamEntity @@ -49,7 +50,7 @@ public async Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, bool isAdm { if (!await teamRepo.CheckTeamExistAsync(teamId)) { - throw new KeyNotFoundException("Команда не найдена"); + throw new TeamNotFoundException(); } if (await teamRepo.GetCaptainIdAsync(teamId) != requestingUserId && !isAdmin) @@ -65,7 +66,7 @@ public async Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUs { if (!await teamRepo.CheckTeamExistAsync(teamId)) { - throw new KeyNotFoundException("Команда не найдена"); + throw new TeamNotFoundException(); } Guid hackathonId = await teamRepo.GetHackathonIdAsync(teamId); @@ -78,13 +79,13 @@ public async Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUs // Проверка, что пользователь не состоит в команде этого события if (await teamRepo.CheckUserTeamInHackAsync(userId, hackathonId)) { - throw new InvalidOperationException("Пользователь уже состоит в команде для данного события"); + throw new MemberAlreadyInTeamException(); } // Проверка, что пользователь не является уже членом этой команды if (await teamRepo.CheckUserInTeamAsync(userId, teamId)) { - throw new InvalidOperationException("Пользователь уже состоит в этой команде"); + throw new MemberAlreadyInTeamException(); } // Добавление пользователя в команду @@ -96,7 +97,7 @@ public async Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid request { if (!await teamRepo.CheckTeamExistAsync(teamId)) { - throw new KeyNotFoundException("Команда не найдена"); + throw new TeamNotFoundException(); } // Проверка прав: капитан может удалить любого, участник - только себя @@ -116,7 +117,7 @@ public async Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid request if (!await teamRepo.CheckUserInTeamAsync(userId, teamId)) { - throw new KeyNotFoundException("Пользователь не найден в команде"); + throw new UserNotFoundException(); } await teamRepo.RemoveMemberAsync(userId, teamId); @@ -127,7 +128,7 @@ public async Task TransferCaptainRightsAsync(Guid teamId, Guid newCaptainId, Gui { if (!await teamRepo.CheckTeamExistAsync(teamId)) { - throw new KeyNotFoundException("Команда не найдена"); + throw new TeamNotFoundException(); } if (await teamRepo.GetCaptainIdAsync(teamId) != currentCaptainId) @@ -150,7 +151,7 @@ public async Task GetTeamByIdAsync(Guid teamId) { if (!await teamRepo.CheckTeamExistAsync(teamId)) { - throw new KeyNotFoundException("Команда не найдена"); + throw new TeamNotFoundException(); } return await teamRepo.GetByIdAsync(teamId); @@ -161,7 +162,7 @@ public async Task> GetTeamMembersAsync(Guid teamId) { if (!await teamRepo.CheckTeamExistAsync(teamId)) { - throw new KeyNotFoundException("Команда не найдена"); + throw new TeamNotFoundException(); } return await teamRepo.GetTeamMembersAsync(teamId); From 768eb312558196550ff1a6273f5ef818300b8957 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:41:24 +0300 Subject: [PATCH 09/52] Added interfaces for rabbit and log publish services Signed-off-by: BelugaChan --- .../Interfaces/ILogQueueService.cs | 9 +++++++++ .../Interfaces/IRabbitMqService.cs | 10 ++++++++++ 2 files changed, 19 insertions(+) create mode 100644 MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs create mode 100644 MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs diff --git a/MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs b/MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs new file mode 100644 index 0000000..8a901fc --- /dev/null +++ b/MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs @@ -0,0 +1,9 @@ +using AuthMetodology.Infrastructure.Models; + +namespace AuthMetodology.Infrastructure.Interfaces +{ + public interface ILogQueueService + { + Task SendLogEventAsync(RabbitMqLogPublish message); + } +} diff --git a/MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs b/MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs new file mode 100644 index 0000000..e2c6c27 --- /dev/null +++ b/MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs @@ -0,0 +1,10 @@ +using RabbitMQ.Client; + +namespace AuthMetodology.Infrastructure.Interfaces; + +public interface IRabbitMqService +{ + //Task GetConnectionAsync(); + Task SendMessageAsync(T message, string queueName) + where T : class; +} \ No newline at end of file From 5c2711e04df0762a30e4989f5335aa234ce0eb15 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:42:01 +0300 Subject: [PATCH 10/52] Added new model which connect with rabbit Signed-off-by: BelugaChan --- .../Models/RabbitMqLogPublish.cs | 15 +++++++++++++++ .../Models/RabbitMqOptions.cs | 8 ++++++++ 2 files changed, 23 insertions(+) create mode 100644 MethodologyMain.Infrastructure/Models/RabbitMqLogPublish.cs create mode 100644 MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqLogPublish.cs b/MethodologyMain.Infrastructure/Models/RabbitMqLogPublish.cs new file mode 100644 index 0000000..646bd5f --- /dev/null +++ b/MethodologyMain.Infrastructure/Models/RabbitMqLogPublish.cs @@ -0,0 +1,15 @@ +using Serilog.Events; + +namespace AuthMetodology.Infrastructure.Models +{ + public class RabbitMqLogPublish + { + public required string Message { get; set; } + + public DateTime TimeStamp { get; set; } = DateTime.UtcNow; + + public required LogEventLevel LogLevel { get; set; } + + public required string ServiceName { get; set; } + } +} diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs b/MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs new file mode 100644 index 0000000..0a4ec48 --- /dev/null +++ b/MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs @@ -0,0 +1,8 @@ +namespace AuthMetodology.Infrastructure.Models; + +public class RabbitMqOptions +{ + public string Host { get; set; } = string.Empty; + + public int Port { get; set; } +} \ No newline at end of file From d439ac4c00ba87457deea639d45a0435d8199843 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:42:31 +0300 Subject: [PATCH 11/52] Added new nuget packages Signed-off-by: BelugaChan --- .../MethodologyMain.Infrastructure.csproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj b/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj index 2150e37..a4a798b 100644 --- a/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj +++ b/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj @@ -7,4 +7,10 @@ enable + + + + + + From a5c708c362293815890d5c63445e1dc7e3764521 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Thu, 10 Apr 2025 19:43:21 +0300 Subject: [PATCH 12/52] Added implementation of rabbit and log publish interfaces Signed-off-by: BelugaChan --- .../Services/LogQueueService.cs | 17 +++++ .../Services/RabbitMqService.cs | 76 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 MethodologyMain.Infrastructure/Services/LogQueueService.cs create mode 100644 MethodologyMain.Infrastructure/Services/RabbitMqService.cs diff --git a/MethodologyMain.Infrastructure/Services/LogQueueService.cs b/MethodologyMain.Infrastructure/Services/LogQueueService.cs new file mode 100644 index 0000000..8b2c34d --- /dev/null +++ b/MethodologyMain.Infrastructure/Services/LogQueueService.cs @@ -0,0 +1,17 @@ +using AuthMetodology.Infrastructure.Interfaces; +using AuthMetodology.Infrastructure.Models; + +namespace MethodologyMain.Infrastructure.Services +{ + public class LogQueueService : ILogQueueService + { + private readonly IRabbitMqService rabbitMqService; + private readonly string QueueName = "LogQueue"; + public LogQueueService(IRabbitMqService rabbitMqService) => this.rabbitMqService = rabbitMqService; + + public async Task SendLogEventAsync(RabbitMqLogPublish message) + { + await rabbitMqService.SendMessageAsync(message, QueueName); + } + } +} diff --git a/MethodologyMain.Infrastructure/Services/RabbitMqService.cs b/MethodologyMain.Infrastructure/Services/RabbitMqService.cs new file mode 100644 index 0000000..eb18e5b --- /dev/null +++ b/MethodologyMain.Infrastructure/Services/RabbitMqService.cs @@ -0,0 +1,76 @@ +using AuthMetodology.Infrastructure.Interfaces; +using AuthMetodology.Infrastructure.Models; +using Microsoft.Extensions.Options; +using RabbitMQ.Client; +using System.Text.Json; + +namespace MethodologyMain.Infrastructure.Services +{ + public class RabbitMqService : IRabbitMqService, IAsyncDisposable + { + private IConnection? connection; + private bool disposed; + private SemaphoreSlim connectionLock = new SemaphoreSlim(1,1); + private readonly RabbitMqOptions options; + public RabbitMqService(IOptions options) + { + this.options = options.Value; + } + public async ValueTask DisposeAsync() + { + if (disposed) + return; + + disposed = true; + if (connection?.IsOpen == true) + { + await connection.CloseAsync(); + } + connection?.Dispose(); + connectionLock.Dispose(); + GC.SuppressFinalize(this); + } + + private async Task GetConnectionAsync() + { + await connectionLock.WaitAsync(); + try + { + if (connection?.IsOpen == true) return connection; + + connection?.Dispose(); + var factory = new ConnectionFactory() + { + HostName = options.Host, + Port = options.Port + }; + connection = await factory.CreateConnectionAsync(); + return connection; + } + finally + { + connectionLock.Release(); + } + } + + public async Task SendMessageAsync(T message, string queueName) where T : class + { + connection = await GetConnectionAsync(); + + using (var channel = await connection.CreateChannelAsync()) + { + await channel.QueueDeclareAsync( + queue: queueName, + durable: false, + exclusive: false, + autoDelete: false, + arguments: null + ); + + var messageBody = JsonSerializer.SerializeToUtf8Bytes(message); + + await channel.BasicPublishAsync(exchange: "", routingKey: queueName, messageBody); + }; + } + } +} From ab3a8575cd8bc57f6c4e0966dba9c1c15d161dff Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 13 Apr 2025 23:18:52 +0300 Subject: [PATCH 13/52] Add CancellationToken into TeamController --- .../Controllers/TeamController.cs | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index c3d5382..ec0e179 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -13,18 +13,18 @@ namespace MethodologyMain.API.Controllers [Route("api/[controller]")] public class TeamController : ControllerBase { - private readonly ITeamService _teamService; + private readonly ITeamService teamService; private readonly ILogQueueService logQueueService; public TeamController(ITeamService teamService, ILogQueueService logQueueService) { - _teamService = teamService; + this.teamService = teamService; this.logQueueService = logQueueService; } // Создание команды [HttpPost] //[Authorize] - public async Task> CreateTeam([FromBody] CreateTeamDto dto) + public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { @@ -34,7 +34,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish TimeStamp = DateTime.UtcNow }); Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена - var team = await _teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId); + var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); return CreatedAtAction(nameof(GetTeam), new { id = team.Id }, team); //try //{ @@ -48,7 +48,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish // Получение информации о команде [HttpGet("{id}")] - public async Task> GetTeam(Guid id) + public async Task> GetTeam(Guid id, CancellationToken token) { await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { @@ -57,7 +57,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish Message = "GET api/Team/id was called", TimeStamp = DateTime.UtcNow }); - var team = await _teamService.GetTeamByIdAsync(id); + var team = await teamService.GetTeamByIdAsync(id, token); return Ok(team); //try //{ @@ -72,7 +72,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish // Удаление команды [HttpDelete("{id}")] //[Authorize] - public async Task DeleteTeam(Guid id) + public async Task DeleteTeam(Guid id, CancellationToken token) { await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { @@ -84,7 +84,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish Guid currentUserId = GetCurrentUserId(); bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора - await _teamService.DeleteTeamAsync(id, currentUserId, isAdmin); + await teamService.DeleteTeamAsync(id, currentUserId, token, isAdmin); return NoContent(); //try //{ @@ -103,7 +103,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish // Добавление пользователя в команду [HttpPost("{id}/members")] //[Authorize] - public async Task AddMember(Guid id, [FromBody] AddUserDto dto) + public async Task AddMember(Guid id, [FromBody] AddUserDto dto, CancellationToken token) { await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { @@ -113,7 +113,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish TimeStamp = DateTime.UtcNow }); Guid currentUserId = GetCurrentUserId(); - await _teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId); + await teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId, token); return NoContent(); //try //{ @@ -136,7 +136,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish // Удаление пользователя из команды [HttpDelete("{id}/members/{userId}")] //[Authorize] - public async Task RemoveMember(Guid id, Guid userId) + public async Task RemoveMember(Guid id, Guid userId, CancellationToken token) { await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { @@ -146,7 +146,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish TimeStamp = DateTime.UtcNow }); Guid currentUserId = GetCurrentUserId(); - await _teamService.RemoveUserFromTeamAsync(id, userId, currentUserId); + await teamService.RemoveUserFromTeamAsync(id, userId, currentUserId, token); return NoContent(); //try //{ @@ -168,7 +168,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish // Получение списка участников команды [HttpGet("{id}/members")] - public async Task>> GetTeamMembers(Guid id) + public async Task>> GetTeamMembers(Guid id, CancellationToken token) { await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { @@ -177,7 +177,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish Message = "GET api/Team/id/members was called", TimeStamp = DateTime.UtcNow }); - var members = await _teamService.GetTeamMembersAsync(id); + var members = await teamService.GetTeamMembersAsync(id, token); return Ok(members); //try //{ @@ -192,7 +192,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish // Передача прав капитана [HttpPut("{id}/captain")] //[Authorize] - public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto) + public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto, CancellationToken token) { await logQueueService.SendLogEventAsync(new RabbitMqLogPublish { @@ -202,7 +202,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish TimeStamp = DateTime.UtcNow }); Guid currentUserId = GetCurrentUserId(); - await _teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId); + await teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId, token); return NoContent(); //try //{ @@ -222,42 +222,42 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish //} } - // Получение списка команд для события - [HttpGet("event/{eventId}")] - public async Task>> GetTeamsByEvent(Guid eventId) - { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "GET api/Team/event/eventId was called", - TimeStamp = DateTime.UtcNow - }); - var teams = await _teamService.GetTeamsByEventIdAsync(eventId); - return Ok(teams); - } + //// Получение списка команд для события + //[HttpGet("event/{eventId}")] + //public async Task>> GetTeamsByEvent(Guid eventId) + //{ + // await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "GET api/Team/event/eventId was called", + // TimeStamp = DateTime.UtcNow + // }); + // var teams = await _teamService.GetTeamsByEventIdAsync(eventId); + // return Ok(teams); + //} - // Получение команды пользователя для конкретного события - [HttpGet("event/{eventId}/user")] - //[Authorize] - public async Task> GetUserTeamForEvent(Guid eventId) - { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "GET api/Team/event/eventId/user was called", - TimeStamp = DateTime.UtcNow - }); - Guid currentUserId = GetCurrentUserId(); - var team = await _teamService.GetUserTeamForEventAsync(currentUserId, eventId); + //// Получение команды пользователя для конкретного события + //[HttpGet("event/{eventId}/user")] + ////[Authorize] + //public async Task> GetUserTeamForEvent(Guid eventId) + //{ + // await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "GET api/Team/event/eventId/user was called", + // TimeStamp = DateTime.UtcNow + // }); + // Guid currentUserId = GetCurrentUserId(); + // var team = await _teamService.GetUserTeamForEventAsync(currentUserId, eventId); - if (team == null) - { - return NotFound(); - } + // if (team == null) + // { + // return NotFound(); + // } - return Ok(team); + // return Ok(team); //try //{ @@ -267,7 +267,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish //{ // return BadRequest(ex.Message); //} - } + //} // Вспомогательный метод для получения ID текущего пользователя //private int GetCurrentUserId() From 606571208db64fb2dd134b7a5b83aa78f11f4a89 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 13 Apr 2025 23:20:26 +0300 Subject: [PATCH 14/52] Add CancellationToken into GenericRepository --- .../Interfaces/IGenericRepository.cs | 14 ++++---- .../Repository/GenericRepository.cs | 32 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs b/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs index cf8e8b0..d6afcd6 100644 --- a/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs @@ -4,12 +4,12 @@ namespace MethodologyMain.Persistence.Interfaces { public interface IGenericRepository where T : class { - Task GetByIdAsync(Guid id); - Task> GetAllAsync(); - Task> FindAsync(Expression> expression); - Task AddAsync(T entity); - Task AddRangeAsync(IEnumerable entities); - Task RemoveAsync(T entity); - Task RemoveRangeAsync(IEnumerable entities); + Task AddAsync(T entity, CancellationToken token); + Task AddRangeAsync(IEnumerable entities, CancellationToken token); + Task> FindAsync(Expression> expression, CancellationToken token); + Task> GetAllAsync(CancellationToken token); + Task GetByIdAsync(Guid id, CancellationToken token); + Task RemoveAsync(T entity, CancellationToken token); + Task RemoveRangeAsync(IEnumerable entities, CancellationToken token); } } diff --git a/MethodologyMain.Persistence/Repository/GenericRepository.cs b/MethodologyMain.Persistence/Repository/GenericRepository.cs index a22be42..8b57920 100644 --- a/MethodologyMain.Persistence/Repository/GenericRepository.cs +++ b/MethodologyMain.Persistence/Repository/GenericRepository.cs @@ -13,43 +13,43 @@ public GenericRepository(MyDbContext context) _context = context; } - public async Task AddAsync(T entity) + public async Task AddAsync(T entity, CancellationToken token) { - await _context.Set().AddAsync(entity); - await _context.SaveChangesAsync(); + _context.Set().Add(entity); + await _context.SaveChangesAsync(token); } - public async Task AddRangeAsync(IEnumerable entities) + public async Task AddRangeAsync(IEnumerable entities, CancellationToken token) { - await _context.Set().AddRangeAsync(entities); - await _context.SaveChangesAsync(); + _context.Set().AddRange(entities); + await _context.SaveChangesAsync(token); } - public async Task> FindAsync(Expression> expression) + public async Task> FindAsync(Expression> expression, CancellationToken token) { - return await _context.Set().Where(expression).ToListAsync(); + return await _context.Set().Where(expression).ToListAsync(token); } - public async Task> GetAllAsync() + public async Task> GetAllAsync(CancellationToken token) { - return await _context.Set().ToListAsync(); + return await _context.Set().ToListAsync(token); } - public async Task GetByIdAsync(Guid id) + public async Task GetByIdAsync(Guid id, CancellationToken token) { - return await _context.Set().FindAsync(id); + return await _context.Set().FindAsync([id], token); } - public async Task RemoveAsync(T entity) + public async Task RemoveAsync(T entity, CancellationToken token) { _context.Set().Remove(entity); - await _context.SaveChangesAsync(); + await _context.SaveChangesAsync(token); } - public async Task RemoveRangeAsync(IEnumerable entities) + public async Task RemoveRangeAsync(IEnumerable entities, CancellationToken token) { _context.Set().RemoveRange(entities); - await _context.SaveChangesAsync(); + await _context.SaveChangesAsync(token); } } } From 6101e6e4a58b9db9054164c6e4949b72c7b8b442 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 13 Apr 2025 23:21:10 +0300 Subject: [PATCH 15/52] Refactor TeamRepository and add CancellationToken --- .../Interfaces/ITeamRepository.cs | 21 ++-- .../Repository/TeamRepository.cs | 100 +++++++++--------- 2 files changed, 61 insertions(+), 60 deletions(-) diff --git a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs index d379d45..ed7d7b7 100644 --- a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs @@ -1,20 +1,19 @@ using MethodologyMain.Logic.Entities; -using MethodTeams.Models; namespace MethodologyMain.Persistence.Interfaces { public interface ITeamRepository : IGenericRepository { - Task AddMemberAsync(Guid userId, Guid teamId); - Task CheckUserInTeamAsync(Guid userId, Guid teamId); - Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId); - Task CheckTeamExistAsync(Guid teamId); - Task RemoveTeamAsync(Guid teamId); - Task RemoveMemberAsync(Guid userId, Guid teamId); - Task TransferCaptainAsync(Guid newCaptainId, Guid teamId); - Task GetCaptainIdAsync(Guid teamId); - Task GetHackathonIdAsync(Guid teamId); - Task> GetTeamMembersAsync(Guid teamId); + Task AddMemberAsync(Guid userId, Guid teamId, CancellationToken token); + Task CheckTeamExistAsync(Guid teamId, CancellationToken token); + Task CheckUserInTeamAsync(Guid userId, Guid teamId, CancellationToken token); + Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token); + Task GetCaptainIdAsync(Guid teamId, CancellationToken token); + Task GetHackathonIdAsync(Guid teamId, CancellationToken token); + Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task RemoveMemberAsync(Guid userId, Guid teamId, CancellationToken token); + Task RemoveTeamAsync(Guid teamId, CancellationToken token); + Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, CancellationToken token); } } diff --git a/MethodologyMain.Persistence/Repository/TeamRepository.cs b/MethodologyMain.Persistence/Repository/TeamRepository.cs index 02b9146..ba6ccf9 100644 --- a/MethodologyMain.Persistence/Repository/TeamRepository.cs +++ b/MethodologyMain.Persistence/Repository/TeamRepository.cs @@ -1,10 +1,8 @@ using MethodologyMain.Logic.Entities; using MethodologyMain.Persistence.Interfaces; using MethodTeams.Data; -using MethodTeams.Models; using Microsoft.EntityFrameworkCore; - namespace MethodologyMain.Persistence.Repository { public class TeamRepository : GenericRepository, ITeamRepository @@ -12,87 +10,91 @@ public class TeamRepository : GenericRepository, ITeamRepository public TeamRepository(MyDbContext context) : base(context) { } - public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId) + private static void CheckCancellation(CancellationToken token) + { + token.ThrowIfCancellationRequested(); + } + private async Task GetTeamNoTrackingAsync(Guid teamId, CancellationToken token) { - // User cannot be null - var user = await _context.Users. - AsNoTracking(). - FirstAsync(e => e.Id == userId); - return user.Teams.Find(m => m.Team.HackathonId == hackathonId) - != null; + CheckCancellation(token); + return await _context.Teams + .AsNoTracking() + .FirstAsync(e => e.Id == teamId, token); } - public async Task CheckUserInTeamAsync(Guid userId, Guid teamId) + private async Task GetTeamAsync(Guid teamId, CancellationToken token) { - // Team cannot be null checked before - var team = await _context.Teams. - AsNoTracking(). - FirstAsync(e => e.Id == teamId); - return team.Members.Find(m => m.UserId == userId) - != null; + CheckCancellation(token); + return await _context.Teams.FindAsync([teamId], token); } - public async Task CheckTeamExistAsync(Guid teamId) + private async Task SaveChangesAsync(CancellationToken token) { - // Team cannot be null checked before - var team = await _context.Teams. - AsNoTracking(). - FirstAsync(e => e.Id == teamId); + CheckCancellation(token); + await _context.SaveChangesAsync(token); + } + public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token) + { + CheckCancellation(token); + var user = await _context.Users + .AsNoTracking() + .FirstAsync(e => e.Id == userId, token); + return user.Teams.Find(m => m.Team.HackathonId == hackathonId) != null; + } + public async Task CheckUserInTeamAsync(Guid userId, Guid teamId, CancellationToken token) + { + var team = await GetTeamNoTrackingAsync(teamId, token); + return team.Members.Find(m => m.UserId == userId) != null; + } + public async Task CheckTeamExistAsync(Guid teamId, CancellationToken token) + { + var team = await GetTeamNoTrackingAsync(teamId, token); return team != null; } - public async Task AddMemberAsync(Guid userId, Guid teamId) + public async Task AddMemberAsync(Guid userId, Guid teamId, CancellationToken token) { - // Team cannot be null checked before - var team = await _context.Teams.FindAsync(teamId); + var team = await GetTeamAsync(teamId, token); team.Members.Add(new UserTeamEntity { TeamId = teamId, UserId = userId, JoinedAt = DateTime.UtcNow }); - await _context.SaveChangesAsync(); + await SaveChangesAsync(token); } - public async Task RemoveTeamAsync(Guid teamId) + public async Task RemoveTeamAsync(Guid teamId, CancellationToken token) { - // Удаление связанных участников (maybe not required) - var team = await _context.Teams.FindAsync(teamId); + var team = await GetTeamAsync(teamId, token); if (team.Members is not null) { var _ = team.Members.RemoveAll; } - // Удаление команды _context.Teams.Remove(team); - await _context.SaveChangesAsync(); + await SaveChangesAsync(token); } - - public async Task RemoveMemberAsync(Guid userId, Guid teamId) + public async Task RemoveMemberAsync(Guid userId, Guid teamId, CancellationToken token) { - var team = await _context.Teams.FindAsync(teamId); + var team = await GetTeamAsync(teamId, token); var member = team.Members.Find(e => e.UserId == userId); team.Members.Remove(member); - await _context.SaveChangesAsync(); + await SaveChangesAsync(token); } - - public async Task TransferCaptainAsync(Guid newCaptainId, Guid teamId) + public async Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, CancellationToken token) { - var team = await _context.Teams.FindAsync(teamId); + var team = await GetTeamAsync(teamId, token); var member = team.Members.Find(e => e.UserId == newCaptainId); team.CaptainId = newCaptainId; - await _context.SaveChangesAsync(); + await SaveChangesAsync(token); } - public async Task GetCaptainIdAsync(Guid teamId) + public async Task GetCaptainIdAsync(Guid teamId, CancellationToken token) { - var team = await _context.Teams. - AsNoTracking(). - FirstAsync(e => e.Id == teamId); + var team = await GetTeamNoTrackingAsync(teamId, token); return team.CaptainId; } - public async Task GetHackathonIdAsync(Guid teamId) + public async Task GetHackathonIdAsync(Guid teamId, CancellationToken token) { - var team = await _context.Teams. - AsNoTracking(). - FirstAsync(e => e.Id == teamId); + var team = await GetTeamNoTrackingAsync(teamId, token); return team.HackathonId; } - public async Task> GetTeamMembersAsync(Guid teamId) + public async Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token) { - var team = await _context.Teams.FindAsync(teamId); + var team = await GetTeamAsync(teamId, token); return team.Members.Select(m => m.UserId).ToList(); } } -} +} \ No newline at end of file From c2c06e272ba854ab43c75dd660eceb14efe2b735 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 13 Apr 2025 23:22:27 +0300 Subject: [PATCH 16/52] Refactor TeamService and add CancallationToken --- .../Interface/ITeamService.cs | 14 +- .../Interface/ITeamValidationService.cs | 14 ++ .../Services/TeamService.cs | 177 +++++++----------- .../Services/TeamValidationService.cs | 82 ++++++++ 4 files changed, 168 insertions(+), 119 deletions(-) create mode 100644 MethodologyMain.Application/Interface/ITeamValidationService.cs create mode 100644 MethodologyMain.Application/Services/TeamValidationService.cs diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index 1458842..65cfad8 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -4,15 +4,15 @@ namespace MethodologyMain.Application.Interface { public interface ITeamService { - Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId); - Task CreateTeamAsync(string name, string description, Guid captainId, Guid eventId); - Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, bool isAdmin = false); - Task GetTeamByIdAsync(Guid teamId); - Task> GetTeamMembersAsync(Guid teamId); + Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); + Task CreateTeamAsync(string name, string description, Guid captainId, Guid eventId, CancellationToken token); + Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, CancellationToken token, bool isAdmin = false); + Task GetTeamByIdAsync(Guid teamId, CancellationToken token); + Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); //Task> GetTeamsByEventIdAsync(Guid eventId); //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); //Task IsUserTeamCaptainAsync(Guid teamId, Guid userId); - Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid requestingUserId); - Task TransferCaptainRightsAsync(Guid teamId, Guid newCaptainId, Guid currentCaptainId); + Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); + Task TransferCaptainRightsAsync(Guid teamId, Guid newCaptainId, Guid currentCaptainId, CancellationToken token); } } \ No newline at end of file diff --git a/MethodologyMain.Application/Interface/ITeamValidationService.cs b/MethodologyMain.Application/Interface/ITeamValidationService.cs new file mode 100644 index 0000000..2303803 --- /dev/null +++ b/MethodologyMain.Application/Interface/ITeamValidationService.cs @@ -0,0 +1,14 @@ +namespace MethodologyMain.Application.Interface +{ + public interface ITeamValidationService + { + Task CheckCaptainKick(Guid teamId, Guid userId, CancellationToken token); + Task CheckTeamExistsAsync(Guid teamId, CancellationToken token); + Task CheckUserInTeamAsync(Guid userId, Guid teamId, CancellationToken token); + Task CheckUserIsCaptainAsync(Guid teamId, Guid userId, CancellationToken token); + Task CheckUserIsCaptainOrAdminAsync(Guid teamId, Guid userId, bool isAdmin, CancellationToken token); + Task CheckUserIsCaptainOrRequestedAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); + Task CheckUserNotInAnyTeamForHackathonAsync(Guid userId, Guid hackathonId, CancellationToken token); + Task CheckUserNotInTeamAsync(Guid userId, Guid teamId, CancellationToken token); + } +} \ No newline at end of file diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index c7d7f52..2164008 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -1,28 +1,33 @@ -using Microsoft.EntityFrameworkCore; -using AutoMapper; -using MethodologyMain.Persistence.Interfaces; +using MethodologyMain.Persistence.Interfaces; using MethodologyMain.Application.Interface; using MethodologyMain.Logic.Entities; using MethodologyMain.Application.Exceptions; namespace MethodTeams.Services { - public class TeamService : ITeamService + public class TeamService: ITeamService { private readonly ITeamRepository teamRepo; - public TeamService(ITeamRepository teamRepo) + private readonly ITeamValidationService validation; + public TeamService( + ITeamRepository teamRepo, + ITeamValidationService validation) { this.teamRepo = teamRepo; + this.validation = validation; } // Создание новой команды - public async Task CreateTeamAsync(string name, string description, Guid captainId, Guid HackathonId) + public async Task CreateTeamAsync( + string name, + string description, + Guid captainId, + Guid HackathonId, + CancellationToken token + ) { // Проверка, что у пользователя нет другой команды для этого - if (await teamRepo.CheckUserTeamInHackAsync(captainId, HackathonId)) - { - throw new MemberAlreadyInTeamException(); - } + await validation.CheckUserNotInAnyTeamForHackathonAsync(captainId, HackathonId, token); // Создание команды var team = new TeamEntity { @@ -41,133 +46,81 @@ public async Task CreateTeamAsync(string name, string description, G JoinedAt = DateTime.UtcNow }; team.Members.Add(member); - await teamRepo.AddAsync(team); + await teamRepo.AddAsync(team, token); return team; } // Удаление команды (только капитаном или администратором) - public async Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, bool isAdmin = false) + public async Task DeleteTeamAsync( + Guid teamId, + Guid requestingUserId, + CancellationToken token, + bool isAdmin = false + ) { - if (!await teamRepo.CheckTeamExistAsync(teamId)) - { - throw new TeamNotFoundException(); - } - - if (await teamRepo.GetCaptainIdAsync(teamId) != requestingUserId && !isAdmin) - { - throw new UnauthorizedAccessException("Только капитан команды или администратор может удалить команду"); - } - - await teamRepo.RemoveTeamAsync(teamId); + await validation.CheckTeamExistsAsync(teamId, token); + await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); + await teamRepo.RemoveTeamAsync(teamId, token); } // Добавление пользователя в команду - public async Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId) + public async Task AddUserToTeamAsync( + Guid teamId, + Guid userId, + Guid requestingUserId, + CancellationToken token + ) { - if (!await teamRepo.CheckTeamExistAsync(teamId)) - { - throw new TeamNotFoundException(); - } - - Guid hackathonId = await teamRepo.GetHackathonIdAsync(teamId); - - if (await teamRepo.GetCaptainIdAsync(teamId) != requestingUserId) - { - throw new UnauthorizedAccessException("Только капитан команды может добавлять участников"); - } - - // Проверка, что пользователь не состоит в команде этого события - if (await teamRepo.CheckUserTeamInHackAsync(userId, hackathonId)) - { - throw new MemberAlreadyInTeamException(); - } - - // Проверка, что пользователь не является уже членом этой команды - if (await teamRepo.CheckUserInTeamAsync(userId, teamId)) - { - throw new MemberAlreadyInTeamException(); - } - - // Добавление пользователя в команду - await teamRepo.AddMemberAsync(userId, teamId); + await validation.CheckTeamExistsAsync(teamId, token); + Guid hackathonId = (Guid)await teamRepo.GetHackathonIdAsync(teamId, token); + await validation.CheckUserIsCaptainAsync(teamId, requestingUserId, token); + await validation.CheckUserNotInTeamAsync(userId, teamId, token); + await validation.CheckUserNotInAnyTeamForHackathonAsync(userId, hackathonId, token); + await teamRepo.AddMemberAsync(userId, teamId, token); } // Удаление пользователя из команды - public async Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid requestingUserId) + public async Task RemoveUserFromTeamAsync( + Guid teamId, + Guid userId, + Guid requestingUserId, + CancellationToken token + ) { - if (!await teamRepo.CheckTeamExistAsync(teamId)) - { - throw new TeamNotFoundException(); - } - + await validation.CheckTeamExistsAsync(teamId, token); // Проверка прав: капитан может удалить любого, участник - только себя - Guid captainId = await teamRepo.GetCaptainIdAsync(teamId); - bool canRemove = (captainId == requestingUserId) || (userId == requestingUserId); - - if (!canRemove) - { - throw new UnauthorizedAccessException("Недостаточно прав для удаления участника"); - } - + await validation.CheckUserIsCaptainOrRequestedAsync(teamId, userId, requestingUserId, token); // Нельзя удалить капитана - if (userId == captainId) - { - throw new InvalidOperationException("Капитан не может быть удален из команды. Сначала передайте права капитана другому участнику."); - } - - if (!await teamRepo.CheckUserInTeamAsync(userId, teamId)) - { - throw new UserNotFoundException(); - } - - await teamRepo.RemoveMemberAsync(userId, teamId); + await validation.CheckCaptainKick(teamId, userId, token); + await validation.CheckUserInTeamAsync(userId, teamId, token); + await teamRepo.RemoveMemberAsync(userId, teamId, token); } - // Передача прав капитана - public async Task TransferCaptainRightsAsync(Guid teamId, Guid newCaptainId, Guid currentCaptainId) + public async Task TransferCaptainRightsAsync( + Guid teamId, + Guid newCaptainId, + Guid currentCaptainId, + CancellationToken token + ) { - if (!await teamRepo.CheckTeamExistAsync(teamId)) - { - throw new TeamNotFoundException(); - } - - if (await teamRepo.GetCaptainIdAsync(teamId) != currentCaptainId) - { - throw new UnauthorizedAccessException("Только текущий капитан может передать права капитана"); - } - - // Проверка, что новый капитан является участником команды - if (!await teamRepo.CheckUserInTeamAsync(newCaptainId, teamId)) - { - throw new InvalidOperationException("Новый капитан должен быть участником команды"); - } - - // Передача прав - await teamRepo.TransferCaptainAsync(newCaptainId, teamId); + await validation.CheckTeamExistsAsync(teamId, token); + await validation.CheckUserIsCaptainAsync(teamId, currentCaptainId, token); + await validation.CheckUserInTeamAsync(newCaptainId, teamId, token); + await teamRepo.TransferCaptainAsync(newCaptainId, teamId, token); } - // Получение информации о команде по ID - public async Task GetTeamByIdAsync(Guid teamId) + public async Task GetTeamByIdAsync(Guid teamId, CancellationToken token) { - if (!await teamRepo.CheckTeamExistAsync(teamId)) - { - throw new TeamNotFoundException(); - } - - return await teamRepo.GetByIdAsync(teamId); + await validation.CheckTeamExistsAsync(teamId, token); + return await teamRepo.GetByIdAsync(teamId, token); } - // Получение списка участников команды - public async Task> GetTeamMembersAsync(Guid teamId) + public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken token) { - if (!await teamRepo.CheckTeamExistAsync(teamId)) - { - throw new TeamNotFoundException(); - } - - return await teamRepo.GetTeamMembersAsync(teamId); + await validation.CheckTeamExistsAsync(teamId, token); + return await teamRepo.GetTeamMembersAsync(teamId, token); } - + //// Проверка, является ли пользователь капитаном команды //public async Task IsUserTeamCaptainAsync(Guid teamId, Guid userId) //{ diff --git a/MethodologyMain.Application/Services/TeamValidationService.cs b/MethodologyMain.Application/Services/TeamValidationService.cs new file mode 100644 index 0000000..fbdf79b --- /dev/null +++ b/MethodologyMain.Application/Services/TeamValidationService.cs @@ -0,0 +1,82 @@ +using MethodologyMain.Application.Exceptions; +using MethodologyMain.Application.Interface; +using MethodologyMain.Persistence.Interfaces; + +namespace MethodologyMain.Application.Services +{ + class TeamValidationService : ITeamValidationService + { + public readonly ITeamRepository teamRepo; + public TeamValidationService(ITeamRepository teamRepo) + { + this.teamRepo = teamRepo; + } + + // Проверка существования команды + public async Task CheckTeamExistsAsync(Guid teamId, CancellationToken token) + { + if (!await teamRepo.CheckTeamExistAsync(teamId, token)) + { + throw new TeamNotFoundException(); + } + } + // Проверка, что пользователь не состоит в команде для данного хакатона + public async Task CheckUserNotInAnyTeamForHackathonAsync(Guid userId, Guid hackathonId, CancellationToken token) + { + if (await teamRepo.CheckUserTeamInHackAsync(userId, hackathonId, token)) + { + throw new MemberAlreadyInTeamException(); + } + } + + // Проверка, что пользователь не состоит в конкретной команде + public async Task CheckUserNotInTeamAsync(Guid userId, Guid teamId, CancellationToken token) + { + if (await teamRepo.CheckUserInTeamAsync(userId, teamId, token)) + { + throw new MemberAlreadyInTeamException(); + } + } + + // Проверка, что пользователь состоит в команде + public async Task CheckUserInTeamAsync(Guid userId, Guid teamId, CancellationToken token) + { + if (!await teamRepo.CheckUserInTeamAsync(userId, teamId, token)) + { + throw new UserNotInTeamException(); + } + } + + // Проверка, что пользователь имеет права капитана + public async Task CheckUserIsCaptainAsync(Guid teamId, Guid userId, CancellationToken token) + { + if (await teamRepo.GetCaptainIdAsync(teamId, token) != userId) + { + throw new UnauthorizedAccessException(); + } + } + public async Task CheckUserIsCaptainOrAdminAsync(Guid teamId, Guid userId, bool isAdmin, CancellationToken token) + { + if (await teamRepo.GetCaptainIdAsync(teamId, token) != userId && !isAdmin) + { + throw new UnauthorizedAccessException(); + } + } + public async Task CheckUserIsCaptainOrRequestedAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token) + { + Guid captainId = (Guid)await teamRepo.GetCaptainIdAsync(teamId, token); + bool canRemove = (captainId == requestingUserId) || (userId == requestingUserId); + if (!canRemove) + { + throw new UnauthorizedAccessException(); + } + } + public async Task CheckCaptainKick(Guid teamId, Guid userId, CancellationToken token) + { + if (await teamRepo.GetCaptainIdAsync(teamId, token) == userId) + { + throw new InvalidOperationException("Капитан не может быть удален из команды. Сначала передайте права капитана другому участнику."); + } + } + } +} From 6d339ed4f2826cc35731e735c4e2429756cd291c Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 13 Apr 2025 23:24:06 +0300 Subject: [PATCH 17/52] Modify ExceptionMiddleware and add exception --- .../Middleware/ExceptionMiddleware.cs | 12 +++++++----- .../Exceptions/UserNotInTeamException.cs | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 MethodologyMain.Application/Exceptions/UserNotInTeamException.cs diff --git a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs index ea35fe2..21b5c2e 100644 --- a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs +++ b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs @@ -28,19 +28,21 @@ await logQueueService.SendLogEventAsync(new AuthMetodology.Infrastructure.Models Message = $"Exception was thrown.\nMessage: {ex.Message}\nSource: {ex.Source}", TimeStamp = DateTime.UtcNow }); - await HandleExceptionAsync(ex,context); + HandleException(ex,context); } } - private async Task HandleExceptionAsync(Exception ex, HttpContext context) + private static void HandleException(Exception ex, HttpContext context) { ExceptionResponse response = ex switch { MemberAlreadyInTeamException _ => new ExceptionResponse("Пользователь уже состоит в команде для данного события", System.Net.HttpStatusCode.Conflict), TeamNotFoundException _ => new ExceptionResponse("Команда не найдена", System.Net.HttpStatusCode.Conflict), - UnauthorizedAccessException _ => new ExceptionResponse(ex.Message, System.Net.HttpStatusCode.Unauthorized), - InvalidOperationException _ => new ExceptionResponse(ex.Message,System.Net.HttpStatusCode.Conflict), - UserNotFoundException _ => new ExceptionResponse("Пользователь не найден",System.Net.HttpStatusCode.Conflict), + UnauthorizedAccessException _ => new ExceptionResponse("У вас не таких прав", System.Net.HttpStatusCode.Unauthorized), + InvalidOperationException _ => new ExceptionResponse(ex.Message, System.Net.HttpStatusCode.Conflict), + UserNotFoundException _ => new ExceptionResponse("Пользователь не найден", System.Net.HttpStatusCode.Conflict), + UserNotInTeamException _ => new ExceptionResponse("Пользователь не в команде", System.Net.HttpStatusCode.Conflict), + _ => throw new NotImplementedException(), }; } } diff --git a/MethodologyMain.Application/Exceptions/UserNotInTeamException.cs b/MethodologyMain.Application/Exceptions/UserNotInTeamException.cs new file mode 100644 index 0000000..e3690ef --- /dev/null +++ b/MethodologyMain.Application/Exceptions/UserNotInTeamException.cs @@ -0,0 +1,16 @@ +namespace MethodologyMain.Application.Exceptions +{ + public class UserNotInTeamException : Exception + { + public UserNotInTeamException() + { + + } + + public UserNotInTeamException(string message) + : base(message) + { + + } + } +} \ No newline at end of file From f375139904ccf093d306d06a987e45f67515dec1 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Tue, 22 Apr 2025 02:07:03 +0300 Subject: [PATCH 18/52] Add Get All Teams endpoint --- .../Controllers/TeamController.cs | 31 ++++++++++++++ MethodologyMain.API/Program.cs | 7 +++- .../DTO/TeamInfoDto.cs | 4 +- .../Interface/ITeamService.cs | 2 + .../Services/TeamService.cs | 19 ++++++++- .../Services/TeamValidationService.cs | 2 +- .../Repository/TeamRepository.cs | 42 +++++++++---------- 7 files changed, 80 insertions(+), 27 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index ec0e179..cb6e247 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -222,6 +222,37 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish //} } + // Получение списка команд + [HttpGet] + public async Task>> GetTeamsAll(CancellationToken token) + { + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/Team was called", + TimeStamp = DateTime.UtcNow + }); + var teams = await teamService.GetTeamAllAsync(token); + return Ok(teams); + //try + //{ + + //} + //catch (KeyNotFoundException) + //{ + // return NotFound(); + //} + //catch (UnauthorizedAccessException ex) + //{ + // return Forbid(ex.Message); + //} + //catch (InvalidOperationException ex) + //{ + // return BadRequest(ex.Message); + //} + } + //// Получение списка команд для события //[HttpGet("event/{eventId}")] //public async Task>> GetTeamsByEvent(Guid eventId) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 6f2dfc0..e596012 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -2,10 +2,13 @@ using MethodTeams.Services; using System.Text.Json.Serialization; using MethodologyMain.Application.Interface; +using MethodologyMain.Application.Services; using MethodologyMain.API.Middleware; using AuthMetodology.Infrastructure.Models; using AuthMetodology.Infrastructure.Interfaces; using MethodologyMain.Infrastructure.Services; +using MethodologyMain.Persistence.Interfaces; +using MethodologyMain.Persistence.Repository; var builder = WebApplication.CreateBuilder(args); @@ -21,7 +24,9 @@ builder.Services.Configure(builder.Configuration.GetSection(nameof(RabbitMqOptions))); -builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddDbContext(); diff --git a/MethodologyMain.Application/DTO/TeamInfoDto.cs b/MethodologyMain.Application/DTO/TeamInfoDto.cs index 2533612..182b720 100644 --- a/MethodologyMain.Application/DTO/TeamInfoDto.cs +++ b/MethodologyMain.Application/DTO/TeamInfoDto.cs @@ -6,9 +6,9 @@ public class TeamInfoDto { public Guid Id { get; set; } public string Name { get; set; } - public string Description { get; set; } + public string? Description { get; set; } public Guid CaptainId { get; set; } - public Guid EventId { get; set; } + public Guid HackathonId { get; set; } public DateTime CreatedAt { get; set; } public int MemberCount { get; set; } } diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index 65cfad8..b5480b3 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -1,4 +1,5 @@ using MethodologyMain.Logic.Entities; +using MethodTeams.DTO; namespace MethodologyMain.Application.Interface { @@ -9,6 +10,7 @@ public interface ITeamService Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, CancellationToken token, bool isAdmin = false); Task GetTeamByIdAsync(Guid teamId, CancellationToken token); Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task> GetTeamAllAsync(CancellationToken token); //Task> GetTeamsByEventIdAsync(Guid eventId); //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); //Task IsUserTeamCaptainAsync(Guid teamId, Guid userId); diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index 2164008..dfeb4a7 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -2,6 +2,10 @@ using MethodologyMain.Application.Interface; using MethodologyMain.Logic.Entities; using MethodologyMain.Application.Exceptions; +using MethodTeams.Models; +using AutoMapper; +using MethodologyMain.Logic.Models; +using MethodTeams.DTO; namespace MethodTeams.Services { @@ -9,12 +13,15 @@ public class TeamService: ITeamService { private readonly ITeamRepository teamRepo; private readonly ITeamValidationService validation; + private readonly IMapper mapper; public TeamService( ITeamRepository teamRepo, - ITeamValidationService validation) + ITeamValidationService validation, + IMapper mapper) { this.teamRepo = teamRepo; this.validation = validation; + this.mapper = mapper; } // Создание новой команды @@ -120,7 +127,15 @@ public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken await validation.CheckTeamExistsAsync(teamId, token); return await teamRepo.GetTeamMembersAsync(teamId, token); } - + + // Получение списка команд + public async Task> GetTeamAllAsync(CancellationToken token) + { + + var teams = await teamRepo.GetAllAsync(token); + return mapper.Map>(teams); + } + //// Проверка, является ли пользователь капитаном команды //public async Task IsUserTeamCaptainAsync(Guid teamId, Guid userId) //{ diff --git a/MethodologyMain.Application/Services/TeamValidationService.cs b/MethodologyMain.Application/Services/TeamValidationService.cs index fbdf79b..b92d86d 100644 --- a/MethodologyMain.Application/Services/TeamValidationService.cs +++ b/MethodologyMain.Application/Services/TeamValidationService.cs @@ -4,7 +4,7 @@ namespace MethodologyMain.Application.Services { - class TeamValidationService : ITeamValidationService + public class TeamValidationService : ITeamValidationService { public readonly ITeamRepository teamRepo; public TeamValidationService(ITeamRepository teamRepo) diff --git a/MethodologyMain.Persistence/Repository/TeamRepository.cs b/MethodologyMain.Persistence/Repository/TeamRepository.cs index ba6ccf9..0ea85d4 100644 --- a/MethodologyMain.Persistence/Repository/TeamRepository.cs +++ b/MethodologyMain.Persistence/Repository/TeamRepository.cs @@ -10,27 +10,6 @@ public class TeamRepository : GenericRepository, ITeamRepository public TeamRepository(MyDbContext context) : base(context) { } - private static void CheckCancellation(CancellationToken token) - { - token.ThrowIfCancellationRequested(); - } - private async Task GetTeamNoTrackingAsync(Guid teamId, CancellationToken token) - { - CheckCancellation(token); - return await _context.Teams - .AsNoTracking() - .FirstAsync(e => e.Id == teamId, token); - } - private async Task GetTeamAsync(Guid teamId, CancellationToken token) - { - CheckCancellation(token); - return await _context.Teams.FindAsync([teamId], token); - } - private async Task SaveChangesAsync(CancellationToken token) - { - CheckCancellation(token); - await _context.SaveChangesAsync(token); - } public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token) { CheckCancellation(token); @@ -96,5 +75,26 @@ public async Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, Cancellat var team = await GetTeamAsync(teamId, token); return team.Members.Select(m => m.UserId).ToList(); } + private static void CheckCancellation(CancellationToken token) + { + token.ThrowIfCancellationRequested(); + } + private async Task GetTeamNoTrackingAsync(Guid teamId, CancellationToken token) + { + CheckCancellation(token); + return await _context.Teams + .AsNoTracking() + .FirstAsync(e => e.Id == teamId, token); + } + private async Task GetTeamAsync(Guid teamId, CancellationToken token) + { + CheckCancellation(token); + return await _context.Teams.FindAsync([teamId], token); + } + private async Task SaveChangesAsync(CancellationToken token) + { + CheckCancellation(token); + await _context.SaveChangesAsync(token); + } } } \ No newline at end of file From 87a1d0823cf9abad1c21f73f09107abb98fe1ed5 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Tue, 22 Apr 2025 02:08:13 +0300 Subject: [PATCH 19/52] Add User Repository --- .../Interfaces/IUserRepository.cs | 13 ++++++++++++ .../Repository/UserRepository.cs | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 MethodologyMain.Persistence/Interfaces/IUserRepository.cs create mode 100644 MethodologyMain.Persistence/Repository/UserRepository.cs diff --git a/MethodologyMain.Persistence/Interfaces/IUserRepository.cs b/MethodologyMain.Persistence/Interfaces/IUserRepository.cs new file mode 100644 index 0000000..a53ee09 --- /dev/null +++ b/MethodologyMain.Persistence/Interfaces/IUserRepository.cs @@ -0,0 +1,13 @@ +using MethodologyMain.Logic.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Persistence.Interfaces +{ + public interface IUserRepository : IGenericRepository + { + } +} diff --git a/MethodologyMain.Persistence/Repository/UserRepository.cs b/MethodologyMain.Persistence/Repository/UserRepository.cs new file mode 100644 index 0000000..fa50e3e --- /dev/null +++ b/MethodologyMain.Persistence/Repository/UserRepository.cs @@ -0,0 +1,20 @@ +using MethodologyMain.Logic.Entities; +using MethodologyMain.Logic.Models; +using MethodTeams.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Persistence.Repository +{ + public class UserRepository: GenericRepository + { + public UserRepository(MyDbContext context) : base(context) + { + } + + + } +} From f0cc4f0afc04901961a9955a20972e3700c04e08 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Wed, 23 Apr 2025 13:02:50 +0300 Subject: [PATCH 20/52] Remove await log from Team Controller --- .../Controllers/TeamController.cs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index cb6e247..53e7548 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -1,8 +1,8 @@ using MethodologyMain.Application.DTO; using MethodTeams.Models; -using Microsoft.AspNetCore.Authorization; +//using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using System.Security.Claims; +//using System.Security.Claims; using MethodologyMain.Application.Interface; using AuthMetodology.Infrastructure.Interfaces; using AuthMetodology.Infrastructure.Models; @@ -26,7 +26,7 @@ public TeamController(ITeamService teamService, ILogQueueService logQueueService //[Authorize] public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, @@ -50,7 +50,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish [HttpGet("{id}")] public async Task> GetTeam(Guid id, CancellationToken token) { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, @@ -74,7 +74,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish //[Authorize] public async Task DeleteTeam(Guid id, CancellationToken token) { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, @@ -101,11 +101,11 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish } // Добавление пользователя в команду - [HttpPost("{id}/members")] + [HttpPost("{id}/users")] //[Authorize] public async Task AddMember(Guid id, [FromBody] AddUserDto dto, CancellationToken token) { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, @@ -134,11 +134,11 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish } // Удаление пользователя из команды - [HttpDelete("{id}/members/{userId}")] + [HttpDelete("{id}/users/{userId}")] //[Authorize] public async Task RemoveMember(Guid id, Guid userId, CancellationToken token) { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, @@ -167,10 +167,10 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish } // Получение списка участников команды - [HttpGet("{id}/members")] + [HttpGet("{id}/users")] public async Task>> GetTeamMembers(Guid id, CancellationToken token) { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, @@ -194,7 +194,7 @@ await logQueueService.SendLogEventAsync(new RabbitMqLogPublish //[Authorize] public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto, CancellationToken token) { - await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, @@ -290,14 +290,14 @@ public async Task>> GetTeamsAll(CancellationToken token) // return Ok(team); - //try - //{ - - //} - //catch (Exception ex) - //{ - // return BadRequest(ex.Message); - //} + //try + //{ + + //} + //catch (Exception ex) + //{ + // return BadRequest(ex.Message); + //} //} // Вспомогательный метод для получения ID текущего пользователя From d8eb8a2d39447d318c0ace1340a21ce49d968ddb Mon Sep 17 00:00:00 2001 From: wer3454 Date: Wed, 23 Apr 2025 13:05:10 +0300 Subject: [PATCH 21/52] Fix exception throw --- MethodologyMain.API/Middleware/ExceptionMiddleware.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs index 21b5c2e..e17cdc9 100644 --- a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs +++ b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs @@ -1,6 +1,7 @@ using AuthMetodology.Infrastructure.Interfaces; using MethodologyMain.Application.Exceptions; using Serilog.Events; +using System.Threading.Tasks; namespace MethodologyMain.API.Middleware { @@ -22,7 +23,7 @@ public async Task InvokeAsync(HttpContext context) } catch (Exception ex) { - await logQueueService.SendLogEventAsync(new AuthMetodology.Infrastructure.Models.RabbitMqLogPublish { + _ = logQueueService.SendLogEventAsync(new AuthMetodology.Infrastructure.Models.RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Error, Message = $"Exception was thrown.\nMessage: {ex.Message}\nSource: {ex.Source}", @@ -32,7 +33,7 @@ await logQueueService.SendLogEventAsync(new AuthMetodology.Infrastructure.Models } } - private static void HandleException(Exception ex, HttpContext context) + private static async Task HandleException(Exception ex, HttpContext context) { ExceptionResponse response = ex switch { @@ -42,8 +43,12 @@ private static void HandleException(Exception ex, HttpContext context) InvalidOperationException _ => new ExceptionResponse(ex.Message, System.Net.HttpStatusCode.Conflict), UserNotFoundException _ => new ExceptionResponse("Пользователь не найден", System.Net.HttpStatusCode.Conflict), UserNotInTeamException _ => new ExceptionResponse("Пользователь не в команде", System.Net.HttpStatusCode.Conflict), - _ => throw new NotImplementedException(), + _ => new ExceptionResponse(ex.Message, System.Net.HttpStatusCode.InternalServerError), }; + + context.Response.ContentType = "application/json"; + context.Response.StatusCode = (int)response.Code; + await context.Response.WriteAsJsonAsync(response); } } } From a85908f176df5cc4c83402b0af4bcb75fb6112e6 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Wed, 23 Apr 2025 13:05:24 +0300 Subject: [PATCH 22/52] Add automapper config --- MethodologyMain.API/Program.cs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index e596012..fe31320 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -1,5 +1,6 @@ using MethodTeams.Data; using MethodTeams.Services; +using AutoMapper; using System.Text.Json.Serialization; using MethodologyMain.Application.Interface; using MethodologyMain.Application.Services; @@ -9,6 +10,10 @@ using MethodologyMain.Infrastructure.Services; using MethodologyMain.Persistence.Interfaces; using MethodologyMain.Persistence.Repository; +using MethodTeams.DTO; +using System.Reflection; +using MethodologyMain.Application.Profiles; +using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); @@ -22,14 +27,24 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +var configuration = new MapperConfiguration(static cfg => +{ + cfg.AddMaps(Assembly.GetExecutingAssembly()); + cfg.AllowNullCollections = true; + cfg.AddGlobalIgnore("Item"); +} +); + builder.Services.Configure(builder.Configuration.GetSection(nameof(RabbitMqOptions))); builder.Services.AddScoped(); +builder.Services.AddAutoMapper(typeof(TeamProfile).Assembly, typeof(TeamInfoDto).Assembly); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); -builder.Services.AddDbContext(); +var connection = builder.Configuration.GetConnectionString("PostgresConnection"); +builder.Services.AddDbContext(opt => opt.UseNpgsql(connection)); var app = builder.Build(); @@ -41,7 +56,8 @@ app.UseHttpsRedirection(); -app.UseAuthorization(); +//app.UseAuthorization(); +//app.UseAuthentication(); app.MapControllers(); From d7be632f7b7c37f1e7ad5fd3b388e64454bb8236 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Wed, 23 Apr 2025 13:07:57 +0300 Subject: [PATCH 23/52] Fix project --- MethodologyMain.API/MethodologyMain.API.csproj | 7 ++++--- .../Properties/serviceDependencies.json | 11 ++++++++++- .../MethodologyMain.Application.csproj | 2 +- .../MethodologyMain.Infrastructure.csproj | 7 ++++++- MethodologyMain.Logic/MethodologyMain.Logic.csproj | 2 +- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.API/MethodologyMain.API.csproj b/MethodologyMain.API/MethodologyMain.API.csproj index 2134571..6a2ed1f 100644 --- a/MethodologyMain.API/MethodologyMain.API.csproj +++ b/MethodologyMain.API/MethodologyMain.API.csproj @@ -6,17 +6,18 @@ enable 1fe97921-83f1-4b1c-8a25-61646ab7998e Linux + ..\docker-compose.dcproj - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/MethodologyMain.API/Properties/serviceDependencies.json b/MethodologyMain.API/Properties/serviceDependencies.json index 33703d5..5cee86d 100644 --- a/MethodologyMain.API/Properties/serviceDependencies.json +++ b/MethodologyMain.API/Properties/serviceDependencies.json @@ -1,3 +1,12 @@ { - "dependencies": {} + "dependencies": { + "rabbitmq1": { + "type": "rabbitmq", + "connectionId": "QueueConnection" + }, + "postgresql1": { + "type": "postgresql", + "connectionId": "ConnectionStrings:DatabaseConnection" + } + } } \ No newline at end of file diff --git a/MethodologyMain.Application/MethodologyMain.Application.csproj b/MethodologyMain.Application/MethodologyMain.Application.csproj index cd6da6a..4669d23 100644 --- a/MethodologyMain.Application/MethodologyMain.Application.csproj +++ b/MethodologyMain.Application/MethodologyMain.Application.csproj @@ -1,7 +1,7 @@  - Exe + Library net8.0 enable enable diff --git a/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj b/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj index a4a798b..2158186 100644 --- a/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj +++ b/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj @@ -1,7 +1,7 @@  - Exe + Library net8.0 enable enable @@ -13,4 +13,9 @@ + + + + + diff --git a/MethodologyMain.Logic/MethodologyMain.Logic.csproj b/MethodologyMain.Logic/MethodologyMain.Logic.csproj index 2150e37..412d83d 100644 --- a/MethodologyMain.Logic/MethodologyMain.Logic.csproj +++ b/MethodologyMain.Logic/MethodologyMain.Logic.csproj @@ -1,7 +1,7 @@  - Exe + Library net8.0 enable enable From ae78bd7765de504b484274206abfaaa9a1982acf Mon Sep 17 00:00:00 2001 From: wer3454 Date: Wed, 23 Apr 2025 13:09:21 +0300 Subject: [PATCH 24/52] Fix project --- .../MethodologyMain.Persistence.csproj | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj b/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj index 86db8d8..0dbfb18 100644 --- a/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj +++ b/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj @@ -1,18 +1,27 @@  - Exe + Library net8.0 enable enable - + - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + From 58f370dd6c4c011bfe1795c0a5c57880a6878987 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 15:54:36 +0300 Subject: [PATCH 25/52] Add new endpoint to test logging Signed-off-by: BelugaChan --- .../Controllers/TeamController.cs | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 53e7548..b5ef54e 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -4,9 +4,10 @@ using Microsoft.AspNetCore.Mvc; //using System.Security.Claims; using MethodologyMain.Application.Interface; -using AuthMetodology.Infrastructure.Interfaces; using AuthMetodology.Infrastructure.Models; using Serilog.Events; +using RabbitMqPublisher.Interface; +using Newtonsoft.Json.Linq; namespace MethodologyMain.API.Controllers { [ApiController] @@ -14,11 +15,26 @@ namespace MethodologyMain.API.Controllers public class TeamController : ControllerBase { private readonly ITeamService teamService; - private readonly ILogQueueService logQueueService; - public TeamController(ITeamService teamService, ILogQueueService logQueueService) + private readonly IRabbitMqPublisherBase logPublishService; + public TeamController(ITeamService teamService, IRabbitMqPublisherBase logPublishService) { this.teamService = teamService; - this.logQueueService = logQueueService; + this.logPublishService = logPublishService; + } + + //Тестовый эндпоинт + [HttpGet("dummy-data")] + public async Task GetDummyData(CancellationToken cancellationToken) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "POST api/Team/dummy-data was called", + TimeStamp = DateTime.UtcNow + }, cancellationToken); + string data = "Dataaa"; + return Ok(data); } // Создание команды @@ -26,13 +42,13 @@ public TeamController(ITeamService teamService, ILogQueueService logQueueService //[Authorize] public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "POST api/Team was called", TimeStamp = DateTime.UtcNow - }); + }, token); Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); return CreatedAtAction(nameof(GetTeam), new { id = team.Id }, team); @@ -50,13 +66,13 @@ public async Task> CreateTeam([FromBody] CreateTeamDto dto, C [HttpGet("{id}")] public async Task> GetTeam(Guid id, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "GET api/Team/id was called", TimeStamp = DateTime.UtcNow - }); + }, token); var team = await teamService.GetTeamByIdAsync(id, token); return Ok(team); //try @@ -74,13 +90,13 @@ public async Task> GetTeam(Guid id, CancellationToken token) //[Authorize] public async Task DeleteTeam(Guid id, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "DELETE api/Team/id was called", TimeStamp = DateTime.UtcNow - }); + }, token); Guid currentUserId = GetCurrentUserId(); bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора @@ -105,13 +121,13 @@ public async Task DeleteTeam(Guid id, CancellationToken token) //[Authorize] public async Task AddMember(Guid id, [FromBody] AddUserDto dto, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "POST api/Team/id/members was called", TimeStamp = DateTime.UtcNow - }); + }, token); Guid currentUserId = GetCurrentUserId(); await teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId, token); return NoContent(); @@ -138,13 +154,13 @@ public async Task AddMember(Guid id, [FromBody] AddUserDto dto, Ca //[Authorize] public async Task RemoveMember(Guid id, Guid userId, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "DELETE api/Team/id/members/userId was called", TimeStamp = DateTime.UtcNow - }); + }, token); Guid currentUserId = GetCurrentUserId(); await teamService.RemoveUserFromTeamAsync(id, userId, currentUserId, token); return NoContent(); @@ -170,13 +186,13 @@ public async Task RemoveMember(Guid id, Guid userId, CancellationT [HttpGet("{id}/users")] public async Task>> GetTeamMembers(Guid id, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "GET api/Team/id/members was called", TimeStamp = DateTime.UtcNow - }); + }, token); var members = await teamService.GetTeamMembersAsync(id, token); return Ok(members); //try @@ -194,13 +210,13 @@ public async Task>> GetTeamMembers(Guid id, CancellationT //[Authorize] public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "PUT api/Team/id/captain was called", TimeStamp = DateTime.UtcNow - }); + }, token); Guid currentUserId = GetCurrentUserId(); await teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId, token); return NoContent(); @@ -226,13 +242,13 @@ public async Task TransferCaptainRights(Guid id, [FromBody] AddUse [HttpGet] public async Task>> GetTeamsAll(CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, Message = "GET api/Team was called", TimeStamp = DateTime.UtcNow - }); + }, token); var teams = await teamService.GetTeamAllAsync(token); return Ok(teams); //try From 9fbbbea82aa9dd45cf73c084f9861b8ef46b47ab Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 15:55:57 +0300 Subject: [PATCH 26/52] Create new extension to enable jwt authentication and authorization Signed-off-by: BelugaChan --- .../Extensions/AuthExtensions.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 MethodologyMain.API/Extensions/AuthExtensions.cs diff --git a/MethodologyMain.API/Extensions/AuthExtensions.cs b/MethodologyMain.API/Extensions/AuthExtensions.cs new file mode 100644 index 0000000..c65b833 --- /dev/null +++ b/MethodologyMain.API/Extensions/AuthExtensions.cs @@ -0,0 +1,44 @@ +using MethodologyMain.Infrastructure.Models; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; +using System.Text; + +namespace MethodologyMain.API.Extensions +{ + public static class AuthExtensions + { + public static void AddApiAuthentication( + this IServiceCollection services, + IOptions options) + { + var value = options.Value; + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => + { //будет осуществляться проверка, есть ли в headers токен + options.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuer = false, + ValidateAudience = false, + ValidateLifetime = true, + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey( + Encoding.UTF8.GetBytes(value.SecurityKey)) + }; + + options.Events = new JwtBearerEvents() + { + OnMessageReceived = context => + { + context.Token = context.Request.Cookies["access"]; + + return Task.CompletedTask; + } + }; + }); + services.AddAuthorizationBuilder() + //.AddPolicy("AdminOnly", policy => policy.RequireRole(nameof(UserRole.Admin))) + .AddPolicy("BearerOnly", policy => { policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); policy.RequireAuthenticatedUser(); }); + } + } +} From 1b74f2f7ebec935238826b15c0c413be42d73f3d Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 15:58:24 +0300 Subject: [PATCH 27/52] Add error logging Signed-off-by: BelugaChan --- .../Middleware/ExceptionMiddleware.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs index e17cdc9..b758ea2 100644 --- a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs +++ b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs @@ -1,18 +1,18 @@ -using AuthMetodology.Infrastructure.Interfaces; +using AuthMetodology.Infrastructure.Models; using MethodologyMain.Application.Exceptions; +using RabbitMqPublisher.Interface; using Serilog.Events; -using System.Threading.Tasks; namespace MethodologyMain.API.Middleware { public class ExceptionMiddleware { private readonly RequestDelegate next; - private readonly ILogQueueService logQueueService; - public ExceptionMiddleware(RequestDelegate next, ILogQueueService logQueueService) + private readonly IRabbitMqPublisherBase logService; + public ExceptionMiddleware(RequestDelegate next, IRabbitMqPublisherBase logService) { this.next = next; - this.logQueueService = logQueueService; + this.logService = logService; } public async Task InvokeAsync(HttpContext context) @@ -23,13 +23,15 @@ public async Task InvokeAsync(HttpContext context) } catch (Exception ex) { - _ = logQueueService.SendLogEventAsync(new AuthMetodology.Infrastructure.Models.RabbitMqLogPublish { + _ = logService.SendEventAsync(new RabbitMqLogPublish + { ServiceName = "Main service", LogLevel = LogEventLevel.Error, Message = $"Exception was thrown.\nMessage: {ex.Message}\nSource: {ex.Source}", TimeStamp = DateTime.UtcNow }); - HandleException(ex,context); + + await HandleException(ex,context); } } From ff125337d9c67f34cb4a79e2e27ead8f36a905d8 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 15:59:27 +0300 Subject: [PATCH 28/52] Register new services in DI cotainer and add new auth extension Signed-off-by: BelugaChan --- MethodologyMain.API/Program.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index fe31320..1ae8352 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -5,8 +5,6 @@ using MethodologyMain.Application.Interface; using MethodologyMain.Application.Services; using MethodologyMain.API.Middleware; -using AuthMetodology.Infrastructure.Models; -using AuthMetodology.Infrastructure.Interfaces; using MethodologyMain.Infrastructure.Services; using MethodologyMain.Persistence.Interfaces; using MethodologyMain.Persistence.Repository; @@ -14,9 +12,16 @@ using System.Reflection; using MethodologyMain.Application.Profiles; using Microsoft.EntityFrameworkCore; +using RabbitMqModel.Models; +using RabbitMqPublisher.Interface; +using AuthMetodology.Infrastructure.Models; +using MethodologyMain.Infrastructure.Models; +using MethodologyMain.API.Extensions; +using Microsoft.Extensions.Options; var builder = WebApplication.CreateBuilder(args); +builder.Services.AddApiAuthentication(builder.Services.BuildServiceProvider().GetRequiredService>()); builder.Services.AddControllers(); builder.Services.AddControllers() @@ -34,15 +39,19 @@ cfg.AddGlobalIgnore("Item"); } ); +IMapper mapper = configuration.CreateMapper(); +builder.Services.AddSingleton(mapper); builder.Services.Configure(builder.Configuration.GetSection(nameof(RabbitMqOptions))); +builder.Services.Configure(builder.Configuration.GetSection(nameof(JWTOptions))); + builder.Services.AddScoped(); builder.Services.AddAutoMapper(typeof(TeamProfile).Assembly, typeof(TeamInfoDto).Assembly); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); +builder.Services.AddSingleton, LogQueueService>(); + var connection = builder.Configuration.GetConnectionString("PostgresConnection"); builder.Services.AddDbContext(opt => opt.UseNpgsql(connection)); From 2af3683fe46222c4126a51f823f5cac45a0e9b76 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:11:05 +0300 Subject: [PATCH 29/52] Add project refences and new nuget package with jwtBearer Signed-off-by: BelugaChan --- MethodologyMain.API/MethodologyMain.API.csproj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MethodologyMain.API/MethodologyMain.API.csproj b/MethodologyMain.API/MethodologyMain.API.csproj index 6a2ed1f..082b760 100644 --- a/MethodologyMain.API/MethodologyMain.API.csproj +++ b/MethodologyMain.API/MethodologyMain.API.csproj @@ -10,6 +10,7 @@ + all @@ -29,4 +30,13 @@ + + + ..\MethodologyMain.Infrastructure\DLL\RabbitMqModel.dll + + + ..\MethodologyMain.Infrastructure\DLL\RabbitMqPublisher.dll + + + From dd50c1084883620906fb83b3eb1e1436e2c57d3d Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:13:35 +0300 Subject: [PATCH 30/52] Add new dlls Signed-off-by: BelugaChan --- .../MethodologyMain.Infrastructure.csproj | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj b/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj index 2158186..78f38d2 100644 --- a/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj +++ b/MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj @@ -8,14 +8,33 @@ + + + + + + + + + + DLL\RabbitMqListener.dll + + + DLL\RabbitMqModel.dll + + + DLL\RabbitMqPublisher.dll + + + From c41be78c7bfdd1ec6f7e660c7178fbab9ccffe64 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:14:16 +0300 Subject: [PATCH 31/52] Add new RabbitMq custom class libraries Signed-off-by: BelugaChan --- .../DLL/RabbitMqListener.dll | Bin 0 -> 13824 bytes .../DLL/RabbitMqModel.dll | Bin 0 -> 4608 bytes .../DLL/RabbitMqPublisher.dll | Bin 0 -> 10240 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll create mode 100644 MethodologyMain.Infrastructure/DLL/RabbitMqModel.dll create mode 100644 MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll new file mode 100644 index 0000000000000000000000000000000000000000..5578fb2f5626c851da98eb1728be289966da0b94 GIT binary patch literal 13824 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 literal 0 HcmV?d00001 diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqModel.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqModel.dll new file mode 100644 index 0000000000000000000000000000000000000000..851a61874471fbc6915a93a6f5741fd6193752b1 GIT binary patch literal 4608 zcmeHKU2Ggz75-+{yV*F6>$FW3S`;R6N}W<|?Iw+q;yC_UyEgcbUFQd|YR~RoZzh@D z+04v3S(Q-pQz+sg2o#ATA&k@qkb;zlK2%76cqvFILaIOr35hz6iyIS=^tDr2uUbUR6m7UL96|bZ+yLWdVid`>E05e7cs}sMt z-JI<$9JF>B13)(=sYv?y!+cuoBkVx0rp+jB5lH;HtrIDimcYtOVk&>FXUvL-?J4@5 z7h(j+N+Gtk72rO~mimFkt-5>h7Lab!r^!#X@tIIv3CX{_lR%x$HIAE{ZWgeT@dLj| zPRBMvLK2mL+S&-C&-lvqXsA^yREjU1H=l7E0mhni^I4R-vPoE1F^_*Z%8@%PUkU2TGH)%?(}q)&vWEoW&nL-u2�jjoKddp8Uz zIsRcB!NXCWdn27LSu&;>A|7FvI&hqxM`-Cl$&8*U{J{90nZiC(@SC`9-jAQtJO$Gj zqU4TomH52IM>QVTcuV7NA=>NO!yh!>fcUwp>D%U-&{{G<&nf&^B{Dv;hlGk?O|NSg^$MOX5%g5W8`h*o#4pCp3;~oYwdWji1zL6Ad`Ty||>YK}_K*8ebtk zg6|S7e4p5h&uO`Z7w|_Mi17=!U_6db<3-~z0?ISkg$d$=m?J)l3b7As#E;-L;t~9e z_))w`9LMj8AJ_6caYXwZjZr+0qlkcb5e=gFpVqjdZPqnz;H!8S8~6rJ8zyT4988=f z_9jMIIfM0*3MO<SE{>e7()x59}Zt!ULLcH z7rFH(9p#oVH01@`rTIn>s!AqTuZB)VA*%}Ya#{IfzIQpW3$DtCcBnA!Rcel_{7Gep zbzkMwrMly*(rCz|Rj9WaJg2J4=ZH2{|KfHJlg#0a@&m`KZdXoMS3SRChg90`U9HBw>Z((&Gsg}m z&5F!2QsuXt=hSN6UR7Zu$CU|M@~EKNNlv-;6-~A2n>jD|T+?FM8rZBH`(SN@t)R6)E2Ik!w1Y?)Gr(Gt$rWUc`7g$tY( zT>WL)`v{tZNMzq@i6-=E>3Z|}#(U5AO}sk1(fzBxUwa2#mSLn57K|i`J$r=h5lCu& zI%%0kkD0!CYWc-IzwUn4O!b&4G4EkdC;Iv9M>=i9Cv(5NS{KcS&-!+4&Z|ybDJmW3 z;(0k$2JLp}m+(mg`!aJAi{qZJMr*YvAw+FNzGOdC0*1o#%qzU?v~6 zq!bB6HVSveV&L}gzWrqwvkQFD;T-$Tes;On#Z5-YxAt-NH18tm)=+J+e_SU>sMH()TpLN|?+o_@w z6uCi^K5klj=P^3jn&x(o{}YMaA%K0rdgpX{b-}&2O)hqFcRV)&ye*3yx3|rsq|P9Z zW#R;Kq^5b(o+Cd^oQ!VW_)*up??qolSw(5l^Hjv>dsmxVEtUJ7L9aG^`f+$qRPKjmePQ?4T+)F5#zml4DiilY{q+r zK74v<!IaauOF0-?^%Q~yu8Y4A+A2ciapYeHq)$ literal 0 HcmV?d00001 diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll new file mode 100644 index 0000000000000000000000000000000000000000..b2d9043e49abe151d96041c227ecc6beca8504aa GIT binary patch literal 10240 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 literal 0 HcmV?d00001 From 6e94400f2d6e4a9ce9ec29a9d985200d32a9e70e Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:14:49 +0300 Subject: [PATCH 32/52] Create new register user listener Signed-off-by: BelugaChan --- .../Listeners/RabbitMqUserRegisterListener.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs diff --git a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs new file mode 100644 index 0000000..d99496d --- /dev/null +++ b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs @@ -0,0 +1,28 @@ +using MethodologyMain.Infrastructure.Models; +using MethodologyMain.Logic.Entities; +using MethodologyMain.Persistence.Interfaces; +using Microsoft.Extensions.Options; +using RabbitMqListener.Abstract; +using RabbitMqModel.Models; + +namespace MethodologyMain.Infrastructure.Listeners +{ + public class RabbitMqUserRegisterListener : RabbitMqListenerBase + { + private readonly IUserRepository userRepository; + public RabbitMqUserRegisterListener(IUserRepository userRepository, IOptions options) : base(options) + { + this.userRepository = userRepository; + } + + protected override string QueueName => "RegisterUserQueue"; + + public override async Task ProcessMessageAsync(RabbitMqUserRegisterRecieve message) + { + await userRepository.AddAsync(new UserMainEntity + { + Id = message.UserId + }); + } + } +} From 998d1d94533aaba2e33ac5cc25d7ac3e56fa068e Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:15:27 +0300 Subject: [PATCH 33/52] Create new model to configure JWT Signed-off-by: BelugaChan --- MethodologyMain.Infrastructure/Models/JWTOptions.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 MethodologyMain.Infrastructure/Models/JWTOptions.cs diff --git a/MethodologyMain.Infrastructure/Models/JWTOptions.cs b/MethodologyMain.Infrastructure/Models/JWTOptions.cs new file mode 100644 index 0000000..42e3f01 --- /dev/null +++ b/MethodologyMain.Infrastructure/Models/JWTOptions.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Infrastructure.Models +{ + public class JWTOptions + { + public string SecurityKey { get; set; } + } +} From f0b7a364842c48673c0170a3e737b950687b3fd6 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:16:12 +0300 Subject: [PATCH 34/52] Create new model to configure user creation events in rabbitMq Signed-off-by: BelugaChan --- .../Models/RabbitMqUserRegisterRecieve.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs new file mode 100644 index 0000000..b9c9669 --- /dev/null +++ b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Infrastructure.Models +{ + public class RabbitMqUserRegisterRecieve + { + public Guid UserId { get; set; } + } +} From bf971af12bcea9fb16c7128f9f4fc4148c7a78c7 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:16:44 +0300 Subject: [PATCH 35/52] Rework log service Signed-off-by: BelugaChan --- .../Services/LogQueueService.cs | 18 +++-- .../Services/RabbitMqService.cs | 76 ------------------- 2 files changed, 10 insertions(+), 84 deletions(-) delete mode 100644 MethodologyMain.Infrastructure/Services/RabbitMqService.cs diff --git a/MethodologyMain.Infrastructure/Services/LogQueueService.cs b/MethodologyMain.Infrastructure/Services/LogQueueService.cs index 8b2c34d..16f77f5 100644 --- a/MethodologyMain.Infrastructure/Services/LogQueueService.cs +++ b/MethodologyMain.Infrastructure/Services/LogQueueService.cs @@ -1,17 +1,19 @@ -using AuthMetodology.Infrastructure.Interfaces; -using AuthMetodology.Infrastructure.Models; +using AuthMetodology.Infrastructure.Models; +using Microsoft.Extensions.Options; +using RabbitMqModel.Models; +using RabbitMqPublisher.Abstract; namespace MethodologyMain.Infrastructure.Services { - public class LogQueueService : ILogQueueService + public class LogQueueService : RabbitMqPublisherBase { - private readonly IRabbitMqService rabbitMqService; - private readonly string QueueName = "LogQueue"; - public LogQueueService(IRabbitMqService rabbitMqService) => this.rabbitMqService = rabbitMqService; + public LogQueueService(IOptions options) : base(options) { } - public async Task SendLogEventAsync(RabbitMqLogPublish message) + public override string QueueName => "LogQueue"; + + public override async Task SendEventAsync(RabbitMqLogPublish message, CancellationToken cancellationToken = default) { - await rabbitMqService.SendMessageAsync(message, QueueName); + await SendMessageAsync(message, QueueName, cancellationToken); } } } diff --git a/MethodologyMain.Infrastructure/Services/RabbitMqService.cs b/MethodologyMain.Infrastructure/Services/RabbitMqService.cs deleted file mode 100644 index eb18e5b..0000000 --- a/MethodologyMain.Infrastructure/Services/RabbitMqService.cs +++ /dev/null @@ -1,76 +0,0 @@ -using AuthMetodology.Infrastructure.Interfaces; -using AuthMetodology.Infrastructure.Models; -using Microsoft.Extensions.Options; -using RabbitMQ.Client; -using System.Text.Json; - -namespace MethodologyMain.Infrastructure.Services -{ - public class RabbitMqService : IRabbitMqService, IAsyncDisposable - { - private IConnection? connection; - private bool disposed; - private SemaphoreSlim connectionLock = new SemaphoreSlim(1,1); - private readonly RabbitMqOptions options; - public RabbitMqService(IOptions options) - { - this.options = options.Value; - } - public async ValueTask DisposeAsync() - { - if (disposed) - return; - - disposed = true; - if (connection?.IsOpen == true) - { - await connection.CloseAsync(); - } - connection?.Dispose(); - connectionLock.Dispose(); - GC.SuppressFinalize(this); - } - - private async Task GetConnectionAsync() - { - await connectionLock.WaitAsync(); - try - { - if (connection?.IsOpen == true) return connection; - - connection?.Dispose(); - var factory = new ConnectionFactory() - { - HostName = options.Host, - Port = options.Port - }; - connection = await factory.CreateConnectionAsync(); - return connection; - } - finally - { - connectionLock.Release(); - } - } - - public async Task SendMessageAsync(T message, string queueName) where T : class - { - connection = await GetConnectionAsync(); - - using (var channel = await connection.CreateChannelAsync()) - { - await channel.QueueDeclareAsync( - queue: queueName, - durable: false, - exclusive: false, - autoDelete: false, - arguments: null - ); - - var messageBody = JsonSerializer.SerializeToUtf8Bytes(message); - - await channel.BasicPublishAsync(exchange: "", routingKey: queueName, messageBody); - }; - } - } -} From 63a01b219664163dbcec689c054dfa8fcdc2448e Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:17:43 +0300 Subject: [PATCH 36/52] Add default value for user's birth date Signed-off-by: BelugaChan --- MethodologyMain.Logic/Entities/UserMainEntity.cs | 2 +- MethodologyMain.Logic/Models/UserMain.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.Logic/Entities/UserMainEntity.cs b/MethodologyMain.Logic/Entities/UserMainEntity.cs index 5a06803..10d3b2e 100644 --- a/MethodologyMain.Logic/Entities/UserMainEntity.cs +++ b/MethodologyMain.Logic/Entities/UserMainEntity.cs @@ -10,7 +10,7 @@ public class UserMainEntity [Column("id")] public required Guid Id { get; set; } [Column("birthDate")] - public DateTime BirthDate { get; set; } + public DateTime BirthDate { get; set; } = DateTime.MinValue; [Column("education")] public string Education { get; set; } = string.Empty; [Column("firstName")] diff --git a/MethodologyMain.Logic/Models/UserMain.cs b/MethodologyMain.Logic/Models/UserMain.cs index 7982adc..3ba043f 100644 --- a/MethodologyMain.Logic/Models/UserMain.cs +++ b/MethodologyMain.Logic/Models/UserMain.cs @@ -13,7 +13,7 @@ namespace MethodologyMain.Logic.Models public class UserMain { public required Guid Id { get; set; } - public DateTime BirthDate { get; set; } + public DateTime BirthDate { get; set; } = DateTime.MinValue; public string Education { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; From 8463b4655baa5e583d961c311e0adcac484004f0 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:18:37 +0300 Subject: [PATCH 37/52] Change cancellation token requirements to optional Signed-off-by: BelugaChan --- .../Interfaces/IGenericRepository.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs b/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs index d6afcd6..22d0c63 100644 --- a/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs @@ -4,12 +4,12 @@ namespace MethodologyMain.Persistence.Interfaces { public interface IGenericRepository where T : class { - Task AddAsync(T entity, CancellationToken token); - Task AddRangeAsync(IEnumerable entities, CancellationToken token); - Task> FindAsync(Expression> expression, CancellationToken token); - Task> GetAllAsync(CancellationToken token); - Task GetByIdAsync(Guid id, CancellationToken token); - Task RemoveAsync(T entity, CancellationToken token); - Task RemoveRangeAsync(IEnumerable entities, CancellationToken token); + Task AddAsync(T entity, CancellationToken token = default); + Task AddRangeAsync(IEnumerable entities, CancellationToken token = default); + Task> FindAsync(Expression> expression, CancellationToken token = default); + Task> GetAllAsync(CancellationToken token = default); + Task GetByIdAsync(Guid id, CancellationToken token = default); + Task RemoveAsync(T entity, CancellationToken token = default); + Task RemoveRangeAsync(IEnumerable entities, CancellationToken token = default); } } From 33a4219faea742704352e9b37e441f66285e9bb7 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:20:13 +0300 Subject: [PATCH 38/52] Removed old realizations --- .../Interfaces/ILogQueueService.cs | 9 --------- .../Interfaces/IRabbitMqService.cs | 10 ---------- .../Models/RabbitMqOptions.cs | 8 -------- 3 files changed, 27 deletions(-) delete mode 100644 MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs delete mode 100644 MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs delete mode 100644 MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs diff --git a/MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs b/MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs deleted file mode 100644 index 8a901fc..0000000 --- a/MethodologyMain.Infrastructure/Interfaces/ILogQueueService.cs +++ /dev/null @@ -1,9 +0,0 @@ -using AuthMetodology.Infrastructure.Models; - -namespace AuthMetodology.Infrastructure.Interfaces -{ - public interface ILogQueueService - { - Task SendLogEventAsync(RabbitMqLogPublish message); - } -} diff --git a/MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs b/MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs deleted file mode 100644 index e2c6c27..0000000 --- a/MethodologyMain.Infrastructure/Interfaces/IRabbitMqService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using RabbitMQ.Client; - -namespace AuthMetodology.Infrastructure.Interfaces; - -public interface IRabbitMqService -{ - //Task GetConnectionAsync(); - Task SendMessageAsync(T message, string queueName) - where T : class; -} \ No newline at end of file diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs b/MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs deleted file mode 100644 index 0a4ec48..0000000 --- a/MethodologyMain.Infrastructure/Models/RabbitMqOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace AuthMetodology.Infrastructure.Models; - -public class RabbitMqOptions -{ - public string Host { get; set; } = string.Empty; - - public int Port { get; set; } -} \ No newline at end of file From 86da948b0f6b749a72f62269e9e15459959b5ed2 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 23 Apr 2025 16:23:28 +0300 Subject: [PATCH 39/52] Minor fixes --- MethodologyMain.sln | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 MethodologyMain.sln diff --git a/MethodologyMain.sln b/MethodologyMain.sln new file mode 100644 index 0000000..f45ff41 --- /dev/null +++ b/MethodologyMain.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MethodologyMain.Persistence", "MethodologyMain.Persistence\MethodologyMain.Persistence.csproj", "{1FC82515-12C6-4FEE-BBD1-7B8F8556FFCC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MethodologyMain.Application", "MethodologyMain.Application\MethodologyMain.Application.csproj", "{690F1F05-174F-4BB9-97DF-9B6BB9109AA7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MethodologyMain.Logic", "MethodologyMain.Logic\MethodologyMain.Logic.csproj", "{72684002-8EB1-4F55-92ED-B255F3632320}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MethodologyMain.Infrastructure", "MethodologyMain.Infrastructure\MethodologyMain.Infrastructure.csproj", "{BAB29F8B-543F-4F66-9D4C-3438ACCBEBEE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MethodologyMain.API", "MethodologyMain.API\MethodologyMain.API.csproj", "{9617192C-0310-6F26-DC5C-04497DB93B87}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1FC82515-12C6-4FEE-BBD1-7B8F8556FFCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FC82515-12C6-4FEE-BBD1-7B8F8556FFCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FC82515-12C6-4FEE-BBD1-7B8F8556FFCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FC82515-12C6-4FEE-BBD1-7B8F8556FFCC}.Release|Any CPU.Build.0 = Release|Any CPU + {690F1F05-174F-4BB9-97DF-9B6BB9109AA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {690F1F05-174F-4BB9-97DF-9B6BB9109AA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {690F1F05-174F-4BB9-97DF-9B6BB9109AA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {690F1F05-174F-4BB9-97DF-9B6BB9109AA7}.Release|Any CPU.Build.0 = Release|Any CPU + {72684002-8EB1-4F55-92ED-B255F3632320}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72684002-8EB1-4F55-92ED-B255F3632320}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72684002-8EB1-4F55-92ED-B255F3632320}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72684002-8EB1-4F55-92ED-B255F3632320}.Release|Any CPU.Build.0 = Release|Any CPU + {BAB29F8B-543F-4F66-9D4C-3438ACCBEBEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAB29F8B-543F-4F66-9D4C-3438ACCBEBEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAB29F8B-543F-4F66-9D4C-3438ACCBEBEE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAB29F8B-543F-4F66-9D4C-3438ACCBEBEE}.Release|Any CPU.Build.0 = Release|Any CPU + {9617192C-0310-6F26-DC5C-04497DB93B87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9617192C-0310-6F26-DC5C-04497DB93B87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9617192C-0310-6F26-DC5C-04497DB93B87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9617192C-0310-6F26-DC5C-04497DB93B87}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A05B680E-2581-4C1F-B1A8-71A587C941CF} + EndGlobalSection +EndGlobal From 177b5867d095b0af1f72a79f25951f30358bbeb3 Mon Sep 17 00:00:00 2001 From: wer3454 <50406606+wer3454@users.noreply.github.com> Date: Sun, 27 Apr 2025 18:17:48 +0300 Subject: [PATCH 40/52] Update dotnet-desktop.yml --- .github/workflows/dotnet-desktop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index 9a1a036..ad21d28 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -7,7 +7,7 @@ on: jobs: build: - runs-on: shimmer-jaspilite + runs-on: self-hosted steps: - name: Checkout code uses: actions/checkout@v2 From f610f439bd7f27de3add712d52ead9ba1a30486b Mon Sep 17 00:00:00 2001 From: wer3454 <50406606+wer3454@users.noreply.github.com> Date: Sun, 27 Apr 2025 18:41:52 +0300 Subject: [PATCH 41/52] Update dotnet-desktop.yml --- .github/workflows/dotnet-desktop.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index ad21d28..eca883b 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -4,6 +4,8 @@ on: pull_request: branches: [main] workflow_dispatch: +env: + DOTNET_INSTALL_DIR: "./.dotnet" jobs: build: @@ -19,14 +21,14 @@ jobs: # - name: Generate appsettings.json # run: | - # (Get-Content ./AuthMetodology/appsettings.Template.json) -replace '#{POSTGRES_CONNECTION_STRING}#', '${{ secrets.POSTGRES_CONNECTION_STRING }}' -replace '#{GOOGLE_CLIENT_ID}#', '${{ secrets.GOOGLE_CLIENT_ID }}' -replace '#{JWT_SECRET_KEY}#', '${{ secrets.JWT_SECRET_KEY }}' | Set-Content ./AuthMetodology/appsettings.json + # (Get-Content ./MeethodologyMain.API/appsettings.Template.json) -replace '#{POSTGRES_CONNECTION_STRING}#', '${{ secrets.POSTGRES_CONNECTION_STRING }}' -replace '#{GOOGLE_CLIENT_ID}#', '${{ secrets.GOOGLE_CLIENT_ID }}' -replace '#{JWT_SECRET_KEY}#', '${{ secrets.JWT_SECRET_KEY }}' | Set-Content ./AuthMetodology/appsettings.json # shell: pwsh - name: Restore dependencies - run: dotnet restore --verbosity quiet + run: dotnet restore --verbosity quiet ./MethodologyMain.sln - name: Build without warnings - run: dotnet build --configuration Release --no-restore + run: dotnet build --configuration Release --no-restore ./MethodologyMain.sln # - name: Run tests # run: dotnet test --verbosity normal From 662144565f0749dc6291d5f32675ea1d3ed75a8e Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:29:17 +0300 Subject: [PATCH 42/52] Comment launchBrowzer flag Signed-off-by: BelugaChan --- MethodologyMain.API/Properties/launchSettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MethodologyMain.API/Properties/launchSettings.json b/MethodologyMain.API/Properties/launchSettings.json index 5705205..3f97ff6 100644 --- a/MethodologyMain.API/Properties/launchSettings.json +++ b/MethodologyMain.API/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "http": { "commandName": "Project", - "launchBrowser": true, + //"launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" From 53402a1d7acccde3d2831a6bdf55ed8de281dedc Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:29:48 +0300 Subject: [PATCH 43/52] Minor fixes Signed-off-by: BelugaChan --- MethodologyMain.API/Controllers/TeamController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index b5ef54e..9d780da 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -7,7 +7,6 @@ using AuthMetodology.Infrastructure.Models; using Serilog.Events; using RabbitMqPublisher.Interface; -using Newtonsoft.Json.Linq; namespace MethodologyMain.API.Controllers { [ApiController] From 6c2b96ece63dadc91b248be28b9048adb20d5fba Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:34:05 +0300 Subject: [PATCH 44/52] Add option sections for rabbitMq and JWT Signed-off-by: BelugaChan --- MethodologyMain.API/appsettings.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.API/appsettings.json b/MethodologyMain.API/appsettings.json index ca2b892..fdde830 100644 --- a/MethodologyMain.API/appsettings.json +++ b/MethodologyMain.API/appsettings.json @@ -7,12 +7,15 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "PostgresConnection": "Host=localhost;Port=5432;Database=postgres;Username=postgres;Password=Password" + "PostgresConnection": "Host=main_db;Port=5432;Database=maindb;Username=admin;Password=password" }, "RabbitMqOptions": { - "Host": "localhost", + "Host": "rabbitmq", "Port": "5672" }, + "JWTOptions": { + "SecurityKey": "secret" + }, "Serilog": { "Using": [ "Serilog.Sinks.Grafana.Loki" From 14cddfaad038ab816d8180ff82c1c4229e719544 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:34:29 +0300 Subject: [PATCH 45/52] Change dockerfile structure Signed-off-by: BelugaChan --- MethodologyMain.API/Dockerfile | 44 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/MethodologyMain.API/Dockerfile b/MethodologyMain.API/Dockerfile index 12a01a3..c641a52 100644 --- a/MethodologyMain.API/Dockerfile +++ b/MethodologyMain.API/Dockerfile @@ -1,30 +1,28 @@ -# См. статью по ссылке https://aka.ms/customizecontainer, чтобы узнать как настроить контейнер отладки и как Visual Studio использует этот Dockerfile для создания образов для ускорения отладки. +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build -# Этот этап используется при запуске из VS в быстром режиме (по умолчанию для конфигурации отладки) -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base -USER $APP_UID -WORKDIR /app -EXPOSE 8080 -EXPOSE 8081 +WORKDIR /src + +COPY ["MethodologyMain.API/MethodologyMain.API.csproj", "MethodologyMain.API/"] +COPY ["MethodologyMain.Application/MethodologyMain.Application.csproj","MethodologyMain.Application/"] +COPY ["MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj","MethodologyMain.Infrastructure/"] +COPY ["MethodologyMain.Logic/MethodologyMain.Logic.csproj","MethodologyMain.Logic/"] +COPY ["MethodologyMain.Persistence/MethodologyMain.Persistence.csproj","MethodologyMain.Persistence/"] + +RUN dotnet restore "MethodologyMain.API/MethodologyMain.API.csproj" -# Этот этап используется для сборки проекта службы -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build -ARG BUILD_CONFIGURATION=Release -WORKDIR /src -COPY ["MethodTeams1/MethodTeams1.csproj", "MethodTeams1/"] -RUN dotnet restore "./MethodTeams1/MethodTeams1.csproj" COPY . . -WORKDIR "/src/MethodTeams1" -RUN dotnet build "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/build -# Этот этап используется для публикации проекта службы, который будет скопирован на последний этап -FROM build AS publish -ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false +WORKDIR "/src/MethodologyMain.API" +RUN dotnet publish -c Release -o /app/publish + + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime -# Этот этап используется в рабочей среде или при запуске из VS в обычном режиме (по умолчанию, когда конфигурация отладки не используется) -FROM base AS final WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "MethodTeams1.dll"] \ No newline at end of file + +EXPOSE 80 + +COPY --from=build /app/publish . + +ENTRYPOINT ["dotnet", "MethodologyMain.API.dll"] \ No newline at end of file From 0cf630236d6b6a0bdc897529e67b445a31fb60f4 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:35:16 +0300 Subject: [PATCH 46/52] Register new services in DI container Signed-off-by: BelugaChan --- MethodologyMain.API/Program.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 1ae8352..584abd4 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -18,11 +18,11 @@ using MethodologyMain.Infrastructure.Models; using MethodologyMain.API.Extensions; using Microsoft.Extensions.Options; +using RabbitMqListener.Interfaces; +using MethodologyMain.Infrastructure.Listeners; var builder = WebApplication.CreateBuilder(args); -builder.Services.AddApiAuthentication(builder.Services.BuildServiceProvider().GetRequiredService>()); - builder.Services.AddControllers(); builder.Services.AddControllers() .AddJsonOptions(options => @@ -45,13 +45,18 @@ builder.Services.Configure(builder.Configuration.GetSection(nameof(RabbitMqOptions))); builder.Services.Configure(builder.Configuration.GetSection(nameof(JWTOptions))); +builder.Services.AddApiAuthentication(builder.Services.BuildServiceProvider().GetRequiredService>()); builder.Services.AddScoped(); builder.Services.AddAutoMapper(typeof(TeamProfile).Assembly, typeof(TeamInfoDto).Assembly); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton, LogQueueService>(); +builder.Services.AddHostedService() + .AddSingleton(); + var connection = builder.Configuration.GetConnectionString("PostgresConnection"); builder.Services.AddDbContext(opt => opt.UseNpgsql(connection)); @@ -65,8 +70,8 @@ app.UseHttpsRedirection(); -//app.UseAuthorization(); -//app.UseAuthentication(); +app.UseAuthorization(); +app.UseAuthentication(); app.MapControllers(); From b0a47cf5c5d9579d711c979b950a026630e245cd Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:36:12 +0300 Subject: [PATCH 47/52] Add rabbitMq class libs Signed-off-by: BelugaChan --- .../DLL/RabbitMqListener.dll | Bin 13824 -> 13312 bytes .../DLL/RabbitMqModel.dll | Bin 4608 -> 4608 bytes .../DLL/RabbitMqPublisher.dll | Bin 10240 -> 10240 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll index 5578fb2f5626c851da98eb1728be289966da0b94..91b9c2cccc0073b30c72504709c1d4ebd118976a 100644 GIT binary patch literal 13312 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 b(j1QcAMv%x{=12q4S&Qo{>ilevk3eT9~>*! literal 13824 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 diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqModel.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqModel.dll index 851a61874471fbc6915a93a6f5741fd6193752b1..bbf46e21ed0c36c4c164f9986168877079ab7e32 100644 GIT binary patch delta 943 zcmXw&O-NKx6vzMfzIo#`YCaLeti=qYjbnkSlnvQpzz-$~##B^7QcP^L#4id7dLxDy z3Od|H7z`RlBCTpDuv!R)3vtmRf*68`ENEkp3z3M1k| z!~m+vd`+Xn(ShC(P@8cA4(fd^O_(F!V!ys6Ttoe$`Yg+A8UQK)O6oq3`V(oNb0(Qc z8!#-{=da(2*V2holKBivG6$cij1!i)OiH$#Cf*XvfM%U$O7kaJU*ZZjc6FgQ;6l^d zcN-7b*GdzWc4ABOA6V}rou_ax5kdVET2`*HO)5u%qJ6n7L*z*^56XycRPZ2b8`-ru zM@q!Qkv-`uH8^b3;iRk5uqf(EM+HWZibT_q*Wi-F2T?(SCc`@7Pv8P;q>qLI?=I_M$_M2Yzr(i|f?@lbP~SV${PNDo$s7RI&i#XbCj z7Zd0ceq4hs)P|$k4r7GmPMz#VH%3G^`Y}diJ*pYg*+tDY+U^~!L7_$PrWyJ!gmH=1 zS7k7Zjga0>&Pciy{EbPT0~zF-L`UrKP(b%nw;Ref3)LgDE~~d^^m^@`o`KQkvB6}@ zT$5&)LpARzwbqMLsh5w7>zC&LggR#5eMx?F&4}{zgBOz!S0a4aZDf1&9QND?b(wtr zd|CZukpP*ByM5NzoB7MF3(F0O?F&=wzi(Ho_wI&@wAkN~7O8Y)&grW|uO|Nfc=4@s jbAg5*wpI2$aqlsDYi*eW$)j2OhTIA!bFCc_Kb!F%7>&0w delta 860 zcmXw&T}TvB6vzMP&d%(*O3osdnb_JIt{|8~9}8uOD=ATI=%$iL(iav8Y6KFtYlRsJ zwq1k_q78gVFfjHxr56c8qKHE1p@--p10y0Rq&oLFUO2yV&VSB5Gw04sx-wmPcieZr z`PF)6qKvL*W;>`>6II#WQJ`H{s2bfxRWzAsUrK6A0YiEf4@$sL~LFGk!wJi z1w`2*ZI=i8`Y#NDSKI-7>?6rGv~cX2_(-xf&c0KxsM-{7hB4doMeIx2$ji-c6B`50 zstxbpDLqjRN|fP!OsPV=%fc0yt5c>!3SXqr989ATiPzN? z6N}Q!tsN`~zr*O=teZ#Kco1SwJk~e$K{ZND2&0yxAnK6_o6503v9*_#PA@CBT+VtW zON|9AE5;|#=UptYh_k_stYngJ$VbZM`}n4Yd6?ug2r(UOX9iKtbWtaa2^)p2!V|(S zVK0-=$1KKxaM+YOxGkJ!mf|rpj9I3OQPIP=im#~fcmo%y3a5~wY7DWi-}~CnHQ^G5 zsY!%Z;b|#P3$wU`HDsZYB*jwzyR1V@*J|Whi6=BOTVgiHKK>ef>CGeNLRlyEGrLqT z+wt5^XF=)DfoKT6w^P}_J(1>_hHUWN@5$9%S>6N{uYY`a3v?`D-cu*rJb%ga`gw4h z9jFEZdLqKEoZcD)*OWlm+Lhc%6_W1t;q8_FQ diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll index b2d9043e49abe151d96041c227ecc6beca8504aa..114d9437dcf9341bc3dbd037e0865aa7f94b2093 100644 GIT binary patch delta 276 zcmZn&Xb70l!4j}7_UgnQ8OFAWE5jL$Co?jtvqso4FoaB2WYU=&$*9iQGr5tmo-utg zBa<*|fEWV<OoE=C*_x_Jb^we)R9FB2 delta 256 zcmZn&Xb70l!E#+@|A~n`GK@tNSB5jnPiACPXLYe-U zMkZla8!-k3#>o>E%{K=y{b846VPIfT4h?4T5M*Ew0I}UeJzaow#O7447XreJ3=D6M zhacWK%f?|PSHjtC&J#N}mq@>05ncE*?lJ?TZvYceZ2}O_09rU>a-o7a+Ycb?hr;AO z1to#pRj1oFuCH+4bfHz^-t63*$p;jIb)kacMo>YJN!?xQ9xpHXa6Y|p@`k%T&^Rba joa~?|4Rm;n;-<+Cj3S%)lzuTYmDq0 Date: Mon, 28 Apr 2025 12:37:29 +0300 Subject: [PATCH 48/52] Create listener for rabbitMq (user register) Signed-off-by: BelugaChan --- .../Listeners/RabbitMqUserRegisterListener.cs | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs index d99496d..70fea0b 100644 --- a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs +++ b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs @@ -1,28 +1,48 @@ -using MethodologyMain.Infrastructure.Models; +using AuthMetodology.Infrastructure.Models; +using MethodologyMain.Infrastructure.Models; using MethodologyMain.Logic.Entities; using MethodologyMain.Persistence.Interfaces; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using RabbitMqListener.Abstract; using RabbitMqModel.Models; +using RabbitMqPublisher.Interface; +using Serilog.Events; +using System.Text.Json; namespace MethodologyMain.Infrastructure.Listeners { - public class RabbitMqUserRegisterListener : RabbitMqListenerBase + public class RabbitMqUserRegisterListener : RabbitMqListenerBase { - private readonly IUserRepository userRepository; - public RabbitMqUserRegisterListener(IUserRepository userRepository, IOptions options) : base(options) + private readonly IServiceProvider serviceProvider; + private readonly IRabbitMqPublisherBase logPublishService; + public RabbitMqUserRegisterListener(IRabbitMqPublisherBase logPublishService, IServiceProvider serviceProvider, IOptions options) : base(options) { - this.userRepository = userRepository; + this.logPublishService = logPublishService; + this.serviceProvider = serviceProvider; } protected override string QueueName => "RegisterUserQueue"; - public override async Task ProcessMessageAsync(RabbitMqUserRegisterRecieve message) + public override async Task ProcessMessageAsync(string message) { - await userRepository.AddAsync(new UserMainEntity + var data = JsonSerializer.Deserialize(message)!; + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { - Id = message.UserId + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "Method ProcessMessageAsync to register a user was called", + TimeStamp = DateTime.UtcNow }); + using (var scope = serviceProvider.CreateScope()) + { + var context = scope.ServiceProvider.GetRequiredService(); + await context.AddAsync(new UserMainEntity + { + Id = data.UserId + }); + } + } } } From 8807c7678d38ade099eb568dfda1697993cc9958 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:39:01 +0300 Subject: [PATCH 49/52] Add JWT option model Signed-off-by: BelugaChan --- MethodologyMain.Infrastructure/Models/JWTOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MethodologyMain.Infrastructure/Models/JWTOptions.cs b/MethodologyMain.Infrastructure/Models/JWTOptions.cs index 42e3f01..7e45715 100644 --- a/MethodologyMain.Infrastructure/Models/JWTOptions.cs +++ b/MethodologyMain.Infrastructure/Models/JWTOptions.cs @@ -8,6 +8,6 @@ namespace MethodologyMain.Infrastructure.Models { public class JWTOptions { - public string SecurityKey { get; set; } + public required string SecurityKey { get; set; } } } From 0e47dc543edfe9976f159dcc62b6ed741c3ef4d1 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:40:32 +0300 Subject: [PATCH 50/52] Add model for rabbitMq listener Signed-off-by: BelugaChan --- .../Models/RabbitMqUserRegisterRecieve.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs index b9c9669..6c87699 100644 --- a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs +++ b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs @@ -1,13 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using RabbitMqModel.Models; namespace MethodologyMain.Infrastructure.Models { - public class RabbitMqUserRegisterRecieve + public class RabbitMqUserRegisterRecieve : IEvent { public Guid UserId { get; set; } + + public string EventType => "RecieveUserRegister"; } } From 846fd8b490f9c1ba6dddff0a581b2ae401ef192a Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:43:48 +0300 Subject: [PATCH 51/52] Minor fixes Signed-off-by: BelugaChan --- MethodologyMain.Persistence/Repository/UserRepository.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.Persistence/Repository/UserRepository.cs b/MethodologyMain.Persistence/Repository/UserRepository.cs index fa50e3e..8bb81b2 100644 --- a/MethodologyMain.Persistence/Repository/UserRepository.cs +++ b/MethodologyMain.Persistence/Repository/UserRepository.cs @@ -1,15 +1,10 @@ using MethodologyMain.Logic.Entities; -using MethodologyMain.Logic.Models; +using MethodologyMain.Persistence.Interfaces; using MethodTeams.Data; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MethodologyMain.Persistence.Repository { - public class UserRepository: GenericRepository + public class UserRepository: GenericRepository, IUserRepository { public UserRepository(MyDbContext context) : base(context) { From 1cfc634311996d315250d4c057b70f0709fd28fe Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 12:49:56 +0300 Subject: [PATCH 52/52] Change path to rabbitmq class libs Signed-off-by: BelugaChan --- MethodologyMain.API/MethodologyMain.API.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MethodologyMain.API/MethodologyMain.API.csproj b/MethodologyMain.API/MethodologyMain.API.csproj index 082b760..f777033 100644 --- a/MethodologyMain.API/MethodologyMain.API.csproj +++ b/MethodologyMain.API/MethodologyMain.API.csproj @@ -31,6 +31,9 @@ + + ..\MethodologyMain.Infrastructure\DLL\RabbitMqListener.dll + ..\MethodologyMain.Infrastructure\DLL\RabbitMqModel.dll