From 80144bf9fc9710d8b188de678a823878e8941546 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Thu, 4 Jun 2026 22:04:20 +0100 Subject: [PATCH] refacts, and launching Blogs --- .editorconfig | 234 +++++++++++++++++- .vscode/launch.json | 55 ++-- .vscode/settings.json | 3 +- src/Api/Program.cs | 39 ++- src/Api/Properties/launchSettings.json | 5 +- src/Api/appsettings.json | 9 +- src/Yavsc.Abstract/Yavsc.Abstract.csproj | 3 +- src/Yavsc.Blogs/Program.cs | 154 +++++++----- src/Yavsc.Blogs/appsettings.json | 9 +- .../Communicating/BlogspotController.cs | 4 +- src/Yavsc.Server/Yavsc.Server.csproj | 3 +- 11 files changed, 411 insertions(+), 107 deletions(-) diff --git a/.editorconfig b/.editorconfig index c55741fe..80392cb9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -33,12 +33,236 @@ indent_size = 2 [{package.json,.travis.yml}] indent_style = space indent_size = 2 +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true +# C# files +[*.cs] -dotnet_naming_rule.locals_should_be_camel_case.severity = none -dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters -dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style +#### Core EditorConfig Options #### -dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 -dotnet_naming_style.camel_case_style.capitalization = camel_case +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_collection_expression = when_types_loosely_match +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_non_hidden_explicit_cast_in_source = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true +dotnet_prefer_system_hash_code = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:silent + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_style_namespace_declarations = block_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_top_level_statements = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/.vscode/launch.json b/.vscode/launch.json index 0acda146..18027dd1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,44 @@ // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "name": ".NET API", + "type": "coreclr", + "request": "launch", + "program": "${workspaceFolder}/src/Api/bin/Debug/net10.0/Api.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Api", + "serverReadyAction": { + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "envFile": "${workspaceFolder}/src/Api/.env" + }, + { + "name": "C#: API Debug", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/src/Api/Api.csproj" + }, + { + "name": "Blogs", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Yavsc.Blogs/bin/Debug/net10.0/Yavsc.Blogs.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Yavsc.Blogs/", + "stopAtEntry": false, + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, { "name": "C#: Yavsc.Org Debug", "type": "dotnet", @@ -26,8 +64,9 @@ "env": { "ASPNETCORE_ENVIRONMENT": "Development" }, + "envFile": "${workspaceFolder}/src/Yavsc.Org/.env", "sourceFileMap": { - "/Views": "${workspaceFolder}/Views" + "/Views": "${workspaceFolder}/src/Yavsc.Org/Views" } }, { @@ -58,21 +97,9 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "sourceFileMap": { - "/Views": "${workspaceFolder}/src/Web/Views" + "/Views": "${workspaceFolder}/src/Yavsc.Web/Views" } }, - - { - "name": "Api", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-webapi", - "program": "${workspaceFolder}/src/Api/bin/Debug/net10.0/Api.dll", - "args": [], - "cwd": "${workspaceFolder}/src/Api", - "stopAtEntry": false, - "console": "internalConsole" - }, { "name": "PostIt", "type": "dotnet", diff --git a/.vscode/settings.json b/.vscode/settings.json index 420ea3b7..e7ffe374 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,5 +18,6 @@ "chat.tools.terminal.autoApprove": { "dotnet test": true }, - "makefile.configureOnOpen": false + "makefile.configureOnOpen": false, + "chat.disableAIFeatures": false } diff --git a/src/Api/Program.cs b/src/Api/Program.cs index ea884e2f..9b47aa6b 100644 --- a/src/Api/Program.cs +++ b/src/Api/Program.cs @@ -65,16 +65,39 @@ internal class Program new() { ValidateAudience = false, RoleClaimType = YavscConstants.RoleClaimType }; options.MapInboundClaims = true; }); - + services.AddDbContext(options => - + options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); + services.AddLocalization(options => + { + options.ResourcesPath = "Resources"; + }); + // + services.AddTransient, MailSender>(); services.AddTransient() + .AddTransient() .AddTransient() .AddTransient(); services.AddTransient(); - + builder.Services.AddSession(options => + { + options.IdleTimeout = TimeSpan.FromMinutes(30); + options.Cookie.HttpOnly = true; + options.Cookie.IsEssential = false; + }); + + builder.Services.AddDistributedMemoryCache(); + + builder.Services.Configure(options => + { + var supportedCultures = new[] { "fr", "en", "pt" }; + options.SetDefaultCulture(supportedCultures[0]) + .AddSupportedCultures(supportedCultures) + .AddSupportedUICultures(supportedCultures); + }); WorkflowHelpers.ConfigureBillingService(); using (var app = builder.Build()) { @@ -86,20 +109,14 @@ internal class Program .UseAuthentication() .UseAuthorization() .UseCors("default") - /* .UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute() - .RequireAuthorization(); - })*/ - ; - // app.MapIdentityApi().RequireAuthorization("ApiScope"); + app.MapIdentityApi().RequireAuthorization("ApiScope"); app.MapDefaultControllerRoute(); app.MapGet("/identity", (HttpContext context) => new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) ); - // app.UseSession(); + app.UseSession(); await app.RunAsync(); } } diff --git a/src/Api/Properties/launchSettings.json b/src/Api/Properties/launchSettings.json index e27c888f..3ede6774 100644 --- a/src/Api/Properties/launchSettings.json +++ b/src/Api/Properties/launchSettings.json @@ -4,17 +4,16 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "https://localhost:5001", + "applicationUrl": "https://localhost:6001", "sslPort": 6001 } }, "profiles": { - "https": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": false, - "applicationUrl": "https://localhost:6001;", + "applicationUrl": "https://localhost:6001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Api/appsettings.json b/src/Api/appsettings.json index d9d9a9bf..2d20fb7a 100644 --- a/src/Api/appsettings.json +++ b/src/Api/appsettings.json @@ -6,5 +6,12 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "Kestrel": { + "Endpoints": { + "Https":{ + "Url": "https://localhost:6001" + } + } + } } diff --git a/src/Yavsc.Abstract/Yavsc.Abstract.csproj b/src/Yavsc.Abstract/Yavsc.Abstract.csproj index fbc32624..b2a9fa63 100644 --- a/src/Yavsc.Abstract/Yavsc.Abstract.csproj +++ b/src/Yavsc.Abstract/Yavsc.Abstract.csproj @@ -7,8 +7,9 @@ Yavsc.Abstract https://github.com/pazof/yavsc true + true - \ No newline at end of file + diff --git a/src/Yavsc.Blogs/Program.cs b/src/Yavsc.Blogs/Program.cs index e7dca81f..1160173c 100644 --- a/src/Yavsc.Blogs/Program.cs +++ b/src/Yavsc.Blogs/Program.cs @@ -23,89 +23,109 @@ using Yavsc.Server.Helpers; internal class Program { private static async Task Main(string[] args) - { - Console.Title = "Yavsc.Blogs"; + { + Console.Title = "Yavsc.Blogs"; - var builder = WebApplication.CreateBuilder(args); + var builder = WebApplication.CreateBuilder(args); - var services = builder.Services; + var services = builder.Services; - var authority = builder.GetAuthority(); - var audience = builder.GetAudience(); + var authority = builder.GetAuthority(); + var audience = builder.GetAudience(); - // builder.Services.AddDistributedMemoryCache(); + // builder.Services.AddDistributedMemoryCache(); - // accepts any access token issued by identity server - // adds an authorization policy for scope 'scope1' + // accepts any access token issued by identity server + // adds an authorization policy for scope 'scope1' - services - .AddAuthorization(options => - { - options.AddPolicy("ApiScope", policy => - { - policy + services + .AddAuthorization(options => + { + options.AddPolicy("ApiScope", policy => + { + policy .RequireAuthenticatedUser() .RequireClaim(JwtClaimTypes.Scope, new string[] { "blogs" }); - }); - }) - .AddCors(options => - { - // this defines a CORS policy called "default" - options.AddPolicy("default", policy => - { - policy.WithOrigins(audience) + }); + }) + .AddCors(options => + { + // this defines a CORS policy called "default" + options.AddPolicy("default", policy => + { + policy.WithOrigins(audience) .AllowAnyHeader() .AllowAnyMethod(); - }); - }) - .AddControllers(); + }); + }) + .AddControllers(); - // accepts any access token issued by identity server - var authenticationBuilder = services.AddAuthentication("Bearer") - .AddJwtBearer("Bearer", options => - { - options.IncludeErrorDetails = true; - options.Authority = authority; - options.TokenValidationParameters = - new() { ValidateAudience = false, RoleClaimType = YavscConstants.RoleClaimType }; - options.MapInboundClaims = true; - }); - - services.AddDbContext(options => - options.UseNpgsql(builder.Configuration.GetConnectionString(YavscConstants.YavscConnectionStringName))); + // accepts any access token issued by identity server + var authenticationBuilder = services.AddAuthentication("Bearer") + .AddJwtBearer("Bearer", options => + { + options.IncludeErrorDetails = true; + options.Authority = authority; + options.TokenValidationParameters = + new() { ValidateAudience = false, RoleClaimType = YavscConstants.RoleClaimType }; + options.MapInboundClaims = true; + }); - services.AddTransient() - .AddTransient() - .AddTransient(); - services.AddTransient(); + services.AddDbContext(options => + options.UseNpgsql(builder.Configuration.GetConnectionString(YavscConstants.YavscConnectionStringName))); - WorkflowHelpers.ConfigureBillingService(); - using (var app = builder.Build()) - { - if (app.Environment.IsDevelopment()) - app.UseDeveloperExceptionPage(); + services.AddTransient() + .AddTransient() + .AddTransient(); + services.AddTransient(); + + services.AddLocalization(options => + { + options.ResourcesPath = "Resources"; + }); + services.AddDistributedMemoryCache(); - app - .UseRouting() - .UseAuthentication() - .UseAuthorization() - .UseCors("default") - /* .UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute() - .RequireAuthorization(); - })*/ + services.AddSession(options => + { + options.IdleTimeout = TimeSpan.FromMinutes(30); + options.Cookie.HttpOnly = true; + options.Cookie.IsEssential = false; + }); - ; - // app.MapIdentityApi().RequireAuthorization("ApiScope"); - app.MapDefaultControllerRoute(); - app.MapGet("/identity", (HttpContext context) => - new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) - ); + services.Configure(options => + { + var supportedCultures = new[] { "fr", "en", "pt" }; + options.SetDefaultCulture(supportedCultures[0]) + .AddSupportedCultures(supportedCultures) + .AddSupportedUICultures(supportedCultures); + }); - // app.UseSession(); - await app.RunAsync(); + using (var app = builder.Build()) + { + if (app.Environment.IsDevelopment()) + app.UseDeveloperExceptionPage(); + + app + .UseRouting() + .UseAuthentication() + .UseAuthorization() + .UseCors("default") + /* .UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute() + .RequireAuthorization(); + })*/ + + ; + // app.MapIdentityApi().RequireAuthorization("ApiScope"); + app.MapDefaultControllerRoute(); + app.MapGet("/identity", (HttpContext context) => + new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) + ); + + // app.UseSession(); + await app.RunAsync(); + } } - } } diff --git a/src/Yavsc.Blogs/appsettings.json b/src/Yavsc.Blogs/appsettings.json index a0f7abe2..0012fcfa 100644 --- a/src/Yavsc.Blogs/appsettings.json +++ b/src/Yavsc.Blogs/appsettings.json @@ -1,4 +1,11 @@ { + "Site": { + "Title": "Yavsc Blogs", + "Description": "A collection of blogs about software development, technology, and programming.", + "Keywords": "software development, technology, programming, coding, blogs", + "Authority": "https://localhost:5001", + "Audience": "https://localhost:5005" + }, "Logging": { "LogLevel": { "Default": "Information", @@ -10,7 +17,7 @@ "Kestrel": { "Endpoints": { "Https": { - "Url": "https://localhost:6001" + "Url": "https://localhost:5005" } } } diff --git a/src/Yavsc.Org/Controllers/Communicating/BlogspotController.cs b/src/Yavsc.Org/Controllers/Communicating/BlogspotController.cs index 6360dd84..a357458a 100644 --- a/src/Yavsc.Org/Controllers/Communicating/BlogspotController.cs +++ b/src/Yavsc.Org/Controllers/Communicating/BlogspotController.cs @@ -12,7 +12,7 @@ using Yavsc.Server.Helpers; namespace Yavsc.Controllers { - public class BlogspotController : Controller + public class BlogSpotController : Controller { readonly ILogger _logger; private readonly ApplicationDbContext _context; @@ -20,7 +20,7 @@ namespace Yavsc.Controllers readonly RequestLocalizationOptions _localisationOptions; readonly BlogSpotService blogSpotService; - public BlogspotController( + public BlogSpotController( ApplicationDbContext context, ILoggerFactory loggerFactory, IAuthorizationService authorizationService, diff --git a/src/Yavsc.Server/Yavsc.Server.csproj b/src/Yavsc.Server/Yavsc.Server.csproj index a04afbb6..b43402e8 100644 --- a/src/Yavsc.Server/Yavsc.Server.csproj +++ b/src/Yavsc.Server/Yavsc.Server.csproj @@ -6,6 +6,7 @@ Yavsc.Server true https://github.com/pazof/yavsc + true @@ -33,4 +34,4 @@ - \ No newline at end of file +