-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
461 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
src/Api/Endpoints/Preferences/UpdatePreferencesEndpoint.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using Api.Mappers.UserPreferences; | ||
using Api.Models.Requests.UserPreferences; | ||
using Api.Models.Responses; | ||
using Core.Abstractions; | ||
using FastEndpoints; | ||
|
||
namespace Api.Endpoints.Preferences; | ||
|
||
public class UpdatePreferencesEndpoint(IUserPreferencesService userPreferencesService) : | ||
Endpoint<UpdateUserPreferencesRequest, ApiResponse, UpdateUserPreferencesMapper> | ||
{ | ||
private readonly IUserPreferencesService _preferencesService = userPreferencesService; | ||
|
||
public override void Configure() | ||
{ | ||
Verbs(Http.PUT); | ||
Routes("api/preferences"); | ||
} | ||
|
||
public override async Task HandleAsync(UpdateUserPreferencesRequest req, CancellationToken ct) | ||
{ | ||
var dto = Map.ToEntity(req).Value; | ||
var result = await _preferencesService.UpdateUserPreferences(dto, ct); | ||
|
||
var apiResponse = Map.FromEntity(result); | ||
await SendAsync(apiResponse, cancellation: ct); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
src/Api/Mappers/UserPreferences/UpdateUserPreferencesMapper.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using Api.Extensions; | ||
using Api.Models.Requests.UserPreferences; | ||
using Api.Models.Responses; | ||
using Core.Models.UserPreferences; | ||
using ErrorOr; | ||
using FastEndpoints; | ||
|
||
namespace Api.Mappers.UserPreferences; | ||
|
||
public class UpdateUserPreferencesMapper | ||
: Mapper<UpdateUserPreferencesRequest, ApiResponse, ErrorOr<UserPreferencesDto>> | ||
{ | ||
public override ErrorOr<UserPreferencesDto> ToEntity(UpdateUserPreferencesRequest r) | ||
{ | ||
return new UserPreferencesDto | ||
{ | ||
UserId = r.UserId, | ||
Channels = r.Channels.ToDictionary( | ||
kvp => kvp.Key, | ||
kvp => new ChannelDescriptorBaseDto | ||
{ | ||
Enabled = kvp.Value.Enabled, | ||
Description = kvp.Value.Description, | ||
Metadata = kvp.Value.Metadata | ||
}) | ||
}; | ||
} | ||
|
||
public override ApiResponse FromEntity(ErrorOr<UserPreferencesDto> e) | ||
{ | ||
if (e.IsError) | ||
{ | ||
var problemDetails = new ProblemDetails | ||
{ | ||
Errors = e.ToProblemDetailsErrors() | ||
}; | ||
|
||
return ApiResponse.Fail(problemDetails); | ||
} | ||
|
||
return ApiResponse.Success(); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/Api/Models/Requests/UserPreferences/ChannelDescriptorBaseRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Api.Models.Requests.UserPreferences; | ||
|
||
public record ChannelDescriptorBaseRequest | ||
{ | ||
public bool Enabled { get; init; } | ||
public string? Description { get; init; } | ||
public Dictionary<string, string>? Metadata { get; init; } | ||
} |
7 changes: 7 additions & 0 deletions
7
src/Api/Models/Requests/UserPreferences/UpdateUserPreferencesRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Api.Models.Requests.UserPreferences; | ||
|
||
public class UpdateUserPreferencesRequest | ||
{ | ||
public required string UserId { get; set; } | ||
public required Dictionary<string, ChannelDescriptorBaseRequest> Channels { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Core.Models.UserPreferences; | ||
using ErrorOr; | ||
|
||
namespace Core.Abstractions; | ||
|
||
public interface IUserPreferencesService | ||
{ | ||
Task<ErrorOr<UserPreferencesDto>> CreateUserPreferences(string userId, CancellationToken ct); | ||
Task<ErrorOr<UserPreferencesDto>> UpdateUserPreferences( | ||
UserPreferencesDto userPreferences, CancellationToken ct); | ||
Task<ErrorOr<ChannelDescriptorBaseDto>> GetChannelDeliveryInfo( | ||
string recipientUserId, string channel, CancellationToken ct); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using Core.Models.UserPreferences; | ||
using ErrorOr; | ||
|
||
namespace Core.Errors; | ||
|
||
public static class UserPreferencesErrors | ||
{ | ||
internal static ErrorOr<UserPreferencesDto> FailedToCreate | ||
=> Error.Unexpected("UserPreferences.CreateFailed", "Failed to create user preferences"); | ||
|
||
internal static ErrorOr<UserPreferencesDto> FailedToUpdate | ||
=> Error.Unexpected("UserPreferences.CreateUpdate", "Failed to update user preferences"); | ||
|
||
internal static ErrorOr<UserPreferencesDto> NotFound | ||
=> Error.NotFound("UserPreferences.NotFound", "User preferences not found"); | ||
|
||
internal static ErrorOr<ChannelDescriptorBaseDto> ChannelNotFound | ||
=> Error.NotFound("UserPreferences.Channel.NotFound", "User preferences for channel not found"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System.Globalization; | ||
using System.Text; | ||
|
||
namespace Core.Extensions; | ||
|
||
public static class StringExtensions | ||
{ | ||
public static string ToPascalCase(this string text) | ||
{ | ||
if (text.Length < 1) | ||
return text; | ||
|
||
var words = text.Split(new[] { ' ', '-', '_', '.' }, StringSplitOptions.RemoveEmptyEntries); | ||
|
||
var sb = new StringBuilder(); | ||
|
||
foreach (var word in words) | ||
{ | ||
if (word.Length > 0) | ||
{ | ||
sb.Append(CultureInfo.InvariantCulture.TextInfo.ToTitleCase(word.ToLowerInvariant())); | ||
} | ||
} | ||
|
||
return sb.ToString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using Core.Extensions; | ||
using Core.Models.UserPreferences; | ||
using Infrastructure.Persistence.Mongo.Entities.Preferences; | ||
using MongoDB.Bson; | ||
|
||
namespace Core.Mappers; | ||
|
||
public static class UserPreferencesChannelMapper | ||
{ | ||
public static ChannelDescriptorBaseDto ToDto(ChannelDescriptorBase e) | ||
{ | ||
return new ChannelDescriptorBaseDto | ||
{ | ||
Enabled = e.Enabled, | ||
Description = e.Description, | ||
Metadata = e.Metadata | ||
}; | ||
} | ||
|
||
public static ChannelDescriptorBase ToEntity(ChannelDescriptorBaseDto dto) | ||
{ | ||
return new ChannelDescriptorBase | ||
{ | ||
Enabled = dto.Enabled, | ||
Description = dto.Description, | ||
Metadata = dto.Metadata | ||
}; | ||
} | ||
} | ||
|
||
public static class UserPreferencesMapper | ||
{ | ||
internal static UserPreferencesDto ToDto(UserPreferences e) | ||
{ | ||
return new UserPreferencesDto | ||
{ | ||
Id = e.Id.ToString(), | ||
UserId = e.UserId, | ||
Channels = e.Channels.ToDictionary(x => x.Key, d => UserPreferencesChannelMapper.ToDto(d.Value)) | ||
}; | ||
} | ||
|
||
public static UserPreferences UpdateEntity(UserPreferences e, UserPreferencesDto dto) | ||
{ | ||
var channels = e.Channels; | ||
foreach (var ch in dto.Channels) | ||
{ | ||
var metadataKeys = ch.Value.Metadata?.Keys.ToArray()!; | ||
foreach (var mk in metadataKeys) | ||
{ | ||
var normalized = mk.ToPascalCase(); | ||
|
||
if (!mk.Equals(normalized)) | ||
{ | ||
ch.Value.Metadata![normalized] = ch.Value.Metadata[mk]; | ||
ch.Value.Metadata.Remove(mk); | ||
} | ||
} | ||
|
||
var normalizedKey = ch.Key.ToPascalCase(); | ||
if (channels.TryGetValue(normalizedKey, out var channel)) | ||
{ | ||
channel.Enabled = ch.Value.Enabled; | ||
channel.Description = ch.Value.Description; | ||
channel.Metadata = ch.Value.Metadata; | ||
} | ||
else | ||
{ | ||
channels.Add(normalizedKey, new ChannelDescriptorBase | ||
{ | ||
Enabled = ch.Value.Enabled, | ||
Description = ch.Value.Description, | ||
Metadata = ch.Value.Metadata | ||
}); | ||
} | ||
} | ||
|
||
return e with { LastUpdated = DateTimeOffset.UtcNow, Channels = channels }; | ||
} | ||
|
||
public static UserPreferences ToEntity(UserPreferencesDto dto) | ||
{ | ||
var id = string.IsNullOrEmpty(dto.Id) | ||
? ObjectId.GenerateNewId() | ||
: ObjectId.Parse(dto.Id); | ||
|
||
return new UserPreferences | ||
{ | ||
Id = id, | ||
UserId = dto.UserId, | ||
Channels = dto.Channels.ToDictionary(x => x.Key, d => UserPreferencesChannelMapper.ToEntity(d.Value)), | ||
LastUpdated = DateTimeOffset.UtcNow | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Core.Models.UserPreferences; | ||
|
||
public record ChannelDescriptorBaseDto | ||
{ | ||
public bool Enabled { get; init; } | ||
public string? Description { get; init; } | ||
public Dictionary<string, string>? Metadata { get; init; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Core.Models.UserPreferences; | ||
|
||
public record UserPreferencesDto | ||
{ | ||
public string? Id { get; init; } | ||
public required string UserId { get; init; } | ||
public required Dictionary<string, ChannelDescriptorBaseDto> Channels { get; init; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.