diff --git a/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs b/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs index 80547c1..02d8a6b 100644 --- a/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs +++ b/CleanArchitecture/CleanArchitecture.API/Controllers/StreamerController.cs @@ -1,6 +1,11 @@ using CleanArchitecture.Application.Features.Streamers.Commands.CreateStreamer; using CleanArchitecture.Application.Features.Streamers.Commands.DeleteStreamer; using CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer; +using CleanArchitecture.Application.Features.Streamers.Queries.DTOs; +using CleanArchitecture.Application.Features.Streamers.Queries.GetStreamersListByName; +using CleanArchitecture.Application.Features.Streamers.Queries.GetStreamersListByUserName; +using CleanArchitecture.Application.Features.Videos.Queries.DTOs; +using CleanArchitecture.Application.Features.Videos.Queries.GetVideosList; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -19,6 +24,27 @@ namespace CleanArchitecture.API.Controllers mediator = _mediator; } + [HttpGet("ByName/{name}", Name = "GetStreamersByName")] + [Authorize] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task>> GetStreamersByName(string name) + { + var query = new GetStreamerListByNameQuery(name); + var streamers = await mediator.Send(query); + return Ok(streamers); + } + + [HttpGet("ByUserName/{username}", Name = "GetStreamersByUserName")] + [Authorize] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task>> GetStreamersByUserName(string username) + { + var query = new GetStreamerByUserNameListQuery(username); + var streamers = await mediator.Send(query); + return Ok(streamers); + } + + [HttpPost(Name = "CreateStreamer")] [Authorize(Roles = "Administrator")] [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)] diff --git a/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs b/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs index 54caf39..bf640f3 100644 --- a/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs +++ b/CleanArchitecture/CleanArchitecture.API/Controllers/VideoController.cs @@ -4,6 +4,7 @@ using CleanArchitecture.Application.Features.Streamers.Commands.UpdateStreamer; using CleanArchitecture.Application.Features.Videos.Commands.CreateVideo; using CleanArchitecture.Application.Features.Videos.Commands.DeleteVideo; using CleanArchitecture.Application.Features.Videos.Commands.UpdateVideo; +using CleanArchitecture.Application.Features.Videos.Queries.DTOs; using CleanArchitecture.Application.Features.Videos.Queries.GetVideosList; using CleanArchitecture.Domain; using MediatR; @@ -30,7 +31,7 @@ namespace CleanArchitecture.API.Controllers [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] public async Task>> GetVideosByUserName(string username) { - var query = new GetVideosListQuery(username); + var query = new GetVideosListByUserNameQuery(username); var videos = await mediator.Send(query); return Ok(videos); } diff --git a/CleanArchitecture/CleanArchitecture.API/Program.cs b/CleanArchitecture/CleanArchitecture.API/Program.cs index 24c6b45..9e0799d 100644 --- a/CleanArchitecture/CleanArchitecture.API/Program.cs +++ b/CleanArchitecture/CleanArchitecture.API/Program.cs @@ -2,6 +2,8 @@ using CleanArchitecture.Application; using CleanArchitecture.Infrastructure; using CleanArchitecture.Identity; using CleanArchitecture.API.Middlewares; +using CleanArchitecture.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); @@ -14,6 +16,7 @@ builder.Services.AddSwaggerGen(); builder.Services.AddInfrastructureServices(builder.Configuration); + builder.Services.AddApplicationServices(); builder.Services.ConfigureIdentityServices(builder.Configuration); @@ -28,6 +31,40 @@ builder.Services.AddCors(o => var app = builder.Build(); +using (var scope = app.Services.CreateScope()) +{ + IServiceProvider services = scope.ServiceProvider; + + try + { + var dbContext = services.GetRequiredService(); // Reemplaza YourDbContext con el contexto de tu aplicación + dbContext.Database.Migrate(); // Aplica migraciones pendientes + } + catch (Exception ex) + { + // Considera añadir algún manejo de errores aquí, como loguear el error + var logger = services.GetRequiredService>(); + logger.LogError(ex, "Un error ocurrió mientras se aplicaban las migraciones."); + } +} + +using (var scope = app.Services.CreateScope()) +{ + IServiceProvider services = scope.ServiceProvider; + + try + { + var dbContext = services.GetRequiredService(); // Reemplaza YourDbContext con el contexto de tu aplicación + dbContext.Database.Migrate(); // Aplica migraciones pendientes + } + catch (Exception ex) + { + // Considera añadir algún manejo de errores aquí, como loguear el error + var logger = services.GetRequiredService>(); + logger.LogError(ex, "Un error ocurrió mientras se aplicaban las migraciones."); + } +} + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { diff --git a/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json b/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json index b3ae0a7..c0aee29 100644 --- a/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json +++ b/CleanArchitecture/CleanArchitecture.API/Properties/launchSettings.json @@ -10,6 +10,16 @@ "dotnetRunMessages": true, "applicationUrl": "http://localhost:14563" }, + "http-production": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Production" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:14563" + }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, diff --git a/CleanArchitecture/CleanArchitecture.API/appsettings.Development.json b/CleanArchitecture/CleanArchitecture.API/appsettings.Development.json index ff66ba6..950bd10 100644 --- a/CleanArchitecture/CleanArchitecture.API/appsettings.Development.json +++ b/CleanArchitecture/CleanArchitecture.API/appsettings.Development.json @@ -1,8 +1,24 @@ { + "ConnectionStrings": { + "ConnectionString": "server=localhost;database=CleanArchitectureV3;user=root;password=securePassword", + "IdentityConnectionString": "server=localhost;database=CleanArchitecture.Security;user=root;password=securePassword" + }, + "EmailSettings": { + "FromAddress": "alejandro@asarmiento.es", + "ApiKey": "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", + "FromName": "Alejandro Sarmiento" + }, + "JwtSettings": { + "Key": "CjF*Hp$pHvsx$%wsSyfpMevUrzj@%TJv3ZjNPk34daE7N%3KjrjCnv2V76uRY8bCtH5aduTmMwdiuh%QP3iYEh$Fy*XDzz7S&pFyyZVDLDwTdFDxrP9m#A@MBgV6oNCf", + "Issuer": "CleanArchitectureAlejandroSarmiento", + "Audience": "CleanArchitectureUsers", + "DurationInMinutes": 360 + }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } - } + }, + "AllowedHosts": "*" } diff --git a/CleanArchitecture/CleanArchitecture.API/appsettings.Production.json b/CleanArchitecture/CleanArchitecture.API/appsettings.Production.json new file mode 100644 index 0000000..5d068b6 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.API/appsettings.Production.json @@ -0,0 +1,24 @@ +{ + "ConnectionStrings": { + "ConnectionString": "server=smariadb.alexdev.es;port=20003;database=CleanArchitecture;user=CleanUser;password=e7848cfeUN$6Ny$v", + "IdentityConnectionString": "server=smariadb.alexdev.es;port=20003;database=CleanArchitecture.Security;user=CleanUser;password=e7848cfeUN$6Ny$v" + }, + "EmailSettings": { + "FromAddress": "alejandro@asarmiento.es", + "ApiKey": "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", + "FromName": "Alejandro Sarmiento" + }, + "JwtSettings": { + "Key": "CjF*Hp$pHvsx$%wsSyfpMevUrzj@%TJv3ZjNPk34daE7N%3KjrjCnv2V76uRY8bCtH5aduTmMwdiuh%QP3iYEh$Fy*XDzz7S&pFyyZVDLDwTdFDxrP9m#A@MBgV6oNCf", + "Issuer": "CleanArchitectureAlejandroSarmiento", + "Audience": "CleanArchitectureUsers", + "DurationInMinutes": 360 + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/CleanArchitecture/CleanArchitecture.API/appsettings.json b/CleanArchitecture/CleanArchitecture.API/appsettings.json index 351455a..6e29d67 100644 --- a/CleanArchitecture/CleanArchitecture.API/appsettings.json +++ b/CleanArchitecture/CleanArchitecture.API/appsettings.json @@ -1,7 +1,7 @@ { "ConnectionStrings": { - "ConnectionString": "server=localhost;database=CleanArchitectureV2;user=root;password=securePassword", + "ConnectionString": "server=localhost;database=CleanArchitectureV3;user=root;password=securePassword", "IdentityConnectionString": "server=localhost;database=CleanArchitecture.Security;user=root;password=securePassword" }, "EmailSettings": { diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandlerXUnitTests.cs index 69aaa67..d68a9f0 100644 --- a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandlerXUnitTests.cs +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Commands/DeleteStreamer/DeleteStreamerCommandHandlerXUnitTests.cs @@ -34,7 +34,7 @@ namespace CleanArchitecture.Application.UnitTests.Features.Streamers.Commands.De } [Fact] - public async Task UpdateStreamerTest() + public async Task DeleteStreamerTest() { var handler = new DeleteStreamerCommandHandler(mockUnitOfWork.Object, mapper, logger.Object); var request = new DeleteStreamerCommand() diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Queries/GetStreamerListByNameQueryHandlerXUnitTest.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Queries/GetStreamerListByNameQueryHandlerXUnitTest.cs new file mode 100644 index 0000000..21c3a34 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Queries/GetStreamerListByNameQueryHandlerXUnitTest.cs @@ -0,0 +1,42 @@ +using AutoMapper; +using CleanArchitecture.Application.Features.Streamers.Queries.DTOs; +using CleanArchitecture.Application.Features.Streamers.Queries.GetStreamersListByName; +using CleanArchitecture.Application.Features.Streamers.Queries.GetStreamersListByUserName; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Infrastructure.Repositories; +using Moq; +using Shouldly; +using Xunit; + +namespace CleanArchitecture.Application.UnitTests.Features.Streamers.Queries +{ + public class GetStreamerListByNameQueryHandlerXUnitTest + { + private readonly IMapper mapper; + private Mock mockUnitOfWork; + public GetStreamerListByNameQueryHandlerXUnitTest() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + MockStreamerRepository.AddDataStreamerRepository(mockUnitOfWork.Object.StreamerDbContext); + + } + + [Fact] + public async Task GetStreamerListByNameTest() + { + var handler = new GetStreamerListByNameQueryHandler(mockUnitOfWork.Object, mapper); + var request = new GetStreamerListByNameQuery("Avatar"); + var result = await handler.Handle(request, CancellationToken.None); + + result.ShouldBeOfType>(); + result.Count.ShouldBe(2); + } + } +} + diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Queries/GetStreamerListByUserNameQueryHandlerXUnitTest.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Queries/GetStreamerListByUserNameQueryHandlerXUnitTest.cs new file mode 100644 index 0000000..59bbfd0 --- /dev/null +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Streamers/Queries/GetStreamerListByUserNameQueryHandlerXUnitTest.cs @@ -0,0 +1,40 @@ +using AutoMapper; +using CleanArchitecture.Application.Features.Streamers.Queries.DTOs; +using CleanArchitecture.Application.Features.Streamers.Queries.GetStreamersListByUserName; +using CleanArchitecture.Application.Mappings; +using CleanArchitecture.Application.UnitTests.Mocks; +using CleanArchitecture.Infrastructure.Repositories; +using Moq; +using Shouldly; +using Xunit; + +namespace CleanArchitecture.Application.UnitTests.Features.Streamers.Queries +{ + public class GetStreamerListByUserNameQueryHandlerXUnitTest + { + private readonly IMapper mapper; + private Mock mockUnitOfWork; + public GetStreamerListByUserNameQueryHandlerXUnitTest() + { + mockUnitOfWork = MockUnitOfWork.GetUnitOfWork(); + var mapperConfiguration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + mapper = mapperConfiguration.CreateMapper(); + MockStreamerRepository.AddDataStreamerRepository(mockUnitOfWork.Object.StreamerDbContext); + + } + + [Fact] + public async Task GetStreamerListByUserNameTest() + { + var handler = new GetStreamerListByUserNameQueryHandler(mockUnitOfWork.Object, mapper); + var request = new GetStreamerByUserNameListQuery("Alex"); + var result = await handler.Handle(request, CancellationToken.None); + + result.ShouldBeOfType>(); + result.Count.ShouldBe(1); + } + } +} diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Queries/GetVideosListQueryHandlerXUnitTests.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Queries/GetVideosListQueryHandlerXUnitTests.cs index e230572..c10534c 100644 --- a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Queries/GetVideosListQueryHandlerXUnitTests.cs +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Features/Video/Queries/GetVideosListQueryHandlerXUnitTests.cs @@ -1,5 +1,7 @@ using AutoMapper; -using CleanArchitecture.Application.Contracts.Persistence; +using CleanArchitecture.Application.Features.Streamers.Queries.DTOs; +using CleanArchitecture.Application.Features.Streamers.Queries.GetStreamersListByUserName; +using CleanArchitecture.Application.Features.Videos.Queries.DTOs; using CleanArchitecture.Application.Features.Videos.Queries.GetVideosList; using CleanArchitecture.Application.Mappings; using CleanArchitecture.Application.UnitTests.Mocks; @@ -30,8 +32,8 @@ namespace CleanArchitecture.Application.UnitTests.Features.Video.Queries [Fact] public async Task GetVideoListTest() { - var handler = new GetVideosListQueryHandler(mockUnitOfWork.Object, mapper); - var request = new GetVideosListQuery("Alex"); + var handler = new GetVideosListByUserNameQueryHandler(mockUnitOfWork.Object, mapper); + var request = new GetVideosListByUserNameQuery("Alex"); var result = await handler.Handle(request, CancellationToken.None); result.ShouldBeOfType>(); diff --git a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockStreamerRepository.cs b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockStreamerRepository.cs index e39c088..e1f9b58 100644 --- a/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockStreamerRepository.cs +++ b/CleanArchitecture/CleanArchitecture.Application.UnitTests/Mocks/MockStreamerRepository.cs @@ -17,6 +17,24 @@ namespace CleanArchitecture.Application.UnitTests.Mocks fixture.Behaviors.Add(new OmitOnRecursionBehavior()); var streamers = fixture.CreateMany().ToList(); + + streamers.Add(fixture.Build() + .With(tr => tr.CreatedBy, "Alex") + .Without(tr => tr.Videos) + .Create() + ); + streamers.Add(fixture.Build() + .With(tr => tr.Nombre, "Avatar") + .Without(tr => tr.Videos) + .Create() + ); + streamers.Add(fixture.Build() + .With(tr => tr.Nombre, "Avatar 2") + .Without(tr => tr.Videos) + .Create() + ); + + var guidFromText = Guid.Parse("edfe00d5-7599-4788-b52a-acc2a683b188"); streamers.Add(fixture.Build() .With(tr => tr.Id, guidFromText) diff --git a/CleanArchitecture/CleanArchitecture.Application/CleanArchitecture.Application.csproj b/CleanArchitecture/CleanArchitecture.Application/CleanArchitecture.Application.csproj index 1f94596..31b8b41 100644 --- a/CleanArchitecture/CleanArchitecture.Application/CleanArchitecture.Application.csproj +++ b/CleanArchitecture/CleanArchitecture.Application/CleanArchitecture.Application.csproj @@ -14,7 +14,6 @@ - diff --git a/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IStreamerRepository.cs b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IStreamerRepository.cs index 63900d9..4c99182 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IStreamerRepository.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IStreamerRepository.cs @@ -9,6 +9,7 @@ namespace CleanArchitecture.Application.Contracts.Persistence { public interface IStreamerRepository: IAsyncRepository { - + public Task> GetStreamerByNombre(string nombreVideo); + public Task> GetStreamerByUserName(string userName); } } diff --git a/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IVideoRepository.cs b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IVideoRepository.cs index 443546f..26c2e76 100644 --- a/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IVideoRepository.cs +++ b/CleanArchitecture/CleanArchitecture.Application/Contracts/Persistence/IVideoRepository.cs @@ -4,7 +4,7 @@ namespace CleanArchitecture.Application.Contracts.Persistence { public interface IVideoRepository : IAsyncRepository