diff --git a/.editorconfig b/.editorconfig index 3d5299a..ab266d2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,23 +1,118 @@ root = true -# EditorConfig is awesome: https://EditorConfig.org -# top-most EditorConfig file - -# Unix-style newlines with a newline ending every file [*] charset = utf-8 end_of_line = lf max_line_length = 120 insert_final_newline = true -trim_trailing_whitespace = false +trim_trailing_whitespace = true indent_style = space indent_size = 4 +# Microsoft .NET properties +csharp_preferred_modifier_order = public, protected, internal, private, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion +csharp_style_expression_bodied_accessors = true:suggestion +csharp_style_expression_bodied_constructors = true:suggestion +csharp_style_expression_bodied_methods = true:suggestion +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_namespace_declarations = file_scoped:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_var_elsewhere = true:suggestion +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:suggestion +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion +dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion + +# ReSharper properties +resharper_align_multiline_binary_expressions_chain = false +resharper_align_multiline_statement_conditions = false +resharper_braces_for_ifelse = not_required_for_both +resharper_braces_for_lock = required_for_multiline +resharper_braces_for_using = required_for_multiline +resharper_braces_for_for = required_for_multiline +resharper_braces_for_foreach = required_for_multiline +resharper_braces_for_dowhile = required_for_multiline +resharper_braces_for_while = required_for_multiline +resharper_braces_for_fixed = required_for_multiline +resharper_builtin_type_apply_to_native_integer = true +resharper_csharp_int_align_fix_in_adjacent = false +resharper_csharp_keep_blank_lines_in_code = 1 +resharper_csharp_keep_blank_lines_in_declarations = 1 +resharper_csharp_max_enum_members_on_line = 1 +resharper_csharp_wrap_before_binary_opsign = true +resharper_csharp_wrap_before_first_type_parameter_constraint = true +resharper_csharp_wrap_extends_list_style = chop_always +resharper_enforce_line_ending_style = true +resharper_force_attribute_style = join +resharper_int_align_methods = true +resharper_keep_existing_embedded_arrangement = false +resharper_keep_existing_expr_member_arrangement = false +resharper_keep_existing_initializer_arrangement = false +resharper_keep_existing_primary_constructor_declaration_parens_arrangement = true +resharper_keep_existing_property_patterns_arrangement = false +resharper_keep_existing_switch_expression_arrangement = false +resharper_local_function_body = expression_body +resharper_max_attribute_length_for_same_line = 120 +resharper_new_line_before_while = true +resharper_place_accessorholder_attribute_on_same_line = false +resharper_place_accessor_attribute_on_same_line = true +resharper_place_expr_accessor_on_single_line = true +resharper_place_expr_method_on_single_line = false +resharper_place_expr_property_on_single_line = false +resharper_place_field_attribute_on_same_line = false +resharper_place_record_field_attribute_on_same_line = true +resharper_place_simple_accessor_on_single_line = false +resharper_place_simple_embedded_statement_on_same_line = false +resharper_place_simple_initializer_on_single_line = false +resharper_show_autodetect_configure_formatting_tip = false +resharper_static_members_qualify_with = current_type +resharper_use_indent_from_vs = false +resharper_wrap_array_initializer_style = chop_always +resharper_wrap_before_primary_constructor_declaration_lpar = false +resharper_wrap_before_primary_constructor_declaration_rpar = true +resharper_wrap_for_stmt_header_style = wrap_if_long +resharper_wrap_lines = true +resharper_wrap_linq_expressions = chop_always +resharper_wrap_list_pattern = chop_always +resharper_wrap_object_and_collection_initializer_style = chop_always + +# ReSharper inspection severities +resharper_arrange_attributes_highlighting = suggestion +resharper_arrange_default_value_when_type_not_evident_highlighting = suggestion +resharper_arrange_local_function_body_highlighting = suggestion +resharper_arrange_null_checking_pattern_highlighting = suggestion +resharper_arrange_object_creation_when_type_not_evident_highlighting = suggestion +resharper_arrange_redundant_parentheses_highlighting = suggestion +resharper_convert_closure_to_method_group_highlighting = none +resharper_convert_to_primary_constructor_highlighting = none +resharper_enforce_do_while_statement_braces_highlighting = suggestion +resharper_enforce_fixed_statement_braces_highlighting = suggestion +resharper_enforce_foreach_statement_braces_highlighting = suggestion +resharper_enforce_for_statement_braces_highlighting = suggestion +resharper_enforce_if_statement_braces_highlighting = suggestion +resharper_enforce_lock_statement_braces_highlighting = suggestion +resharper_enforce_using_statement_braces_highlighting = suggestion +resharper_enforce_while_statement_braces_highlighting = suggestion +resharper_razor_assembly_not_resolved_highlighting = warning +resharper_remove_redundant_braces_highlighting = suggestion +resharper_suggest_discard_declaration_var_style_highlighting = suggestion +resharper_web_config_module_not_resolved_highlighting = warning +resharper_web_config_type_not_resolved_highlighting = warning +resharper_web_config_wrong_module_highlighting = warning + [*.{cs,vb}] dotnet_sort_system_directives_first = true dotnet_style_null_propagation = true:warning dotnet_style_prefer_auto_properties = true:warning -dotnet_style_coalesce_expression = true:suggestion +dotnet_style_coalesce_expression = true:warning # XML project files [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] diff --git a/src/People.Api/Application/Commands/ConfirmEmail/ConfirmEmailCommand.cs b/src/People.Api/Application/Commands/ConfirmEmail/ConfirmEmailCommand.cs index c8595eb..04fb101 100644 --- a/src/People.Api/Application/Commands/ConfirmEmail/ConfirmEmailCommand.cs +++ b/src/People.Api/Application/Commands/ConfirmEmail/ConfirmEmailCommand.cs @@ -27,7 +27,7 @@ public async Task Handle(ConfirmEmailCommand request, Cancellation var confirmation = await _confirmation.VerifyEmailAsync(request.Token, request.Code, ct); var account = await _repository.GetAsync(confirmation.AccountId, ct) - ?? throw AccountException.NotFound(confirmation.AccountId); + ?? throw AccountException.NotFound(confirmation.AccountId); account.ConfirmEmail(confirmation.Email, _timeProvider); diff --git a/src/People.Api/Application/Commands/SignInByGoogle/SignInByGoogleCommand.cs b/src/People.Api/Application/Commands/SignInByGoogle/SignInByGoogleCommand.cs index 573e474..5effc0c 100644 --- a/src/People.Api/Application/Commands/SignInByGoogle/SignInByGoogleCommand.cs +++ b/src/People.Api/Application/Commands/SignInByGoogle/SignInByGoogleCommand.cs @@ -35,11 +35,11 @@ public async Task Handle(SignInByGoogleCommand request, Cancellati var google = await _google.GetAsync(request.Token, ct); var result = await _dbContext.Accounts - .AsNoTracking() - .WhereGoogle(google.Identity) - .Select(x => new SignInResult(x.Id, x.Name.FullName())) - .FirstOrDefaultAsync(ct) - ?? throw ExternalAccountException.NotFound(ExternalService.Google, google.Identity); + .AsNoTracking() + .WhereGoogle(google.Identity) + .Select(x => new SignInResult(x.Id, x.Name.FullName())) + .FirstOrDefaultAsync(ct) + ?? throw ExternalAccountException.NotFound(ExternalService.Google, google.Identity); var evt = new AccountActivity.LoggedInIntegrationEvent(Guid.NewGuid(), _timeProvider.UtcNow(), result.Id); await _bus.PublishAsync(evt, ct); diff --git a/src/People.Api/Application/Commands/SignInByMicrosoft/SignInByMicrosoftCommand.cs b/src/People.Api/Application/Commands/SignInByMicrosoft/SignInByMicrosoftCommand.cs index 59a30b4..dee4d9b 100644 --- a/src/People.Api/Application/Commands/SignInByMicrosoft/SignInByMicrosoftCommand.cs +++ b/src/People.Api/Application/Commands/SignInByMicrosoft/SignInByMicrosoftCommand.cs @@ -35,11 +35,11 @@ public async Task Handle(SignInByMicrosoftCommand request, Cancell var microsoft = await _microsoft.GetAsync(request.Token, ct); var result = await _dbContext.Accounts - .AsNoTracking() - .WhereMicrosoft(microsoft.Identity) - .Select(x => new SignInResult(x.Id, x.Name.FullName())) - .FirstOrDefaultAsync(ct) - ?? throw ExternalAccountException.NotFound(ExternalService.Microsoft, microsoft.Identity); + .AsNoTracking() + .WhereMicrosoft(microsoft.Identity) + .Select(x => new SignInResult(x.Id, x.Name.FullName())) + .FirstOrDefaultAsync(ct) + ?? throw ExternalAccountException.NotFound(ExternalService.Microsoft, microsoft.Identity); var evt = new AccountActivity.LoggedInIntegrationEvent(Guid.NewGuid(), _timeProvider.UtcNow(), result.Id); await _bus.PublishAsync(evt, ct); diff --git a/src/People.Api/Application/Commands/SigningInByEmail/SigningInByEmailCommand.cs b/src/People.Api/Application/Commands/SigningInByEmail/SigningInByEmailCommand.cs index e094229..189a3c4 100644 --- a/src/People.Api/Application/Commands/SigningInByEmail/SigningInByEmailCommand.cs +++ b/src/People.Api/Application/Commands/SigningInByEmail/SigningInByEmailCommand.cs @@ -29,7 +29,12 @@ public async Task Handle(SigningInByEmailCommand request, CancellationTo { var email = await _dbContext.Emails .Where(x => x.Email == request.Email.Address) - .Select(x => new { x.AccountId, Email = new MailAddress(x.Email), x.IsConfirmed }) + .Select(x => new + { + x.AccountId, + Email = new MailAddress(x.Email), + x.IsConfirmed + }) .FirstOrDefaultAsync(ct) ?? throw EmailException.NotFound(request.Email); if (!email.IsConfirmed) diff --git a/src/People.Api/Application/Commands/SigningUpByEmail/SigningUpByEmailCommand.cs b/src/People.Api/Application/Commands/SigningUpByEmail/SigningUpByEmailCommand.cs index a713200..4148d95 100644 --- a/src/People.Api/Application/Commands/SigningUpByEmail/SigningUpByEmailCommand.cs +++ b/src/People.Api/Application/Commands/SigningUpByEmail/SigningUpByEmailCommand.cs @@ -40,7 +40,12 @@ public async Task Handle(SigningUpByEmailCommand request, CancellationTo { var email = await _dbContext.Emails .Where(x => x.Email == request.Email.Address) - .Select(x => new { x.AccountId, Email = new MailAddress(x.Email), x.IsConfirmed }) + .Select(x => new + { + x.AccountId, + Email = new MailAddress(x.Email), + x.IsConfirmed + }) .FirstOrDefaultAsync(ct); if (email is not null) diff --git a/src/People.Api/Application/Queries/IsAccountActive/IsAccountActiveQuery.cs b/src/People.Api/Application/Queries/IsAccountActive/IsAccountActiveQuery.cs index c6dd63c..03be977 100644 --- a/src/People.Api/Application/Queries/IsAccountActive/IsAccountActiveQuery.cs +++ b/src/People.Api/Application/Queries/IsAccountActive/IsAccountActiveQuery.cs @@ -27,7 +27,11 @@ public async Task Handle(IsAccountActiveQuery request, CancellationToken c { var data = await _dataProvider .Sql($"SELECT is_activated, ban IS NOT NULL FROM accounts WHERE id = {request.Id} LIMIT 1") - .Select(x => new { IsActivated = x.GetBoolean(0), IsBanned = x.GetBoolean(1) }) + .Select(x => new + { + IsActivated = x.GetBoolean(0), + IsBanned = x.GetBoolean(1) + }) .FirstOrDefaultAsync(ct); if (data is null) diff --git a/src/People.Api/Dockerfile b/src/People.Api/Dockerfile index 24d31a1..e42367f 100644 --- a/src/People.Api/Dockerfile +++ b/src/People.Api/Dockerfile @@ -1,7 +1,7 @@ -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR / COPY "src" "src/" WORKDIR /src/People.Api diff --git a/src/People.Api/Endpoints/Account/Requests/UpdateRequest.cs b/src/People.Api/Endpoints/Account/Requests/UpdateRequest.cs index 71decab..08c5410 100644 --- a/src/People.Api/Endpoints/Account/Requests/UpdateRequest.cs +++ b/src/People.Api/Endpoints/Account/Requests/UpdateRequest.cs @@ -15,7 +15,8 @@ internal sealed record UpdateRequest( string TimeZone, string DateFormat, string TimeFormat, - DayOfWeek StartOfWeek) + DayOfWeek StartOfWeek +) { public UpdateAccountCommand ToCommand(AccountId id) => new( diff --git a/src/People.Api/Grpc/PeopleService.cs b/src/People.Api/Grpc/PeopleService.cs index c653773..b937516 100644 --- a/src/People.Api/Grpc/PeopleService.cs +++ b/src/People.Api/Grpc/PeopleService.cs @@ -37,7 +37,10 @@ public override async Task IsAccountActive(AccountRequest request, Se var query = new IsAccountActiveQuery(request.Id); var result = await _mediator.Send(query, context.CancellationToken); - return new BoolValue { Value = result }; + return new BoolValue + { + Value = result + }; } public override async Task SigningUpByEmail(EmailSigningUpRequest request, diff --git a/src/People.Api/Infrastructure/ErrorFactory.cs b/src/People.Api/Infrastructure/ErrorFactory.cs index 1a2f743..e54185e 100644 --- a/src/People.Api/Infrastructure/ErrorFactory.cs +++ b/src/People.Api/Infrastructure/ErrorFactory.cs @@ -22,7 +22,10 @@ public static ValidationProblemDetails ToProblem(this ValidationException ex) => ValidationProblemDetails(GetValidationErrors(ex)); private static ValidationProblemDetails ToProblem(this ArgumentException ex) => - ValidationProblemDetails(new Dictionary { [ex.ParamName ?? "@"] = new[] { ex.Message } }); + ValidationProblemDetails(new Dictionary + { + [ex.ParamName ?? "@"] = [ex.Message] + }); private static ProblemDetails ToProblem(this PeopleException exception) { diff --git a/src/People.Api/Infrastructure/GlobalExceptionHandler.cs b/src/People.Api/Infrastructure/GlobalExceptionHandler.cs index 9ee353d..69b7a16 100644 --- a/src/People.Api/Infrastructure/GlobalExceptionHandler.cs +++ b/src/People.Api/Infrastructure/GlobalExceptionHandler.cs @@ -8,10 +8,8 @@ public sealed class GlobalExceptionHandler : IExceptionHandler { private readonly ILogger _logger; - public GlobalExceptionHandler(ILogger logger) - { + public GlobalExceptionHandler(ILogger logger) => _logger = logger; - } public async ValueTask TryHandleAsync(HttpContext context, Exception exception, CancellationToken ct) { diff --git a/src/People.Api/Infrastructure/Interceptors/GrpcExceptionInterceptor.cs b/src/People.Api/Infrastructure/Interceptors/GrpcExceptionInterceptor.cs index 85532b9..e79162f 100644 --- a/src/People.Api/Infrastructure/Interceptors/GrpcExceptionInterceptor.cs +++ b/src/People.Api/Infrastructure/Interceptors/GrpcExceptionInterceptor.cs @@ -50,8 +50,12 @@ private RpcException WrapPeopleException(ServerCallContext context, PeopleExcept var meta = new Metadata { - { "ex-name", ex.Name }, - { "ex-code", ex.Code }, + { + "ex-name", ex.Name + }, + { + "ex-code", ex.Code + }, { "ex-id", ex switch { @@ -73,8 +77,12 @@ private RpcException WrapValidationException(ServerCallContext context, Validati var meta = new Metadata { - { "ex-name", name }, - { "ex-code", "InvalidModel" } + { + "ex-name", name + }, + { + "ex-code", "InvalidModel" + } }; var result = ex.Errors.GroupBy(x => x.PropertyName) @@ -93,9 +101,15 @@ private RpcException WrapArgumentExceptions(ServerCallContext context, ArgumentE var meta = new Metadata { - { "ex-name", name }, - { "ex-code", "InvalidModel" }, - { $"ex-field-{ex.ParamName}", ex.Message } + { + "ex-name", name + }, + { + "ex-code", "InvalidModel" + }, + { + $"ex-field-{ex.ParamName}", ex.Message + } }; throw new RpcException(new Status(StatusCode.InvalidArgument, ex.Message), meta); @@ -108,8 +122,12 @@ private RpcException WrapUnhandledException(ServerCallContext context, Exception var meta = new Metadata { - { "ex-name", name }, - { "ex-code", "Unhandled" } + { + "ex-name", name + }, + { + "ex-code", "Unhandled" + } }; throw new RpcException(new Status(StatusCode.Internal, ex.Message), meta); diff --git a/src/People.Api/Infrastructure/Notifications/NotificationSender.cs b/src/People.Api/Infrastructure/Notifications/NotificationSender.cs index f136ce3..8277674 100644 --- a/src/People.Api/Infrastructure/Notifications/NotificationSender.cs +++ b/src/People.Api/Infrastructure/Notifications/NotificationSender.cs @@ -22,7 +22,12 @@ public async Task SendConfirmationAsync(MailAddress email, string code, Language var template = $"Confirmation.{language}.liquid"; var (subject, body) = await _emailBuilder.CreateEmailAsync(template, new ConfirmationCodeModel(code)); - var message = new SendRequest { Email = email.Address, Subject = subject, Body = body }; + var message = new SendRequest + { + Email = email.Address, + Subject = subject, + Body = body + }; await _notification.SendEmailAsync(message, cancellationToken: ct); } } diff --git a/src/People.Api/Infrastructure/Providers/IpApi/IpApiService.cs b/src/People.Api/Infrastructure/Providers/IpApi/IpApiService.cs index 28f634e..fadce21 100644 --- a/src/People.Api/Infrastructure/Providers/IpApi/IpApiService.cs +++ b/src/People.Api/Infrastructure/Providers/IpApi/IpApiService.cs @@ -8,7 +8,10 @@ public sealed class IpApiService : IIpApiService private static readonly JsonSerializerOptions Options = new() { PropertyNameCaseInsensitive = true, - Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } + Converters = + { + new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) + } }; private readonly HttpClient _client; diff --git a/src/People.Api/Messages/AccountReply.cs b/src/People.Api/Messages/AccountReply.cs index 1dd0651..d00a81c 100644 --- a/src/People.Api/Messages/AccountReply.cs +++ b/src/People.Api/Messages/AccountReply.cs @@ -19,7 +19,10 @@ internal static AccountReply Map(AccountSummary account) => TimeZone = account.TimeZone.ToString(), Language = Language.Create(account.Language), Ban = Types.Ban.Map(account.Ban), - Roles = { account.Roles } + Roles = + { + account.Roles + } }; public partial class Types @@ -29,7 +32,11 @@ public partial class Ban public static Ban? Map(Domain.ValueObjects.Ban? ban) => ban switch { - not null => new Ban { Reason = ban.Reason, ExpiresAt = ban.ExpiredAt.ToTimestamp() }, + not null => new Ban + { + Reason = ban.Reason, + ExpiresAt = ban.ExpiredAt.ToTimestamp() + }, _ => null }; } diff --git a/src/People.Api/Messages/EmailSigningInReply.cs b/src/People.Api/Messages/EmailSigningInReply.cs index 0a323f9..4d947a7 100644 --- a/src/People.Api/Messages/EmailSigningInReply.cs +++ b/src/People.Api/Messages/EmailSigningInReply.cs @@ -5,5 +5,8 @@ namespace People.Grpc.People; public partial class EmailSigningInReply { internal static EmailSigningInReply Map(string token) => - new() { Token = token }; + new() + { + Token = token + }; } diff --git a/src/People.Api/Messages/EmailSigningUpReply.cs b/src/People.Api/Messages/EmailSigningUpReply.cs index ca0ec3d..cc89550 100644 --- a/src/People.Api/Messages/EmailSigningUpReply.cs +++ b/src/People.Api/Messages/EmailSigningUpReply.cs @@ -5,5 +5,8 @@ namespace People.Grpc.People; public partial class EmailSigningUpReply { internal static EmailSigningUpReply Map(string token) => - new() { Token = token }; + new() + { + Token = token + }; } diff --git a/src/People.Api/Messages/SignInReply.cs b/src/People.Api/Messages/SignInReply.cs index 73e8f2a..76c380b 100644 --- a/src/People.Api/Messages/SignInReply.cs +++ b/src/People.Api/Messages/SignInReply.cs @@ -6,5 +6,9 @@ namespace People.Grpc.People; public partial class SignInReply { internal static SignInReply Map(SignInResult result) => - new() { Id = result.Id, FullName = result.FullName }; + new() + { + Id = result.Id, + FullName = result.FullName + }; } diff --git a/src/People.Api/Messages/SignUpReply.cs b/src/People.Api/Messages/SignUpReply.cs index 337b39a..8cbb1f8 100644 --- a/src/People.Api/Messages/SignUpReply.cs +++ b/src/People.Api/Messages/SignUpReply.cs @@ -6,5 +6,9 @@ namespace People.Grpc.People; public partial class SignUpReply { internal static SignUpReply Map(SignUpResult result) => - new() { Id = result.Id, FullName = result.FullName }; + new() + { + Id = result.Id, + FullName = result.FullName + }; } diff --git a/src/People.Api/People.Api.csproj b/src/People.Api/People.Api.csproj index 4c191ed..0de76c9 100644 --- a/src/People.Api/People.Api.csproj +++ b/src/People.Api/People.Api.csproj @@ -1,6 +1,6 @@ - net8.0 + net9.0 enable enable @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + diff --git a/src/People.Api/Program.cs b/src/People.Api/Program.cs index 2df62ae..a093633 100644 --- a/src/People.Api/Program.cs +++ b/src/People.Api/Program.cs @@ -81,7 +81,11 @@ options.SupportedUICultures = cultures; options.RequestCultureProviders = new List { - new QueryStringRequestCultureProvider { QueryStringKey = "language", UIQueryStringKey = "language" }, + new QueryStringRequestCultureProvider + { + QueryStringKey = "language", + UIQueryStringKey = "language" + }, new AcceptLanguageHeaderRequestCultureProvider() }; }); @@ -148,14 +152,20 @@ { new MethodConfig { - Names = { MethodName.Default }, + Names = + { + MethodName.Default + }, RetryPolicy = new RetryPolicy { MaxAttempts = 5, InitialBackoff = TimeSpan.FromSeconds(1), MaxBackoff = TimeSpan.FromSeconds(3), BackoffMultiplier = 1, - RetryableStatusCodes = { StatusCode.Unavailable } + RetryableStatusCodes = + { + StatusCode.Unavailable + } } } } @@ -236,8 +246,16 @@ .Destructure.AsScalar() .Destructure.AsScalar() .Destructure.AsScalar() - .Destructure.ByTransforming(x => new { x.Id, x.Name.Nickname }) - .Destructure.ByTransforming(x => new { x.Id, x.Name.Nickname }) + .Destructure.ByTransforming(x => new + { + x.Id, + x.Name.Nickname + }) + .Destructure.ByTransforming(x => new + { + x.Id, + x.Name.Nickname + }) .ReadFrom.Configuration(context.Configuration) ); diff --git a/src/People.Domain/Entities/EmailAccount.cs b/src/People.Domain/Entities/EmailAccount.cs index c393c91..eff8849 100644 --- a/src/People.Domain/Entities/EmailAccount.cs +++ b/src/People.Domain/Entities/EmailAccount.cs @@ -4,14 +4,14 @@ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Local namespace People.Domain.Entities; -public sealed class EmailAccount : Entity +public sealed class EmailAccount : Entity { private DateTime? _confirmedAt; private DateTime _createdAt; public EmailAccount(AccountId accountId, string email, bool isPrimary, DateTime? confirmedAt, DateTime createdAt) { - Id = Ulid.NewUlid(); + Id = Guid.CreateVersion7(); AccountId = accountId; Email = email; IsPrimary = isPrimary; diff --git a/src/People.Domain/Entities/ExternalConnection.cs b/src/People.Domain/Entities/ExternalConnection.cs index b627f42..73ed4e5 100644 --- a/src/People.Domain/Entities/ExternalConnection.cs +++ b/src/People.Domain/Entities/ExternalConnection.cs @@ -4,7 +4,7 @@ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Local namespace People.Domain.Entities; -public sealed class ExternalConnection : Entity +public sealed class ExternalConnection : Entity { private DateTime _createdAt; @@ -16,7 +16,7 @@ private ExternalConnection( DateTime createdAt ) { - Id = Ulid.NewUlid(); + Id = Guid.CreateVersion7(); Type = type; Identity = identity; FirstName = firstName; diff --git a/src/People.Domain/Exceptions/AccountException.cs b/src/People.Domain/Exceptions/AccountException.cs index 9ab372c..200cf09 100644 --- a/src/People.Domain/Exceptions/AccountException.cs +++ b/src/People.Domain/Exceptions/AccountException.cs @@ -14,5 +14,5 @@ public static AccountException NotFound(AccountId id) => new(nameof(NotFound), id, $"Account '{id}' not found"); public static AccountException PrimaryEmailCannotBeRemoved(AccountId id) => - new(nameof(PrimaryEmailCannotBeRemoved), id, $"Primary email for account {id} cannot be removed"); + new(nameof(PrimaryEmailCannotBeRemoved), id, $"The primary email address for account {id} cannot be removed"); } diff --git a/src/People.Domain/People.Domain.csproj b/src/People.Domain/People.Domain.csproj index 1c84627..940e374 100644 --- a/src/People.Domain/People.Domain.csproj +++ b/src/People.Domain/People.Domain.csproj @@ -1,11 +1,10 @@ - net8.0 + net9.0 enable enable - - + diff --git a/src/People.Domain/ValueObjects/DateFormat.cs b/src/People.Domain/ValueObjects/DateFormat.cs index 137b812..3528389 100644 --- a/src/People.Domain/ValueObjects/DateFormat.cs +++ b/src/People.Domain/ValueObjects/DateFormat.cs @@ -11,19 +11,19 @@ namespace People.Domain.ValueObjects; "dd.MM.yy", "d.M.yyyy", "d.M.yy", - + "MM-dd-yyyy", "dd-MM-yyyy", "dd-MM-yy", "d-M-yyyy", "d-M-yy", - + "MM/dd/yyyy", "dd/MM/yyyy", "dd/MM/yy", "d/M/yyyy", "d/M/yy", - + "yyyy-MM-dd" }; diff --git a/src/People.Domain/ValueObjects/RegionCode.cs b/src/People.Domain/ValueObjects/RegionCode.cs index 2f0f6de..eaa8146 100644 --- a/src/People.Domain/ValueObjects/RegionCode.cs +++ b/src/People.Domain/ValueObjects/RegionCode.cs @@ -65,8 +65,10 @@ private static RegionCode GetCodeOrDefault(string value) return Regions.ContainsKey(value) ? new RegionCode(value) : Empty; foreach (var (code, name) in Regions) + { if (name.Equals(value, StringComparison.OrdinalIgnoreCase)) return new RegionCode(code); + } return Empty; } diff --git a/src/People.Domain/ValueObjects/TimeFormat.cs b/src/People.Domain/ValueObjects/TimeFormat.cs index 8c634e3..f7a3b37 100644 --- a/src/People.Domain/ValueObjects/TimeFormat.cs +++ b/src/People.Domain/ValueObjects/TimeFormat.cs @@ -36,7 +36,7 @@ public static bool TryParse(string? value, out TimeFormat format) format = Default; return false; } - + format = new TimeFormat(value); return true; } diff --git a/src/People.Infrastructure/Confirmations/Confirmation.cs b/src/People.Infrastructure/Confirmations/Confirmation.cs index 8b1447c..7d368e2 100644 --- a/src/People.Infrastructure/Confirmations/Confirmation.cs +++ b/src/People.Infrastructure/Confirmations/Confirmation.cs @@ -15,7 +15,7 @@ private Confirmation() public Confirmation(AccountId accountId, string code, string type, DateTime createdAt, TimeSpan ttl) { - Id = Ulid.NewUlid(); + Id = Guid.CreateVersion7(); AccountId = accountId; Code = code; Type = type; @@ -23,7 +23,7 @@ public Confirmation(AccountId accountId, string code, string type, DateTime crea ExpiresAt = createdAt + ttl; } - public Ulid Id { get; private set; } + public Guid Id { get; private set; } public AccountId AccountId { get; private set; } diff --git a/src/People.Infrastructure/Confirmations/ConfirmationService.cs b/src/People.Infrastructure/Confirmations/ConfirmationService.cs index 9512a36..cfce545 100644 --- a/src/People.Infrastructure/Confirmations/ConfirmationService.cs +++ b/src/People.Infrastructure/Confirmations/ConfirmationService.cs @@ -64,7 +64,7 @@ public async Task VerifyEmailAsync(string token, string code, try { var bytes = Decrypt(Convert.FromBase64String(token)); - var id = new Ulid(bytes[..16]); + var id = new Guid(bytes[..16]); var email = new MailAddress(Encoding.UTF8.GetString(bytes[16..])); var accountId = await DecodeAsync(id, "EmailVerify", code, ct); @@ -133,7 +133,7 @@ private async Task EncodeAsync(AccountId id, string type, Cancella return entity; } - private async Task DecodeAsync(Ulid id, string type, string code, CancellationToken ct) + private async Task DecodeAsync(Guid id, string type, string code, CancellationToken ct) { var confirmation = await _dbContext.Set() .FirstOrDefaultAsync(x => x.Id == id, ct) ?? throw ConfirmationException.NotFound(); @@ -147,11 +147,11 @@ private async Task DecodeAsync(Ulid id, string type, string code, Can return confirmation.AccountId; } - private static Ulid ConventToGuid(string token) + private static Guid ConventToGuid(string token) { try { - return new Ulid(Convert.FromBase64String(token)); + return new Guid(Convert.FromBase64String(token)); } catch { diff --git a/src/People.Infrastructure/Confirmations/ConfirmationsWorker.cs b/src/People.Infrastructure/Confirmations/ConfirmationsWorker.cs index 2b328d8..5cdd6cc 100644 --- a/src/People.Infrastructure/Confirmations/ConfirmationsWorker.cs +++ b/src/People.Infrastructure/Confirmations/ConfirmationsWorker.cs @@ -19,6 +19,7 @@ public ConfirmationsWorker(ILogger logger, IServiceProvider protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (await _timer.WaitForNextTickAsync(stoppingToken)) + { try { var result = await DeleteAsync(stoppingToken); @@ -29,6 +30,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogWarning(ex, "Exception occured in {service}", nameof(ConfirmationsWorker)); } + } } private async Task DeleteAsync(CancellationToken ct) diff --git a/src/People.Infrastructure/EntityConfigurations/ConfirmationEntityTypeConfiguration.cs b/src/People.Infrastructure/EntityConfigurations/ConfirmationEntityTypeConfiguration.cs index 3c28445..5544b5f 100644 --- a/src/People.Infrastructure/EntityConfigurations/ConfirmationEntityTypeConfiguration.cs +++ b/src/People.Infrastructure/EntityConfigurations/ConfirmationEntityTypeConfiguration.cs @@ -2,7 +2,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders; using People.Domain.Entities; using People.Infrastructure.Confirmations; -using People.Infrastructure.ValueConverters; namespace People.Infrastructure.EntityConfigurations; @@ -14,11 +13,14 @@ public void Configure(EntityTypeBuilder builder) builder.HasKey(x => x.Id); - builder.HasIndex(x => new { x.AccountId, x.Type }); + builder.HasIndex(x => new + { + x.AccountId, + x.Type + }); builder.Property(x => x.Id) - .HasColumnName("id") - .HasConversion(); + .HasColumnName("id"); builder.Property(x => x.AccountId) .HasColumnName("account_id") diff --git a/src/People.Infrastructure/EntityConfigurations/EmailEntityTypeConfiguration.cs b/src/People.Infrastructure/EntityConfigurations/EmailEntityTypeConfiguration.cs index 529e4c0..a02fd8e 100644 --- a/src/People.Infrastructure/EntityConfigurations/EmailEntityTypeConfiguration.cs +++ b/src/People.Infrastructure/EntityConfigurations/EmailEntityTypeConfiguration.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using People.Domain.Entities; -using People.Infrastructure.ValueConverters; namespace People.Infrastructure.EntityConfigurations; @@ -18,8 +17,7 @@ public void Configure(EntityTypeBuilder builder) builder.Ignore(x => x.IsConfirmed); builder.Property(x => x.Id) - .HasColumnName("id") - .HasConversion(); + .HasColumnName("id"); builder.Property(x => x.AccountId) .HasColumnName("account_id") diff --git a/src/People.Infrastructure/EntityConfigurations/ExternalConnectionEntityTypeConfiguration.cs b/src/People.Infrastructure/EntityConfigurations/ExternalConnectionEntityTypeConfiguration.cs index ef52fba..e78dc76 100644 --- a/src/People.Infrastructure/EntityConfigurations/ExternalConnectionEntityTypeConfiguration.cs +++ b/src/People.Infrastructure/EntityConfigurations/ExternalConnectionEntityTypeConfiguration.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using People.Domain.Entities; -using People.Infrastructure.ValueConverters; namespace People.Infrastructure.EntityConfigurations; @@ -12,13 +11,16 @@ public void Configure(EntityTypeBuilder builder) builder.ToTable("connections"); builder.HasKey(x => x.Id); - builder.HasAlternateKey(x => new { Name = x.Type, x.Identity }); + builder.HasAlternateKey(x => new + { + Name = x.Type, + x.Identity + }); builder.Ignore(x => x.DomainEvents); builder.Property(x => x.Id) - .HasColumnName("id") - .HasConversion(); + .HasColumnName("id"); builder.Property("_accountId") .HasColumnName("account_id") diff --git a/src/People.Infrastructure/People.Infrastructure.csproj b/src/People.Infrastructure/People.Infrastructure.csproj index fb3d360..f7e47c1 100644 --- a/src/People.Infrastructure/People.Infrastructure.csproj +++ b/src/People.Infrastructure/People.Infrastructure.csproj @@ -1,6 +1,6 @@ - net8.0 + net9.0 enable enable @@ -8,13 +8,13 @@ - - - - - - - - + + + + + + + + diff --git a/src/People.Infrastructure/Providers/NpgsqlData/SqlBuilder.cs b/src/People.Infrastructure/Providers/NpgsqlData/SqlBuilder.cs index eb6abd7..0a7e480 100644 --- a/src/People.Infrastructure/Providers/NpgsqlData/SqlBuilder.cs +++ b/src/People.Infrastructure/Providers/NpgsqlData/SqlBuilder.cs @@ -23,12 +23,20 @@ public SqlBuilder AddParameter(NpgsqlParameter parameter) public SqlBuilder AddParameter(object value) { - _parameters.Add(new NpgsqlParameter { Value = value }); + _parameters.Add(new NpgsqlParameter + { + Value = value + }); + return this; } - public SqlReader Select(Func mapper) => - new(_connection, _sql, _parameters, mapper ?? throw new ArgumentNullException(nameof(mapper))); + public SqlReader Select(Func mapper) + { + ArgumentNullException.ThrowIfNull(mapper); + + return new SqlReader(_connection, _sql, _parameters, mapper); + } public async Task ExecuteAsync(CancellationToken ct = default) { diff --git a/src/People.Infrastructure/ValueConverters/OrderIdConverter.cs b/src/People.Infrastructure/ValueConverters/OrderIdConverter.cs deleted file mode 100644 index 1891bfe..0000000 --- a/src/People.Infrastructure/ValueConverters/OrderIdConverter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace People.Infrastructure.ValueConverters; - -internal sealed class UlidConverter : ValueConverter -{ - public UlidConverter() - : base(x => x.ToGuid(), x => new Ulid(x)) - { - } -} diff --git a/src/People.Kafka/KafkaEventBus.cs b/src/People.Kafka/KafkaEventBus.cs index af9ad3f..00d49e6 100644 --- a/src/People.Kafka/KafkaEventBus.cs +++ b/src/People.Kafka/KafkaEventBus.cs @@ -80,7 +80,7 @@ private async Task PublishAsync(IServiceProvider provider, T message, Cancell ); var producer = provider.GetRequiredService(handlerType) as IKafkaProducer - ?? throw CreateException($"{type.Name}'s producer not found"); + ?? throw CreateException($"{type.Name}'s producer not found"); _logger.MessageSending(message); diff --git a/src/People.Kafka/People.Kafka.csproj b/src/People.Kafka/People.Kafka.csproj index d17b183..785ffaa 100644 --- a/src/People.Kafka/People.Kafka.csproj +++ b/src/People.Kafka/People.Kafka.csproj @@ -1,14 +1,14 @@ - net8.0 + net9.0 enable enable - - - - - + + + + + diff --git a/src/People.Kafka/Producers/KafkaProducer.cs b/src/People.Kafka/Producers/KafkaProducer.cs index 43c4b7f..ab18715 100644 --- a/src/People.Kafka/Producers/KafkaProducer.cs +++ b/src/People.Kafka/Producers/KafkaProducer.cs @@ -38,8 +38,12 @@ public Task ProduceAsync(T message, CancellationToken ct) Timestamp = new Timestamp(message.CreatedAt), Headers = new Headers { - { nameof(Activity.TraceId), Encoding.UTF8.GetBytes(Activity.Current.TraceId.ToHexString()) }, - { nameof(Activity.SpanId), Encoding.UTF8.GetBytes(Activity.Current.SpanId.ToHexString()) } + { + nameof(Activity.TraceId), Encoding.UTF8.GetBytes(Activity.Current.TraceId.ToHexString()) + }, + { + nameof(Activity.SpanId), Encoding.UTF8.GetBytes(Activity.Current.SpanId.ToHexString()) + } } }; diff --git a/src/People.Webhooks/Dockerfile b/src/People.Webhooks/Dockerfile index dd82f80..957074c 100644 --- a/src/People.Webhooks/Dockerfile +++ b/src/People.Webhooks/Dockerfile @@ -1,7 +1,7 @@ -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR / COPY "src" "src/" WORKDIR /src/People.Webhooks diff --git a/src/People.Webhooks/People.Webhooks.csproj b/src/People.Webhooks/People.Webhooks.csproj index 8f3e478..efeaa5e 100644 --- a/src/People.Webhooks/People.Webhooks.csproj +++ b/src/People.Webhooks/People.Webhooks.csproj @@ -1,16 +1,16 @@ - net8.0 + net9.0 enable enable - - - - - - + + + + + + diff --git a/src/People.Webhooks/Program.cs b/src/People.Webhooks/Program.cs index 7da5bb0..f85bdef 100644 --- a/src/People.Webhooks/Program.cs +++ b/src/People.Webhooks/Program.cs @@ -18,7 +18,7 @@ { ApplicationName = appName }; - + options.UseNpgsql(postgresql.ToString(), npgsql => { npgsql.EnableRetryOnFailure(5); diff --git a/src/People.Webhooks/Services/Sender/WebhooksSender.cs b/src/People.Webhooks/Services/Sender/WebhooksSender.cs index 12fa974..9fb3800 100644 --- a/src/People.Webhooks/Services/Sender/WebhooksSender.cs +++ b/src/People.Webhooks/Services/Sender/WebhooksSender.cs @@ -10,7 +10,10 @@ internal sealed class WebhooksSender : IWebhooksSender private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } + Converters = + { + new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) + } }; private readonly HttpClient _httpClient;