Skip to content

Commit

Permalink
feat: Added the option to set a default task list. (#24)
Browse files Browse the repository at this point in the history
* feat: Added the option to set a default task list.

* feat: Minor optimizations.
  • Loading branch information
philipp-meier committed Sep 2, 2023
1 parent 86ee9f3 commit ad21adc
Show file tree
Hide file tree
Showing 26 changed files with 1,108 additions and 73 deletions.
1 change: 1 addition & 0 deletions src/Application/Common/Interfaces/IApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public interface IApplicationDbContext
DbSet<Category> Categories { get; }
DbSet<TaskCategory> TaskCategories { get; }
DbSet<User> Users { get; }
DbSet<UserSettings> UserSettings { get; }

Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
1 change: 1 addition & 0 deletions src/Application/Entities/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ public class User : BaseEntity
{
public string UserId { get; set; }
public string Name { get; set; }
public UserSettings UserSettings { get; set; }
}
11 changes: 11 additions & 0 deletions src/Application/Entities/UserSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Chrono.Application.Entities.Common;

namespace Chrono.Application.Entities;

public class UserSettings : BaseEntity
{
public int UserId { get; set; }
public User User { get; set; }

public TaskList DefaultTaskList { get; set; }
}
39 changes: 39 additions & 0 deletions src/Application/Features/User/GetUserSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Chrono.Application.Common.Exceptions;
using Chrono.Application.Common.Interfaces;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Chrono.Application.Features.User;

public record GetUserSettings : IRequest<UserSettingsDto>;

public class GetUserSettingsHandler : IRequestHandler<GetUserSettings, UserSettingsDto>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUserService;

public GetUserSettingsHandler(IApplicationDbContext context, ICurrentUserService currentUserService)
{
_context = context;
_currentUserService = currentUserService;
}

public async Task<UserSettingsDto> Handle(GetUserSettings request, CancellationToken cancellationToken)
{
var currentUser = await _context.Users
.Include(x => x.UserSettings)
.SingleOrDefaultAsync(x => x.UserId == _currentUserService.UserId, cancellationToken);

if (currentUser == null)
{
throw new NotFoundException($"User \"{_currentUserService.UserId}\" not found.");
}

return new UserSettingsDto { DefaultTaskListId = currentUser.UserSettings?.DefaultTaskList?.Id };
}
}

public class UserSettingsDto
{
public int? DefaultTaskListId { get; init; }
}
70 changes: 70 additions & 0 deletions src/Application/Features/User/UpdateUserSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Chrono.Application.Common.Exceptions;
using Chrono.Application.Common.Extensions;
using Chrono.Application.Common.Interfaces;
using Chrono.Application.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Task = System.Threading.Tasks.Task;

namespace Chrono.Application.Features.User;

public record UpdateUserSettings : IRequest
{
public int? DefaultTaskListId { get; init; }
}

public class UpdateUserSettingsHandler : IRequestHandler<UpdateUserSettings>
{
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
.Include(x => x.UserSettings)
.SingleOrDefaultAsync(x => x.UserId == _currentUserService.UserId, cancellationToken);

if (currentUser == null)
{
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);
}

if (request.DefaultTaskListId.HasValue)
{
var defaultTaskListId = request.DefaultTaskListId.Value;
var taskList = await _context.TaskLists
.SingleOrDefaultAsync(x => x.Id == defaultTaskListId, cancellationToken);

if (taskList == null)
{
throw new NotFoundException($"Task list \"{defaultTaskListId}\" not found.");
}

if (!taskList.IsPermitted(_currentUserService.UserId))
{
throw new ForbiddenAccessException();
}

userSettings.DefaultTaskList = taskList;
}
else
{
userSettings.DefaultTaskList = null;
}

await _context.SaveChangesAsync(cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,12 @@ public void Configure(EntityTypeBuilder<User> builder)

builder.Property(x => x.Name)
.IsRequired();

builder.HasOne(x => x.UserSettings)
.WithOne(x => x.User)
.HasPrincipalKey<User>(x => x.Id)
.HasForeignKey<UserSettings>(x => x.UserId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired(false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Chrono.Application.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Chrono.Application.Infrastructure.Configurations;

public class UserSettingsConfiguration : IEntityTypeConfiguration<UserSettings>
{
public void Configure(EntityTypeBuilder<UserSettings> builder)
{
builder.Navigation(x => x.DefaultTaskList)
.AutoInclude();
}
}
Loading

0 comments on commit ad21adc

Please sign in to comment.