From de2be35f44743bd47d78b50833e151a8b9911b36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 02:06:39 +0000 Subject: [PATCH 1/2] chore(deps-dev): Bump vite from 4.4.9 to 4.4.12 in /src/Chrono/ClientApp Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.4.9 to 4.4.12. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v4.4.12/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v4.4.12/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- src/Chrono/ClientApp/package-lock.json | 14 +++++++------- src/Chrono/ClientApp/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Chrono/ClientApp/package-lock.json b/src/Chrono/ClientApp/package-lock.json index d21baf8..63d3ff4 100644 --- a/src/Chrono/ClientApp/package-lock.json +++ b/src/Chrono/ClientApp/package-lock.json @@ -31,7 +31,7 @@ "prettier": "3.0.3", "react-router-dom": "^6.14.2", "typescript": "^5.2.2", - "vite": "^4.4.5", + "vite": "^4.4.12", "vite-plugin-mkcert": "^1.16.0" } }, @@ -4248,9 +4248,9 @@ } }, "node_modules/vite": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", - "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.12.tgz", + "integrity": "sha512-KtPlUbWfxzGVul8Nut8Gw2Qe8sBzWY+8QVc5SL8iRFnpnrcoCaNlzO40c1R6hPmcdTwIPEDkq0Y9+27a5tVbdQ==", "dev": true, "dependencies": { "esbuild": "^0.18.10", @@ -7166,9 +7166,9 @@ } }, "vite": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", - "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.12.tgz", + "integrity": "sha512-KtPlUbWfxzGVul8Nut8Gw2Qe8sBzWY+8QVc5SL8iRFnpnrcoCaNlzO40c1R6hPmcdTwIPEDkq0Y9+27a5tVbdQ==", "dev": true, "requires": { "esbuild": "^0.18.10", diff --git a/src/Chrono/ClientApp/package.json b/src/Chrono/ClientApp/package.json index 8c6c046..f7ae305 100644 --- a/src/Chrono/ClientApp/package.json +++ b/src/Chrono/ClientApp/package.json @@ -34,7 +34,7 @@ "prettier": "3.0.3", "react-router-dom": "^6.14.2", "typescript": "^5.2.2", - "vite": "^4.4.5", + "vite": "^4.4.12", "vite-plugin-mkcert": "^1.16.0" } } From 5a7b37f79ac105dfbe52446c0daedc8560f97d7b Mon Sep 17 00:00:00 2001 From: Philipp Meier Date: Sat, 23 Dec 2023 17:27:39 +0100 Subject: [PATCH 2/2] feat: Updated to .NET 8 and C# 12 --- src/Chrono.Tests/Chrono.Tests.csproj | 13 +++--- src/Chrono.Tests/E2E/00_E2ETestBase.cs | 14 +++---- src/Chrono/Chrono.csproj | 17 ++++---- src/Chrono/ConfigureSecurity.cs | 17 +++----- src/Chrono/ConfigureServices.cs | 1 - .../Features/Categories/CreateCategory.cs | 26 +++++------- .../Features/Categories/DeleteCategory.cs | 26 +++++------- .../Features/Categories/GetCategories.cs | 20 ++++------ src/Chrono/Features/Notes/CreateNote.cs | 31 +++++--------- src/Chrono/Features/Notes/DeleteNote.cs | 24 +++++------ src/Chrono/Features/Notes/GetMyNotes.cs | 28 +++++-------- src/Chrono/Features/Notes/GetNote.cs | 20 ++++------ src/Chrono/Features/Notes/UpdateNote.cs | 22 ++++------ .../Features/TaskLists/CreateTaskList.cs | 29 +++++--------- .../Features/TaskLists/DeleteTaskList.cs | 26 +++++------- .../Features/TaskLists/GetMyTaskLists.cs | 27 +++++-------- src/Chrono/Features/TaskLists/GetTaskList.cs | 20 ++++------ .../Features/TaskLists/GetTaskListOptions.cs | 27 +++++-------- .../TaskListSaveChangesInterceptor.cs | 15 ++----- .../Features/TaskLists/UpdateTaskList.cs | 33 ++++++--------- src/Chrono/Features/Tasks/CreateTask.cs | 40 ++++++++----------- src/Chrono/Features/Tasks/DeleteTask.cs | 24 +++++------ src/Chrono/Features/Tasks/GetTask.cs | 20 ++++------ .../Tasks/TaskSaveChangesInterceptor.cs | 15 ++----- src/Chrono/Features/Tasks/UpdateTask.cs | 28 +++++-------- src/Chrono/Features/Users/GetUserInfo.cs | 19 ++++----- src/Chrono/Features/Users/GetUserSettings.cs | 27 +++++-------- src/Chrono/Features/Users/LoginController.cs | 20 ++++------ .../Features/Users/UpdateUserSettings.cs | 39 +++++++----------- .../Persistence/ApplicationDbContext.cs | 33 +++++---------- .../ApplicationDbContextInitializer.cs | 18 +++------ src/Chrono/Shared/Api/JSendResponseBuilder.cs | 14 ++----- .../AuditableEntitySaveChangesInterceptor.cs | 18 ++------- .../Shared/Behaviors/PerformanceBehavior.cs | 18 ++++----- .../Shared/Behaviors/ValidationBehavior.cs | 21 ++++------ .../Exceptions/ForbiddenAccessException.cs | 4 +- .../Shared/Exceptions/NotFoundException.cs | 8 +--- .../Shared/Extensions/TaskListExtensions.cs | 5 +-- .../Shared/Services/CurrentUserService.cs | 15 ++----- src/Chrono/Shared/Services/TextService.cs | 4 +- 40 files changed, 292 insertions(+), 534 deletions(-) diff --git a/src/Chrono.Tests/Chrono.Tests.csproj b/src/Chrono.Tests/Chrono.Tests.csproj index fa4a5b0..0256559 100644 --- a/src/Chrono.Tests/Chrono.Tests.csproj +++ b/src/Chrono.Tests/Chrono.Tests.csproj @@ -1,22 +1,23 @@  - net7.0 + net8.0 false enable disable Chrono.Tests + 12 - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/Chrono.Tests/E2E/00_E2ETestBase.cs b/src/Chrono.Tests/E2E/00_E2ETestBase.cs index 6d388ca..75b6b7e 100644 --- a/src/Chrono.Tests/E2E/00_E2ETestBase.cs +++ b/src/Chrono.Tests/E2E/00_E2ETestBase.cs @@ -5,9 +5,11 @@ namespace Chrono.Tests.E2E; -[Parallelizable(ParallelScope.None)] [Category("E2E")] +[Parallelizable(ParallelScope.None)] +[Category("E2E")] public partial class E2ETests : PlaywrightTest { + private static readonly string[] PlaywrightArgs = { "install" }; private IBrowser _browser; private IConfiguration _config; private IPage _page; @@ -28,10 +30,7 @@ public async Task Init() private async Task InitPlaywright() { // Ensure the required web driver is installed. - Program.Main(new[] - { - "install" - }); + Program.Main(PlaywrightArgs); await PlaywrightSetup(); @@ -52,9 +51,6 @@ private async Task Login_User() await _page.GetByLabel("Email address").FillAsync(_config["TestUser:Username"]!); await _page.GetByLabel("Password").FillAsync(_config["TestUser:Password"]!); - await _page.GetByRole(AriaRole.Button, new PageGetByRoleOptions - { - Name = "Continue" - }).ClickAsync(); + await _page.GetByRole(AriaRole.Button, new PageGetByRoleOptions { Name = "Continue" }).ClickAsync(); } } diff --git a/src/Chrono/Chrono.csproj b/src/Chrono/Chrono.csproj index 9a13e36..5a20f59 100644 --- a/src/Chrono/Chrono.csproj +++ b/src/Chrono/Chrono.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 disable true Latest @@ -13,17 +13,18 @@ enable Chrono Chrono + 12 - + - - - - - - + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Chrono/ConfigureSecurity.cs b/src/Chrono/ConfigureSecurity.cs index bd3eac8..08c5612 100644 --- a/src/Chrono/ConfigureSecurity.cs +++ b/src/Chrono/ConfigureSecurity.cs @@ -1,6 +1,6 @@ using System.Security.Claims; -using Chrono.Shared.Interfaces; using Chrono.Entities; +using Chrono.Shared.Interfaces; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; @@ -26,7 +26,7 @@ public static void AddWebUiSecurityServices(this IServiceCollection services, IC //options.Cookie.SameSite = SameSiteMode.Strict; options.Cookie.Name = configuration["IdentityProvider:CookieName"]; - options.Events.OnSigningOut = async e => await e.HttpContext.RevokeUserRefreshTokenAsync(); + options.Events.OnSigningOut = e => e.HttpContext.RevokeUserRefreshTokenAsync(); }) .AddOpenIdConnect(options => { @@ -75,10 +75,7 @@ public static void AddWebUiSecurityServices(this IServiceCollection services, IC var user = db.Users.FirstOrDefault(x => x.UserId == userId); if (user == null) { - db.Users.Add(new User - { - UserId = userId, Name = userName - }); + db.Users.Add(new User { UserId = userId, Name = userName }); } else { @@ -93,11 +90,9 @@ public static void AddWebUiSecurityServices(this IServiceCollection services, IC }); // Ensures endpoints are secured by default. - services.AddAuthorization(options => - { - options.FallbackPolicy = new AuthorizationPolicyBuilder() + services.AddAuthorizationBuilder() + .SetFallbackPolicy(new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() - .Build(); - }); + .Build()); } } diff --git a/src/Chrono/ConfigureServices.cs b/src/Chrono/ConfigureServices.cs index d1adcf2..5f00624 100644 --- a/src/Chrono/ConfigureServices.cs +++ b/src/Chrono/ConfigureServices.cs @@ -30,7 +30,6 @@ public static void AddWebUiServices(this IServiceCollection services, IConfigura services.AddHttpContextAccessor(); services.AddScoped(); - services.AddScoped(); services.AddControllersWithViews(); services.AddSwaggerGen(options => options.CustomSchemaIds(type => type.FullName)); diff --git a/src/Chrono/Features/Categories/CreateCategory.cs b/src/Chrono/Features/Categories/CreateCategory.cs index fcd9c7a..18c5f98 100644 --- a/src/Chrono/Features/Categories/CreateCategory.cs +++ b/src/Chrono/Features/Categories/CreateCategory.cs @@ -1,6 +1,6 @@ -using Chrono.Shared.Api; +using Chrono.Entities; +using Chrono.Shared.Api; using Chrono.Shared.Interfaces; -using Chrono.Entities; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -9,30 +9,22 @@ namespace Chrono.Features.Categories; public record CreateCategory(string Name) : IRequest; -public class CreateCategoryHandler : IRequestHandler +public class CreateCategoryHandler(IApplicationDbContext context) : IRequestHandler { - private readonly IApplicationDbContext _context; - - public CreateCategoryHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(CreateCategory request, CancellationToken cancellationToken) { - var entity = new Category - { - Name = request.Name - }; - _context.Categories.Add(entity); + var entity = new Category { Name = request.Name }; + context.Categories.Add(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); return entity.Id; } } -[Authorize] [Route("api/categories")] [Tags("Categories")] +[Authorize] +[Route("api/categories")] +[Tags("Categories")] public class CreateCategoryController : ApiControllerBase { [HttpPost] diff --git a/src/Chrono/Features/Categories/DeleteCategory.cs b/src/Chrono/Features/Categories/DeleteCategory.cs index c158920..276c51c 100644 --- a/src/Chrono/Features/Categories/DeleteCategory.cs +++ b/src/Chrono/Features/Categories/DeleteCategory.cs @@ -12,20 +12,12 @@ namespace Chrono.Features.Categories; public record DeleteCategory(int Id) : IRequest; -public class DeleteCategoryHandler : IRequestHandler +public class DeleteCategoryHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public DeleteCategoryHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(DeleteCategory request, CancellationToken cancellationToken) { - var entity = await _context.Categories + var entity = await context.Categories .Include(x => x.Tasks) .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); @@ -34,20 +26,22 @@ public async Task Handle(DeleteCategory request, CancellationToken cancellationT throw new NotFoundException($"Category \"{request.Id}\" not found."); } - if (!entity.IsPermitted(_currentUserService.UserId)) + if (!entity.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } // Ensures only the TaskCategories are getting deleted and not the actual tasks too. - _context.TaskCategories.RemoveRange(entity.Tasks); - _context.Categories.Remove(entity); + context.TaskCategories.RemoveRange(entity.Tasks); + context.Categories.Remove(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/categories")] [Tags("Categories")] +[Authorize] +[Route("api/categories")] +[Tags("Categories")] public class DeleteCategoryController : ApiControllerBase { [HttpDelete("{id:int}")] diff --git a/src/Chrono/Features/Categories/GetCategories.cs b/src/Chrono/Features/Categories/GetCategories.cs index 169426f..a842a66 100644 --- a/src/Chrono/Features/Categories/GetCategories.cs +++ b/src/Chrono/Features/Categories/GetCategories.cs @@ -10,23 +10,15 @@ namespace Chrono.Features.Categories; public record GetCategories : IRequest; -public class GetCategoriesHandler : IRequestHandler +public class GetCategoriesHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public GetCategoriesHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public Task Handle(GetCategories request, CancellationToken cancellationToken) { - var result = _context.Categories + var result = context.Categories .OrderBy(x => x.Name) .AsEnumerable() - .Where(x => x.IsPermitted(_currentUserService.UserId)) + .Where(x => x.IsPermitted(currentUserService.UserId)) .Select(CategoryDto.FromEntity) .ToArray(); @@ -34,7 +26,9 @@ public Task Handle(GetCategories request, CancellationToken cance } } -[Authorize] [Route("api/categories")] [Tags("Categories")] +[Authorize] +[Route("api/categories")] +[Tags("Categories")] public class GetCategoriesController : ApiControllerBase { [HttpGet] diff --git a/src/Chrono/Features/Notes/CreateNote.cs b/src/Chrono/Features/Notes/CreateNote.cs index 2b9f2f6..0bc2137 100644 --- a/src/Chrono/Features/Notes/CreateNote.cs +++ b/src/Chrono/Features/Notes/CreateNote.cs @@ -1,6 +1,6 @@ -using Chrono.Shared.Api; +using Chrono.Entities; +using Chrono.Shared.Api; using Chrono.Shared.Interfaces; -using Chrono.Entities; using FluentValidation; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -23,30 +23,22 @@ public CreateNoteValidator() } } -public class CreateNoteHandler : IRequestHandler +public class CreateNoteHandler(IApplicationDbContext context) : IRequestHandler { - private readonly IApplicationDbContext _context; - - public CreateNoteHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(CreateNote request, CancellationToken cancellationToken) { - var entity = new Note - { - Title = request.Title, Text = request.Text - }; - _context.Notes.Add(entity); + var entity = new Note { Title = request.Title, Text = request.Text }; + context.Notes.Add(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); return entity.Id; } } -[Authorize] [Route("api/notes")] [Tags("Notes")] +[Authorize] +[Route("api/notes")] +[Tags("Notes")] public class CreateNoteController : ApiControllerBase { [HttpPost] @@ -54,9 +46,6 @@ public class CreateNoteController : ApiControllerBase public async Task Create(CreateNote command) { var result = await Mediator.Send(command); - return CreatedAtRoute("GetNote", new - { - id = result - }, JSendResponseBuilder.Success(result)); + return CreatedAtRoute("GetNote", new { id = result }, JSendResponseBuilder.Success(result)); } } diff --git a/src/Chrono/Features/Notes/DeleteNote.cs b/src/Chrono/Features/Notes/DeleteNote.cs index ceb3e64..dbed0ed 100644 --- a/src/Chrono/Features/Notes/DeleteNote.cs +++ b/src/Chrono/Features/Notes/DeleteNote.cs @@ -12,20 +12,12 @@ namespace Chrono.Features.Notes; public record DeleteNote(int Id) : IRequest; -public class DeleteNoteHandler : IRequestHandler +public class DeleteNoteHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public DeleteNoteHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(DeleteNote request, CancellationToken cancellationToken) { - var entity = await _context.Notes + var entity = await context.Notes .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); if (entity == null) @@ -33,18 +25,20 @@ public async Task Handle(DeleteNote request, CancellationToken cancellationToken throw new NotFoundException($"Note \"{request.Id}\" not found."); } - if (!entity.IsPermitted(_currentUserService.UserId)) + if (!entity.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } - _context.Notes.Remove(entity); + context.Notes.Remove(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/notes")] [Tags("Notes")] +[Authorize] +[Route("api/notes")] +[Tags("Notes")] public class DeleteNoteController : ApiControllerBase { [HttpDelete("{id:int}")] diff --git a/src/Chrono/Features/Notes/GetMyNotes.cs b/src/Chrono/Features/Notes/GetMyNotes.cs index d7e4531..c6eb36c 100644 --- a/src/Chrono/Features/Notes/GetMyNotes.cs +++ b/src/Chrono/Features/Notes/GetMyNotes.cs @@ -11,40 +11,28 @@ namespace Chrono.Features.Notes; public record GetMyNotes : IRequest; -public class GetMyNotesHandler : IRequestHandler +public class GetMyNotesHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { private const int MaxTextPreviewLength = 80; - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - private readonly TextService _textService; - - public GetMyNotesHandler(IApplicationDbContext context, ICurrentUserService currentUserService, TextService textService) - { - _context = context; - _currentUserService = currentUserService; - _textService = textService; - } public Task Handle(GetMyNotes request, CancellationToken cancellationToken) { - var result = _context.Notes + var result = context.Notes .OrderByDescending(n => n.Created) .AsEnumerable() - .Where(n => n.IsPermitted(_currentUserService.UserId)) + .Where(n => n.IsPermitted(currentUserService.UserId)) .Select(n => new NotePreview { Id = n.Id, Title = n.Title, - Preview = _textService.Truncate(n.Text, MaxTextPreviewLength), + Preview = TextService.Truncate(n.Text, MaxTextPreviewLength), // Persisted in UTC. Created = n.Created.ToLocalTime().ToString(CultureInfo.InvariantCulture) }) .ToArray(); - return Task.FromResult(new GetMyNotesResponse - { - Notes = result - }); + return Task.FromResult(new GetMyNotesResponse { Notes = result }); } } @@ -61,7 +49,9 @@ public class NotePreview public string Created { get; set; } } -[Authorize] [Route("api/notes")] [Tags("Notes")] +[Authorize] +[Route("api/notes")] +[Tags("Notes")] public class GetMyNotesController : ApiControllerBase { [HttpGet] diff --git a/src/Chrono/Features/Notes/GetNote.cs b/src/Chrono/Features/Notes/GetNote.cs index 30701f1..86451cf 100644 --- a/src/Chrono/Features/Notes/GetNote.cs +++ b/src/Chrono/Features/Notes/GetNote.cs @@ -12,20 +12,12 @@ namespace Chrono.Features.Notes; public record GetNote(int Id) : IRequest; -public class GetNoteHandler : IRequestHandler +public class GetNoteHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public GetNoteHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(GetNote request, CancellationToken cancellationToken) { - var note = await _context.Notes + var note = await context.Notes .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); if (note == null) @@ -33,7 +25,7 @@ public async Task Handle(GetNote request, CancellationToken cancellatio throw new NotFoundException($"Note \"{request.Id}\" not found."); } - if (!note.IsPermitted(_currentUserService.UserId)) + if (!note.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -58,7 +50,9 @@ public class NoteDto public DateTime LastModified { get; init; } } -[Authorize] [Route("api/notes")] [Tags("Notes")] +[Authorize] +[Route("api/notes")] +[Tags("Notes")] public class GetNoteController : ApiControllerBase { [HttpGet("{id:int}", Name = "GetNote")] diff --git a/src/Chrono/Features/Notes/UpdateNote.cs b/src/Chrono/Features/Notes/UpdateNote.cs index 09df005..2f0c9b5 100644 --- a/src/Chrono/Features/Notes/UpdateNote.cs +++ b/src/Chrono/Features/Notes/UpdateNote.cs @@ -31,20 +31,12 @@ public UpdateNoteValidator() } } -public class UpdateNoteHandler : IRequestHandler +public class UpdateNoteHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public UpdateNoteHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(UpdateNote request, CancellationToken cancellationToken) { - var note = await _context.Notes + var note = await context.Notes .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); if (note == null) @@ -52,7 +44,7 @@ public async Task Handle(UpdateNote request, CancellationToken cancellationToken throw new NotFoundException($"Note \"{request.Id}\" not found."); } - if (!note.IsPermitted(_currentUserService.UserId)) + if (!note.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -67,11 +59,13 @@ public async Task Handle(UpdateNote request, CancellationToken cancellationToken note.Text = request.Text; } - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/notes")] [Tags("Notes")] +[Authorize] +[Route("api/notes")] +[Tags("Notes")] public class UpdateNoteController : ApiControllerBase { [HttpPut("{id:int}")] diff --git a/src/Chrono/Features/TaskLists/CreateTaskList.cs b/src/Chrono/Features/TaskLists/CreateTaskList.cs index b7f8283..29185fb 100644 --- a/src/Chrono/Features/TaskLists/CreateTaskList.cs +++ b/src/Chrono/Features/TaskLists/CreateTaskList.cs @@ -1,6 +1,6 @@ +using Chrono.Entities; using Chrono.Shared.Api; using Chrono.Shared.Interfaces; -using Chrono.Entities; using FluentValidation; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -20,30 +20,22 @@ public CreateTaskListValidator() } } -public class CreateTaskListHandler : IRequestHandler +public class CreateTaskListHandler(IApplicationDbContext context) : IRequestHandler { - private readonly IApplicationDbContext _context; - - public CreateTaskListHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(CreateTaskList request, CancellationToken cancellationToken) { - var entity = new TaskList - { - Title = request.Title - }; - _context.TaskLists.Add(entity); + var entity = new TaskList { Title = request.Title }; + context.TaskLists.Add(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); return entity.Id; } } -[Authorize] [Route("api/tasklists")] [Tags("Tasklists")] +[Authorize] +[Route("api/tasklists")] +[Tags("Tasklists")] public class CreateTaskListController : ApiControllerBase { [HttpPost] @@ -52,9 +44,6 @@ public async Task Create(CreateTaskList command) { var result = await Mediator.Send(command); - return CreatedAtRoute("GetTaskList", new - { - id = result - }, JSendResponseBuilder.Success(result)); + return CreatedAtRoute("GetTaskList", new { id = result }, JSendResponseBuilder.Success(result)); } } diff --git a/src/Chrono/Features/TaskLists/DeleteTaskList.cs b/src/Chrono/Features/TaskLists/DeleteTaskList.cs index aa75fc3..23aec89 100644 --- a/src/Chrono/Features/TaskLists/DeleteTaskList.cs +++ b/src/Chrono/Features/TaskLists/DeleteTaskList.cs @@ -12,20 +12,12 @@ namespace Chrono.Features.TaskLists; public record DeleteTaskList(int Id) : IRequest; -public class DeleteTaskListHandler : IRequestHandler +public class DeleteTaskListHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public DeleteTaskListHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(DeleteTaskList request, CancellationToken cancellationToken) { - var entity = await _context.TaskLists + var entity = await context.TaskLists .Include(x => x.Tasks) .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); @@ -34,19 +26,21 @@ public async Task Handle(DeleteTaskList request, CancellationToken cancellationT throw new NotFoundException($"Task list \"{request.Id}\" not found."); } - if (!entity.IsPermitted(_currentUserService.UserId)) + if (!entity.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } - _context.Tasks.RemoveRange(entity.Tasks); - _context.TaskLists.Remove(entity); + context.Tasks.RemoveRange(entity.Tasks); + context.TaskLists.Remove(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/tasklists")] [Tags("Tasklists")] +[Authorize] +[Route("api/tasklists")] +[Tags("Tasklists")] public class DeleteTaskListsController : ApiControllerBase { [HttpDelete("{id:int}")] diff --git a/src/Chrono/Features/TaskLists/GetMyTaskLists.cs b/src/Chrono/Features/TaskLists/GetMyTaskLists.cs index 29040a4..34d3a78 100644 --- a/src/Chrono/Features/TaskLists/GetMyTaskLists.cs +++ b/src/Chrono/Features/TaskLists/GetMyTaskLists.cs @@ -1,8 +1,8 @@ +using Chrono.Entities; using Chrono.Shared.Api; using Chrono.Shared.Extensions; using Chrono.Shared.Interfaces; using Chrono.Shared.Services; -using Chrono.Entities; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -12,23 +12,15 @@ namespace Chrono.Features.TaskLists; public record GetMyTaskLists : IRequest; -public class GetMyTaskListsHandler : IRequestHandler +public class GetMyTaskListsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public GetMyTaskListsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public Task Handle(GetMyTaskLists request, CancellationToken cancellationToken) { - var result = _context.TaskLists + var result = context.TaskLists .OrderBy(x => x.Title) .AsEnumerable() - .Where(x => x.IsPermitted(_currentUserService.UserId)) + .Where(x => x.IsPermitted(currentUserService.UserId)) .Select(TaskListBriefDto.FromEntity) .ToArray(); @@ -43,14 +35,13 @@ public class TaskListBriefDto public static TaskListBriefDto FromEntity(TaskList task) { - return new TaskListBriefDto - { - Id = task.Id, Title = task.Title - }; + return new TaskListBriefDto { Id = task.Id, Title = task.Title }; } } -[Authorize] [Route("api/tasklists")] [Tags("Tasklists")] +[Authorize] +[Route("api/tasklists")] +[Tags("Tasklists")] public class GetMyTaskListsController : ApiControllerBase { [HttpGet] diff --git a/src/Chrono/Features/TaskLists/GetTaskList.cs b/src/Chrono/Features/TaskLists/GetTaskList.cs index 2ea3a15..6a90a00 100644 --- a/src/Chrono/Features/TaskLists/GetTaskList.cs +++ b/src/Chrono/Features/TaskLists/GetTaskList.cs @@ -12,20 +12,12 @@ namespace Chrono.Features.TaskLists; public record GetTaskList(int ListId) : IRequest; -public class GetTaskListHandler : IRequestHandler +public class GetTaskListHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public GetTaskListHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(GetTaskList request, CancellationToken cancellationToken) { - var taskList = await _context.TaskLists + var taskList = await context.TaskLists .Include(x => x.Tasks) .ThenInclude(x => x.Categories) .ThenInclude(x => x.Category) @@ -36,7 +28,7 @@ public async Task Handle(GetTaskList request, CancellationToken can throw new NotFoundException($"Task list \"{request.ListId}\" not found."); } - if (!taskList.IsPermitted(_currentUserService.UserId)) + if (!taskList.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -45,7 +37,9 @@ public async Task Handle(GetTaskList request, CancellationToken can } } -[Authorize] [Route("api/tasklists")] [Tags("Tasklists")] +[Authorize] +[Route("api/tasklists")] +[Tags("Tasklists")] public class GetTaskListController : ApiControllerBase { [HttpGet("{id:int}", Name = "GetTaskList")] diff --git a/src/Chrono/Features/TaskLists/GetTaskListOptions.cs b/src/Chrono/Features/TaskLists/GetTaskListOptions.cs index 8208928..1c8f537 100644 --- a/src/Chrono/Features/TaskLists/GetTaskListOptions.cs +++ b/src/Chrono/Features/TaskLists/GetTaskListOptions.cs @@ -1,9 +1,9 @@ -using Chrono.Shared.Api; +using Chrono.Entities; +using Chrono.Shared.Api; using Chrono.Shared.Exceptions; using Chrono.Shared.Extensions; using Chrono.Shared.Interfaces; using Chrono.Shared.Services; -using Chrono.Entities; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -13,20 +13,12 @@ namespace Chrono.Features.TaskLists; public record GetTaskListOptions(int ListId) : IRequest; -public class GetTaskListOptionsHandler : IRequestHandler +public class GetTaskListOptionsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public GetTaskListOptionsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(GetTaskListOptions request, CancellationToken cancellationToken) { - var taskList = await _context.TaskLists + var taskList = await context.TaskLists .SingleOrDefaultAsync(x => x.Id == request.ListId, cancellationToken); if (taskList == null) @@ -34,7 +26,7 @@ public async Task Handle(GetTaskListOptions request, Cancell throw new NotFoundException($"Task list \"{request.ListId}\" not found."); } - if (!taskList.IsPermitted(_currentUserService.UserId)) + if (!taskList.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -52,12 +44,15 @@ public static TaskListOptionsDto FromEntity(TaskListOptions taskListOptions) { return new TaskListOptionsDto { - RequireBusinessValue = taskListOptions?.RequireBusinessValue ?? true, RequireDescription = taskListOptions?.RequireDescription ?? true + RequireBusinessValue = taskListOptions?.RequireBusinessValue ?? true, + RequireDescription = taskListOptions?.RequireDescription ?? true }; } } -[Authorize] [Route("api/tasklists")] [Tags("Tasklists")] +[Authorize] +[Route("api/tasklists")] +[Tags("Tasklists")] public class GetTaskListOptionsController : ApiControllerBase { [HttpGet("{id:int}/options")] diff --git a/src/Chrono/Features/TaskLists/TaskListSaveChangesInterceptor.cs b/src/Chrono/Features/TaskLists/TaskListSaveChangesInterceptor.cs index 38393a9..a5ec63a 100644 --- a/src/Chrono/Features/TaskLists/TaskListSaveChangesInterceptor.cs +++ b/src/Chrono/Features/TaskLists/TaskListSaveChangesInterceptor.cs @@ -1,20 +1,13 @@ -using Chrono.Shared; -using Chrono.Shared.Services; using Chrono.Entities; using Chrono.Infrastructure.Persistence; +using Chrono.Shared; +using Chrono.Shared.Services; using Microsoft.EntityFrameworkCore; namespace Chrono.Features.TaskLists; -public class TaskListSaveChangesInterceptor : BaseSaveChangesInterceptor +public class TaskListSaveChangesInterceptor(ICurrentUserService currentUserService) : BaseSaveChangesInterceptor { - private readonly ICurrentUserService _currentUserService; - - public TaskListSaveChangesInterceptor(ICurrentUserService currentUserService) - { - _currentUserService = currentUserService; - } - protected override void UpdateEntities(DbContext context) { if (context is not ApplicationDbContext dbContext) @@ -23,7 +16,7 @@ protected override void UpdateEntities(DbContext context) } var currentUtcDate = DateTime.UtcNow; - var currentUser = dbContext.Users.SingleOrDefault(x => x.UserId == _currentUserService.UserId); + var currentUser = dbContext.Users.SingleOrDefault(x => x.UserId == currentUserService.UserId); var changedTaskListOptions = context.ChangeTracker.Entries(); foreach (var entry in changedTaskListOptions) diff --git a/src/Chrono/Features/TaskLists/UpdateTaskList.cs b/src/Chrono/Features/TaskLists/UpdateTaskList.cs index cac8336..ee03a62 100644 --- a/src/Chrono/Features/TaskLists/UpdateTaskList.cs +++ b/src/Chrono/Features/TaskLists/UpdateTaskList.cs @@ -1,9 +1,9 @@ -using Chrono.Shared.Api; +using Chrono.Entities; +using Chrono.Shared.Api; using Chrono.Shared.Exceptions; using Chrono.Shared.Extensions; using Chrono.Shared.Interfaces; using Chrono.Shared.Services; -using Chrono.Entities; using FluentValidation; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -39,20 +39,12 @@ public UpdateTaskListValidator() } } -public class UpdateTaskListHandler : IRequestHandler +public class UpdateTaskListHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public UpdateTaskListHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(UpdateTaskList request, CancellationToken cancellationToken) { - var taskList = await _context.TaskLists + var taskList = await context.TaskLists .SingleOrDefaultAsync(x => x.Id == request.TaskListId, cancellationToken); if (taskList == null) @@ -60,7 +52,7 @@ public async Task Handle(UpdateTaskList request, CancellationToken cancellationT throw new NotFoundException($"Task list \"{request.TaskListId}\" not found."); } - if (!taskList.IsPermitted(_currentUserService.UserId)) + if (!taskList.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -73,21 +65,20 @@ public async Task Handle(UpdateTaskList request, CancellationToken cancellationT var options = taskList.Options; if (options == null) { - options = new TaskListOptions - { - TaskList = taskList, TaskListId = taskList.Id - }; - _context.TaskListOptions.Add(options); + options = new TaskListOptions { TaskList = taskList, TaskListId = taskList.Id }; + context.TaskListOptions.Add(options); } options.RequireBusinessValue = request.RequireBusinessValue.GetValueOrDefault(); options.RequireDescription = request.RequireDescription.GetValueOrDefault(); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/tasklists")] [Tags("Tasklists")] +[Authorize] +[Route("api/tasklists")] +[Tags("Tasklists")] public class UpdateTaskListController : ApiControllerBase { [HttpPut("{id:int}")] diff --git a/src/Chrono/Features/Tasks/CreateTask.cs b/src/Chrono/Features/Tasks/CreateTask.cs index 60beebd..f5412fc 100644 --- a/src/Chrono/Features/Tasks/CreateTask.cs +++ b/src/Chrono/Features/Tasks/CreateTask.cs @@ -1,9 +1,9 @@ +using Chrono.Entities; using Chrono.Shared.Api; using Chrono.Shared.Exceptions; using Chrono.Shared.Extensions; using Chrono.Shared.Interfaces; using Chrono.Shared.Services; -using Chrono.Entities; using FluentValidation; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -57,20 +57,12 @@ private static TaskListOptions GetTaskListOptions(IApplicationDbContext dbContex } } -public class CreateTaskHandler : IRequestHandler +public class CreateTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public CreateTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(CreateTask request, CancellationToken cancellationToken) { - var taskList = await _context.TaskLists + var taskList = await context.TaskLists .Include(x => x.Tasks) .SingleOrDefaultAsync(x => x.Id == request.ListId, cancellationToken); @@ -79,35 +71,40 @@ public async Task Handle(CreateTask request, CancellationToken cancellation throw new NotFoundException($"Task list \"{request.ListId}\" not found."); } - if (!taskList.IsPermitted(_currentUserService.UserId)) + if (!taskList.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } var task = new Task { - Name = request.Name, Position = request.Position, BusinessValue = request.BusinessValue, Description = request.Description + Name = request.Name, + Position = request.Position, + BusinessValue = request.BusinessValue, + Description = request.Description }; var newCategoryNames = request.Categories.Select(x => x.Name).ToArray(); task.SetCategories( - _context.Categories + context.Categories .Where(x => newCategoryNames.Contains(x.Name)) .AsEnumerable() - .Where(x => x.IsPermitted(_currentUserService.UserId)) + .Where(x => x.IsPermitted(currentUserService.UserId)) .ToArray() ); taskList.InsertAt(request.Position, task); - _context.Tasks.Add(task); + context.Tasks.Add(task); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); return task.Id; } } -[Authorize] [Route("api/tasks")] [Tags("Tasks")] +[Authorize] +[Route("api/tasks")] +[Tags("Tasks")] public class CreateTaskController : ApiControllerBase { [HttpPost] @@ -118,9 +115,6 @@ public async Task Create(CreateTask command) { var result = await Mediator.Send(command); - return CreatedAtRoute("GetTask", new - { - id = result - }, JSendResponseBuilder.Success(result)); + return CreatedAtRoute("GetTask", new { id = result }, JSendResponseBuilder.Success(result)); } } diff --git a/src/Chrono/Features/Tasks/DeleteTask.cs b/src/Chrono/Features/Tasks/DeleteTask.cs index 9536dc2..5448c6c 100644 --- a/src/Chrono/Features/Tasks/DeleteTask.cs +++ b/src/Chrono/Features/Tasks/DeleteTask.cs @@ -12,20 +12,12 @@ namespace Chrono.Features.Tasks; public record DeleteTask(int Id) : IRequest; -public class DeleteTaskHandler : IRequestHandler +public class DeleteTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public DeleteTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(DeleteTask request, CancellationToken cancellationToken) { - var entity = await _context.Tasks + var entity = await context.Tasks .Include(x => x.List) .ThenInclude(x => x.Tasks) .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); @@ -35,7 +27,7 @@ public async Task Handle(DeleteTask request, CancellationToken cancellationToken throw new NotFoundException($"Task item \"{request.Id}\" not found."); } - if (!entity.IsPermitted(_currentUserService.UserId)) + if (!entity.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -48,13 +40,15 @@ public async Task Handle(DeleteTask request, CancellationToken cancellationToken var taskList = entity.List; taskList.Tasks.Remove(entity); - _context.Tasks.Remove(entity); + context.Tasks.Remove(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/tasks")] [Tags("Tasks")] +[Authorize] +[Route("api/tasks")] +[Tags("Tasks")] public class DeleteTaskController : ApiControllerBase { [HttpDelete("{id:int}")] diff --git a/src/Chrono/Features/Tasks/GetTask.cs b/src/Chrono/Features/Tasks/GetTask.cs index e71d4e8..ef4ee3d 100644 --- a/src/Chrono/Features/Tasks/GetTask.cs +++ b/src/Chrono/Features/Tasks/GetTask.cs @@ -12,20 +12,12 @@ namespace Chrono.Features.Tasks; public record GetTask(int Id) : IRequest; -public class GetTaskHandler : IRequestHandler +public class GetTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public GetTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(GetTask request, CancellationToken cancellationToken) { - var task = await _context.Tasks + var task = await context.Tasks .Include(x => x.Categories) .ThenInclude(x => x.Category) .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); @@ -35,7 +27,7 @@ public async Task Handle(GetTask request, CancellationToken cancellatio throw new NotFoundException($"Task \"{request.Id}\" not found."); } - if (!task.IsPermitted(_currentUserService.UserId)) + if (!task.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -44,7 +36,9 @@ public async Task Handle(GetTask request, CancellationToken cancellatio } } -[Authorize] [Route("api/tasks")] [Tags("Tasks")] +[Authorize] +[Route("api/tasks")] +[Tags("Tasks")] public class GetTaskController : ApiControllerBase { [HttpGet("{id:int}", Name = "GetTask")] diff --git a/src/Chrono/Features/Tasks/TaskSaveChangesInterceptor.cs b/src/Chrono/Features/Tasks/TaskSaveChangesInterceptor.cs index 043f21d..08ee2d3 100644 --- a/src/Chrono/Features/Tasks/TaskSaveChangesInterceptor.cs +++ b/src/Chrono/Features/Tasks/TaskSaveChangesInterceptor.cs @@ -1,22 +1,15 @@ +using Chrono.Entities; +using Chrono.Infrastructure.Persistence; using Chrono.Shared; using Chrono.Shared.Extensions; using Chrono.Shared.Services; -using Chrono.Entities; -using Chrono.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; using Task = Chrono.Entities.Task; namespace Chrono.Features.Tasks; -public class TaskSaveChangesInterceptor : BaseSaveChangesInterceptor +public class TaskSaveChangesInterceptor(ICurrentUserService currentUserService) : BaseSaveChangesInterceptor { - private readonly ICurrentUserService _currentUserService; - - public TaskSaveChangesInterceptor(ICurrentUserService currentUserService) - { - _currentUserService = currentUserService; - } - protected override void UpdateEntities(DbContext context) { if (context is not ApplicationDbContext dbContext) @@ -25,7 +18,7 @@ protected override void UpdateEntities(DbContext context) } var currentUtcDate = DateTime.UtcNow; - var currentUser = dbContext.Users.SingleOrDefault(x => x.UserId == _currentUserService.UserId); + var currentUser = dbContext.Users.SingleOrDefault(x => x.UserId == currentUserService.UserId); HandleTaskPositionChanges(context); HandleTaskCategoryChanges(context, currentUser, currentUtcDate); diff --git a/src/Chrono/Features/Tasks/UpdateTask.cs b/src/Chrono/Features/Tasks/UpdateTask.cs index d484ac6..fb12386 100644 --- a/src/Chrono/Features/Tasks/UpdateTask.cs +++ b/src/Chrono/Features/Tasks/UpdateTask.cs @@ -1,9 +1,9 @@ +using Chrono.Entities; using Chrono.Shared.Api; using Chrono.Shared.Exceptions; using Chrono.Shared.Extensions; using Chrono.Shared.Interfaces; using Chrono.Shared.Services; -using Chrono.Entities; using FluentValidation; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -59,20 +59,12 @@ private static TaskListOptions GetTaskListOptions(IApplicationDbContext dbContex } } -public class UpdateTaskHandler : IRequestHandler +public class UpdateTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public UpdateTaskHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(UpdateTask request, CancellationToken cancellationToken) { - var task = await _context.Tasks + var task = await context.Tasks .Include(x => x.List) .ThenInclude(x => x.Tasks) .ThenInclude(x => x.Categories) @@ -84,7 +76,7 @@ public async Task Handle(UpdateTask request, CancellationToken cancellationToken throw new NotFoundException($"Task item \"{request.Id}\" not found."); } - if (!task.IsPermitted(_currentUserService.UserId)) + if (!task.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -107,10 +99,10 @@ public async Task Handle(UpdateTask request, CancellationToken cancellationToken var newCategoryNames = request.Categories.Select(x => x.Name).ToArray(); task.SetCategories( - _context.Categories + context.Categories .Where(x => newCategoryNames.Contains(x.Name)) .AsEnumerable() - .Where(x => x.IsPermitted(_currentUserService.UserId)) + .Where(x => x.IsPermitted(currentUserService.UserId)) .ToArray() ); @@ -121,11 +113,13 @@ public async Task Handle(UpdateTask request, CancellationToken cancellationToken } } - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/tasks")] [Tags("Tasks")] +[Authorize] +[Route("api/tasks")] +[Tags("Tasks")] public class UpdateTaskController : ApiControllerBase { [HttpPut("{id:int}")] diff --git a/src/Chrono/Features/Users/GetUserInfo.cs b/src/Chrono/Features/Users/GetUserInfo.cs index d29e735..5550609 100644 --- a/src/Chrono/Features/Users/GetUserInfo.cs +++ b/src/Chrono/Features/Users/GetUserInfo.cs @@ -8,20 +8,13 @@ namespace Chrono.Features.Users; public record GetUserInfo : IRequest; -public class GetUserInfoHandler : IRequestHandler +public class GetUserInfoHandler(ICurrentUserService currentUserService) : IRequestHandler { - private readonly ICurrentUserService _currentUserService; - - public GetUserInfoHandler(ICurrentUserService currentUserService) - { - _currentUserService = currentUserService; - } - - public async Task Handle(GetUserInfo request, CancellationToken cancellationToken) + public Task Handle(GetUserInfo request, CancellationToken cancellationToken) { - return await Task.FromResult(new UserInfoDto + return Task.FromResult(new UserInfoDto { - Username = _currentUserService.UserName, IsAuthenticated = _currentUserService.IsAuthenticated + Username = currentUserService.UserName, IsAuthenticated = currentUserService.IsAuthenticated }); } } @@ -32,7 +25,9 @@ public class UserInfoDto public bool IsAuthenticated { get; init; } } -[Authorize] [Route("api/user")] [Tags("User")] +[Authorize] +[Route("api/user")] +[Tags("User")] public class GetUserInfoController : ApiControllerBase { [HttpGet] diff --git a/src/Chrono/Features/Users/GetUserSettings.cs b/src/Chrono/Features/Users/GetUserSettings.cs index 77d9c8e..f88710b 100644 --- a/src/Chrono/Features/Users/GetUserSettings.cs +++ b/src/Chrono/Features/Users/GetUserSettings.cs @@ -11,32 +11,21 @@ namespace Chrono.Features.Users; public record GetUserSettings : IRequest; -public class GetUserSettingsHandler : IRequestHandler +public class GetUserSettingsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public GetUserSettingsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(GetUserSettings request, CancellationToken cancellationToken) { - var currentUser = await _context.Users + var currentUser = await context.Users .Include(x => x.UserSettings) - .SingleOrDefaultAsync(x => x.UserId == _currentUserService.UserId, cancellationToken); + .SingleOrDefaultAsync(x => x.UserId == currentUserService.UserId, cancellationToken); if (currentUser == null) { - throw new NotFoundException($"User \"{_currentUserService.UserId}\" not found."); + throw new NotFoundException($"User \"{currentUserService.UserId}\" not found."); } - return new UserSettingsDto - { - DefaultTaskListId = currentUser.UserSettings?.DefaultTaskList?.Id - }; + return new UserSettingsDto { DefaultTaskListId = currentUser.UserSettings?.DefaultTaskList?.Id }; } } @@ -45,7 +34,9 @@ public class UserSettingsDto public int? DefaultTaskListId { get; init; } } -[Authorize] [Route("api/user")] [Tags("User")] +[Authorize] +[Route("api/user")] +[Tags("User")] public class GetUserSettingsController : ApiControllerBase { [HttpGet("settings")] diff --git a/src/Chrono/Features/Users/LoginController.cs b/src/Chrono/Features/Users/LoginController.cs index 3b960ba..59a229b 100644 --- a/src/Chrono/Features/Users/LoginController.cs +++ b/src/Chrono/Features/Users/LoginController.cs @@ -7,16 +7,10 @@ namespace Chrono.Features.Users; -[Authorize] [ApiExplorerSettings(IgnoreApi = true)] -public class LoginController : ApiControllerBase +[Authorize] +[ApiExplorerSettings(IgnoreApi = true)] +public class LoginController(IConfiguration config) : ApiControllerBase { - private readonly IConfiguration _configuration; - - public LoginController(IConfiguration config) - { - _configuration = config; - } - [HttpGet] public async Task Get([FromQuery] string redirectUrl, [FromQuery] string sign = "in") { @@ -26,13 +20,15 @@ public async Task Get([FromQuery] string redirectUrl, [FromQuery] } var idToken = await HttpContext.GetTokenAsync("id_token"); - var idpHost = _configuration["IdentityProvider:Authority"]; + var idpHost = config["IdentityProvider:Authority"]; SignOut("cookie", "oidc"); // To ensure that all auth. cookies are being deleted, since ASP.NET Core uses the ChunkingCookieManager for cookie authentication by default. - new ChunkingCookieManager().DeleteCookie(HttpContext, _configuration["IdentityProvider:CookieName"]!, new CookieOptions()); + new ChunkingCookieManager().DeleteCookie(HttpContext, config["IdentityProvider:CookieName"]!, + new CookieOptions()); - return Redirect(idpHost + "oidc/logout?id_token_hint=" + idToken + "&post_logout_redirect_uri=" + HttpUtility.UrlEncode(redirectUrl)); + return Redirect(idpHost + "oidc/logout?id_token_hint=" + idToken + "&post_logout_redirect_uri=" + + HttpUtility.UrlEncode(redirectUrl)); } } diff --git a/src/Chrono/Features/Users/UpdateUserSettings.cs b/src/Chrono/Features/Users/UpdateUserSettings.cs index ba6ef9f..a812429 100644 --- a/src/Chrono/Features/Users/UpdateUserSettings.cs +++ b/src/Chrono/Features/Users/UpdateUserSettings.cs @@ -1,9 +1,9 @@ -using Chrono.Shared.Api; +using Chrono.Entities; +using Chrono.Shared.Api; using Chrono.Shared.Exceptions; using Chrono.Shared.Extensions; using Chrono.Shared.Interfaces; using Chrono.Shared.Services; -using Chrono.Entities; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -14,42 +14,31 @@ namespace Chrono.Features.Users; public record UpdateUserSettings(int? DefaultTaskListId) : IRequest; -public class UpdateUserSettingsHandler : IRequestHandler +public class UpdateUserSettingsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly ICurrentUserService _currentUserService; - - public UpdateUserSettingsHandler(IApplicationDbContext context, ICurrentUserService currentUserService) - { - _context = context; - _currentUserService = currentUserService; - } - public async Task Handle(UpdateUserSettings request, CancellationToken cancellationToken) { - var currentUser = await _context.Users + var currentUser = await context.Users .Include(x => x.UserSettings) - .SingleOrDefaultAsync(x => x.UserId == _currentUserService.UserId, cancellationToken); + .SingleOrDefaultAsync(x => x.UserId == currentUserService.UserId, cancellationToken); if (currentUser == null) { - throw new NotFoundException($"User \"{_currentUserService.UserId}\" not found."); + throw new NotFoundException($"User \"{currentUserService.UserId}\" not found."); } var userSettings = currentUser.UserSettings; if (userSettings == null) { - userSettings = new UserSettings - { - User = currentUser, UserId = currentUser.Id - }; - _context.UserSettings.Add(userSettings); + userSettings = new UserSettings { User = currentUser, UserId = currentUser.Id }; + context.UserSettings.Add(userSettings); } if (request.DefaultTaskListId.HasValue) { var defaultTaskListId = request.DefaultTaskListId.Value; - var taskList = await _context.TaskLists + var taskList = await context.TaskLists .SingleOrDefaultAsync(x => x.Id == defaultTaskListId, cancellationToken); if (taskList == null) @@ -57,7 +46,7 @@ public async Task Handle(UpdateUserSettings request, CancellationToken cancellat throw new NotFoundException($"Task list \"{defaultTaskListId}\" not found."); } - if (!taskList.IsPermitted(_currentUserService.UserId)) + if (!taskList.IsPermitted(currentUserService.UserId)) { throw new ForbiddenAccessException(); } @@ -69,11 +58,13 @@ public async Task Handle(UpdateUserSettings request, CancellationToken cancellat userSettings.DefaultTaskList = null; } - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } -[Authorize] [Route("api/user")] [Tags("User")] +[Authorize] +[Route("api/user")] +[Tags("User")] public class UpdateUserSettingsController : ApiControllerBase { [HttpPut("settings")] diff --git a/src/Chrono/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Chrono/Infrastructure/Persistence/ApplicationDbContext.cs index 6cb8b3e..5645b5c 100644 --- a/src/Chrono/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Chrono/Infrastructure/Persistence/ApplicationDbContext.cs @@ -1,32 +1,21 @@ using System.Reflection; -using Chrono.Shared.Audit; -using Chrono.Shared.Interfaces; using Chrono.Entities; using Chrono.Features.TaskLists; using Chrono.Features.Tasks; +using Chrono.Shared.Audit; +using Chrono.Shared.Interfaces; using Microsoft.EntityFrameworkCore; using Task = Chrono.Entities.Task; namespace Chrono.Infrastructure.Persistence; -public class ApplicationDbContext : DbContext, IApplicationDbContext +public class ApplicationDbContext( + DbContextOptions options, + AuditableEntitySaveChangesInterceptor auditableEntitySaveChangesInterceptor, + TaskSaveChangesInterceptor taskSaveChangesInterceptor, + TaskListSaveChangesInterceptor taskListSaveChangesInterceptor) + : DbContext(options), IApplicationDbContext { - private readonly AuditableEntitySaveChangesInterceptor _auditableEntitySaveChangesInterceptor; - private readonly TaskListSaveChangesInterceptor _taskListSaveChangesInterceptor; - private readonly TaskSaveChangesInterceptor _taskSaveChangesInterceptor; - - public ApplicationDbContext( - DbContextOptions options, - AuditableEntitySaveChangesInterceptor auditableEntitySaveChangesInterceptor, - TaskSaveChangesInterceptor taskSaveChangesInterceptor, - TaskListSaveChangesInterceptor taskListSaveChangesInterceptor) - : base(options) - { - _auditableEntitySaveChangesInterceptor = auditableEntitySaveChangesInterceptor; - _taskSaveChangesInterceptor = taskSaveChangesInterceptor; - _taskListSaveChangesInterceptor = taskListSaveChangesInterceptor; - } - public DbSet Tasks => Set(); public DbSet TaskLists => Set(); public DbSet TaskListOptions => Set(); @@ -45,9 +34,9 @@ protected override void OnModelCreating(ModelBuilder builder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - optionsBuilder.AddInterceptors(_auditableEntitySaveChangesInterceptor); - optionsBuilder.AddInterceptors(_taskSaveChangesInterceptor); - optionsBuilder.AddInterceptors(_taskListSaveChangesInterceptor); + optionsBuilder.AddInterceptors(auditableEntitySaveChangesInterceptor); + optionsBuilder.AddInterceptors(taskSaveChangesInterceptor); + optionsBuilder.AddInterceptors(taskListSaveChangesInterceptor); base.OnConfiguring(optionsBuilder); } } diff --git a/src/Chrono/Infrastructure/Persistence/ApplicationDbContextInitializer.cs b/src/Chrono/Infrastructure/Persistence/ApplicationDbContextInitializer.cs index d4aa5da..09e2832 100644 --- a/src/Chrono/Infrastructure/Persistence/ApplicationDbContextInitializer.cs +++ b/src/Chrono/Infrastructure/Persistence/ApplicationDbContextInitializer.cs @@ -2,27 +2,19 @@ namespace Chrono.Infrastructure.Persistence; -public class ApplicationDbContextInitializer +public class ApplicationDbContextInitializer( + ILogger logger, + ApplicationDbContext context) { - private readonly ApplicationDbContext _context; - private readonly ILogger _logger; - - public ApplicationDbContextInitializer(ILogger logger, - ApplicationDbContext context) - { - _logger = logger; - _context = context; - } - public async Task InitializeAsync() { try { - await _context.Database.MigrateAsync(); + await context.Database.MigrateAsync(); } catch (Exception ex) { - _logger.LogError(ex, "Error occured while initializing the database"); + logger.LogError(ex, "Error occured while initializing the database"); throw; } } diff --git a/src/Chrono/Shared/Api/JSendResponseBuilder.cs b/src/Chrono/Shared/Api/JSendResponseBuilder.cs index bec7fd8..171791a 100644 --- a/src/Chrono/Shared/Api/JSendResponseBuilder.cs +++ b/src/Chrono/Shared/Api/JSendResponseBuilder.cs @@ -10,10 +10,7 @@ public static class JSendResponseBuilder { private static JSendResponseBuilder CreateResponse(string status, T? data, string? message = null) { - return new JSendResponseBuilder(status) - { - Data = data, Message = message - }; + return new JSendResponseBuilder(status) { Data = data, Message = message }; } public static JSendResponseBuilder Success(T data, string? message = null) @@ -32,14 +29,9 @@ public static JSendResponseBuilder Error(string message, T? data = default } } -public class JSendResponseBuilder +public class JSendResponseBuilder(string status) { - public JSendResponseBuilder(string status) - { - Status = status; - } - - public string Status { get; set; } + public string Status { get; set; } = status; [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public string? Message { get; set; } diff --git a/src/Chrono/Shared/Audit/AuditableEntitySaveChangesInterceptor.cs b/src/Chrono/Shared/Audit/AuditableEntitySaveChangesInterceptor.cs index c2dd388..bf0443a 100644 --- a/src/Chrono/Shared/Audit/AuditableEntitySaveChangesInterceptor.cs +++ b/src/Chrono/Shared/Audit/AuditableEntitySaveChangesInterceptor.cs @@ -6,15 +6,8 @@ namespace Chrono.Shared.Audit; -public class AuditableEntitySaveChangesInterceptor : BaseSaveChangesInterceptor +public class AuditableEntitySaveChangesInterceptor(ICurrentUserService currentUserService) : BaseSaveChangesInterceptor { - private readonly ICurrentUserService _currentUserService; - - public AuditableEntitySaveChangesInterceptor(ICurrentUserService currentUserService) - { - _currentUserService = currentUserService; - } - protected override void UpdateEntities(DbContext context) { if (context is not ApplicationDbContext dbContext) @@ -23,13 +16,10 @@ protected override void UpdateEntities(DbContext context) } var currentUtcDate = DateTime.UtcNow; - var currentUser = dbContext.Users.SingleOrDefault(x => x.UserId == _currentUserService.UserId); - if (currentUser == null && !string.IsNullOrEmpty(_currentUserService.UserId)) + var currentUser = dbContext.Users.SingleOrDefault(x => x.UserId == currentUserService.UserId); + if (currentUser == null && !string.IsNullOrEmpty(currentUserService.UserId)) { - currentUser = new User - { - UserId = _currentUserService.UserId, Name = _currentUserService.UserName - }; + currentUser = new User { UserId = currentUserService.UserId, Name = currentUserService.UserName }; dbContext.Users.Add(currentUser); } diff --git a/src/Chrono/Shared/Behaviors/PerformanceBehavior.cs b/src/Chrono/Shared/Behaviors/PerformanceBehavior.cs index 023d9ab..288e9db 100644 --- a/src/Chrono/Shared/Behaviors/PerformanceBehavior.cs +++ b/src/Chrono/Shared/Behaviors/PerformanceBehavior.cs @@ -3,18 +3,14 @@ namespace Chrono.Shared.Behaviors; -public class PerformanceBehavior : IPipelineBehavior where TRequest : notnull +public class PerformanceBehavior(ILogger> logger) + : IPipelineBehavior + where TRequest : notnull { - private readonly ILogger> _logger; - private readonly Stopwatch _timer; + private readonly Stopwatch _timer = new(); - public PerformanceBehavior(ILogger> logger) - { - _timer = new Stopwatch(); - _logger = logger; - } - - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) + public async Task Handle(TRequest request, RequestHandlerDelegate next, + CancellationToken cancellationToken) { _timer.Start(); @@ -26,7 +22,7 @@ public async Task Handle(TRequest request, RequestHandlerDelegate : IPipelineBehavior +public class ValidationBehavior(IEnumerable> validators) + : IPipelineBehavior where TRequest : notnull { - private readonly IEnumerable> _validators; - - public ValidationBehavior(IEnumerable> validators) - { - _validators = validators; - } - - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) + public async Task Handle(TRequest request, RequestHandlerDelegate next, + CancellationToken cancellationToken) { - if (!_validators.Any()) + if (!validators.Any()) { return await next(); } @@ -23,15 +18,15 @@ public async Task Handle(TRequest request, RequestHandlerDelegate(request); var validationResults = await Task.WhenAll( - _validators.Select(v => + validators.Select(v => v.ValidateAsync(context, cancellationToken))); var failures = validationResults - .Where(r => r.Errors.Any()) + .Where(r => r.Errors.Count != 0) .SelectMany(r => r.Errors) .ToList(); - if (failures.Any()) + if (failures.Count != 0) { throw new ValidationException(failures); } diff --git a/src/Chrono/Shared/Exceptions/ForbiddenAccessException.cs b/src/Chrono/Shared/Exceptions/ForbiddenAccessException.cs index 9189eac..4899add 100644 --- a/src/Chrono/Shared/Exceptions/ForbiddenAccessException.cs +++ b/src/Chrono/Shared/Exceptions/ForbiddenAccessException.cs @@ -1,5 +1,3 @@ namespace Chrono.Shared.Exceptions; -public class ForbiddenAccessException : Exception -{ -} +public class ForbiddenAccessException : Exception; diff --git a/src/Chrono/Shared/Exceptions/NotFoundException.cs b/src/Chrono/Shared/Exceptions/NotFoundException.cs index c1cb2d8..6b7650f 100644 --- a/src/Chrono/Shared/Exceptions/NotFoundException.cs +++ b/src/Chrono/Shared/Exceptions/NotFoundException.cs @@ -1,9 +1,3 @@ namespace Chrono.Shared.Exceptions; -public class NotFoundException : Exception -{ - public NotFoundException(string message) - : base(message) - { - } -} +public class NotFoundException(string message) : Exception(message); diff --git a/src/Chrono/Shared/Extensions/TaskListExtensions.cs b/src/Chrono/Shared/Extensions/TaskListExtensions.cs index 177f7ed..94482d6 100644 --- a/src/Chrono/Shared/Extensions/TaskListExtensions.cs +++ b/src/Chrono/Shared/Extensions/TaskListExtensions.cs @@ -7,10 +7,7 @@ public static class TaskListExtensions { public static void ReorderTaskPositions(this TaskList taskList) { - if (taskList == null) - { - throw new ArgumentNullException(nameof(taskList)); - } + ArgumentNullException.ThrowIfNull(taskList); var allTasks = taskList.Tasks .OrderBy(x => x.Position) diff --git a/src/Chrono/Shared/Services/CurrentUserService.cs b/src/Chrono/Shared/Services/CurrentUserService.cs index 92da80c..683c24a 100644 --- a/src/Chrono/Shared/Services/CurrentUserService.cs +++ b/src/Chrono/Shared/Services/CurrentUserService.cs @@ -2,17 +2,10 @@ namespace Chrono.Shared.Services; -public class CurrentUserService : ICurrentUserService +public class CurrentUserService(IHttpContextAccessor httpContextAccessor) : ICurrentUserService { - private readonly IHttpContextAccessor _httpContextAccessor; + public string UserId => httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier); + public string UserName => httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.Name) ?? "Visitor"; - public CurrentUserService(IHttpContextAccessor httpContextAccessor) - { - _httpContextAccessor = httpContextAccessor; - } - - public string UserId => _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier); - public string UserName => _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.Name) ?? "Visitor"; - - public bool IsAuthenticated => _httpContextAccessor.HttpContext?.User.Identity?.IsAuthenticated ?? false; + public bool IsAuthenticated => httpContextAccessor.HttpContext?.User.Identity?.IsAuthenticated ?? false; } diff --git a/src/Chrono/Shared/Services/TextService.cs b/src/Chrono/Shared/Services/TextService.cs index 8c4afbc..b4fc2a5 100644 --- a/src/Chrono/Shared/Services/TextService.cs +++ b/src/Chrono/Shared/Services/TextService.cs @@ -1,8 +1,8 @@ namespace Chrono.Shared.Services; -public class TextService +public static class TextService { - public string Truncate(string text, int length) + public static string Truncate(string text, int length) { if (string.IsNullOrEmpty(text) || text.Length <= length) {