diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index cd967fc..0000000
--- a/.dockerignore
+++ /dev/null
@@ -1,25 +0,0 @@
-**/.dockerignore
-**/.env
-**/.git
-**/.gitignore
-**/.project
-**/.settings
-**/.toolstarget
-**/.vs
-**/.vscode
-**/.idea
-**/*.*proj.user
-**/*.dbmdl
-**/*.jfm
-**/azds.yaml
-**/bin
-**/charts
-**/docker-compose*
-**/Dockerfile*
-**/node_modules
-**/npm-debug.log
-**/obj
-**/secrets.dev.yaml
-**/values.dev.yaml
-LICENSE
-README.md
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 49e0817..1d6b270 100755
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -40,6 +40,7 @@
+
diff --git a/Place.sln b/Place.sln
index 2d04d79..23d77e4 100755
--- a/Place.sln
+++ b/Place.sln
@@ -21,6 +21,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DA61C0F8-3DDC-47E1-93A9-3ACB68AF4AEE}"
ProjectSection(SolutionItems) = preProject
Directory.Packages.props = Directory.Packages.props
+ compose.yaml = compose.yaml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Account", "Account", "{5B48E2F5-D7CC-48EA-94FE-A2F132650C8F}"
@@ -55,6 +56,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.MediatR", "src\Common\
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{4B354D87-FCA4-46F3-A64E-76376D3C68C2}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{CC68CA38-62BE-4535-9BB4-AB1597AFC90A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Place.API", "src\Place.API\Place.API.csproj", "{C4DD7B27-138C-4DFC-BC57-69BFC70853CA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -79,6 +84,7 @@ Global
{5453898F-4A78-4AD6-89B5-BAB204FF67FF} = {25654B5F-D4E9-4019-B307-8759C38E94A8}
{5B48E2F5-D7CC-48EA-94FE-A2F132650C8F} = {4B354D87-FCA4-46F3-A64E-76376D3C68C2}
{C3F80B30-C2DE-41DC-933A-A24E04827504} = {4B354D87-FCA4-46F3-A64E-76376D3C68C2}
+ {C4DD7B27-138C-4DFC-BC57-69BFC70853CA} = {CC68CA38-62BE-4535-9BB4-AB1597AFC90A}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1DFC8537-6B29-4BB5-8449-1910496DB479}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -143,5 +149,9 @@ Global
{5453898F-4A78-4AD6-89B5-BAB204FF67FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5453898F-4A78-4AD6-89B5-BAB204FF67FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5453898F-4A78-4AD6-89B5-BAB204FF67FF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C4DD7B27-138C-4DFC-BC57-69BFC70853CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C4DD7B27-138C-4DFC-BC57-69BFC70853CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C4DD7B27-138C-4DFC-BC57-69BFC70853CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C4DD7B27-138C-4DFC-BC57-69BFC70853CA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/compose.yaml b/compose.yaml
new file mode 100644
index 0000000..1191a95
--- /dev/null
+++ b/compose.yaml
@@ -0,0 +1,6 @@
+services:
+ place.api:
+ image: place.api
+ build:
+ context: .
+ dockerfile: src/Place.API/Dockerfile
diff --git a/src/Account/AccountModule.cs b/src/Account/AccountModule.cs
index 8ece555..ef7b7be 100755
--- a/src/Account/AccountModule.cs
+++ b/src/Account/AccountModule.cs
@@ -1,3 +1,4 @@
+using System.Threading.Tasks;
using Account.Data.Configurations;
using Account.Data.Seed;
using Core.EF;
@@ -22,17 +23,17 @@ IConfiguration configuration
nameof(Core.Identity),
configuration
);
- services.AddScoped();
+ services.AddScoped, AccountDataSeeder>();
return services;
}
- public static WebApplication UseAccountModule(
+ public static async Task UseAccountModule(
this WebApplication app,
IWebHostEnvironment environment
)
{
app.UseCoreFramework();
- app.UseMigration(environment);
+ await app.UseMigrationAsync(environment);
return app;
}
}
diff --git a/src/Account/Data/Configurations/DatabaseInitializer.cs b/src/Account/Data/Configurations/DatabaseInitializer.cs
deleted file mode 100755
index 6be71e0..0000000
--- a/src/Account/Data/Configurations/DatabaseInitializer.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Account.Data.Models;
-using Account.Profile.Models;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-
-namespace Account.Data.Configurations;
-
-///
-/// Extension methods for database initialization and seeding.
-///
-public static class DatabaseInitializer
-{
- ///
- /// Ensures the database is created and migrations are applied.
- /// Also seeds initial data in development environment.
- ///
- public static async Task InitializeDatabaseAsync(this WebApplication app)
- {
- using IServiceScope scope = app.Services.CreateScope();
- IServiceProvider services = scope.ServiceProvider;
- ILogger logger = services.GetRequiredService>();
-
- try
- {
- AccountDbContext context = services.GetRequiredService();
-
- logger.LogInformation("Starting database migration...");
-
- await context.Database.MigrateAsync();
-
- logger.LogInformation("Database migration completed successfully");
-
- // Seed data only in development
- if (app.Environment.IsDevelopment())
- {
- logger.LogInformation("Development environment detected. Starting data seeding...");
- await SeedDataAsync(context);
- logger.LogInformation("Data seeding completed successfully");
- }
- }
- catch (Exception ex)
- {
- logger.LogError(ex, "An error occurred while initializing the database");
- throw;
- }
- }
-
- private static async Task SeedDataAsync(AccountDbContext context)
- {
- // Check if there's any data already
- if (await context.Profiles.AnyAsync())
- {
- return;
- }
-
- // Create sample profiles
- List profiles =
- [
- new()
- {
- Id = Guid.NewGuid(),
- UserId = Guid.NewGuid(),
- Email = "john.doe@example.com",
- FirstName = "John",
- LastName = "Doe",
- DateOfBirth = new DateTime(1990, 1, 1),
- Gender = Gender.Male,
- PhoneNumber = "+33612345678",
- Street = "123 Main St",
- ZipCode = "75001",
- City = "Paris",
- Country = "France",
- CreatedAt = DateTime.UtcNow,
- CreatedBy = Guid.NewGuid(),
- IsDeleted = false,
- },
- new()
- {
- Id = Guid.NewGuid(),
- UserId = Guid.NewGuid(),
- Email = "jane.smith@example.com",
- FirstName = "Jane",
- LastName = "Smith",
- DateOfBirth = new DateTime(1985, 5, 15),
- Gender = Gender.Female,
- PhoneNumber = "+237655555555",
- City = "Yaoundé",
- Country = "Cameroon",
- CreatedAt = DateTime.UtcNow,
- CreatedBy = Guid.NewGuid(),
- IsDeleted = false,
- },
- // Add a soft-deleted profile for testing
-
- new()
- {
- Id = Guid.NewGuid(),
- UserId = Guid.NewGuid(),
- Email = "deleted@example.com",
- FirstName = "Deleted",
- LastName = "User",
- CreatedAt = DateTime.UtcNow.AddDays(-30),
- CreatedBy = Guid.NewGuid(),
- IsDeleted = true,
- DeletedAt = DateTime.UtcNow.AddDays(-1),
- DeletedBy = Guid.NewGuid(),
- },
- ];
-
- await context.Profiles.AddRangeAsync(profiles);
- await context.SaveChangesAsync();
- }
-}
diff --git a/src/Account/Data/Seed/AccountDataSeeder.cs b/src/Account/Data/Seed/AccountDataSeeder.cs
index e6c026d..d2705da 100644
--- a/src/Account/Data/Seed/AccountDataSeeder.cs
+++ b/src/Account/Data/Seed/AccountDataSeeder.cs
@@ -9,7 +9,7 @@
namespace Account.Data.Seed;
-public class AccountDataSeeder(AccountDbContext context) : IDataSeeder
+public class AccountDataSeeder(AccountDbContext context) : IDataSeeder
{
public async Task SeedAllAsync()
{
diff --git a/src/Account/IAccountRoot.cs b/src/Account/IAccountRoot.cs
new file mode 100755
index 0000000..9b5af21
--- /dev/null
+++ b/src/Account/IAccountRoot.cs
@@ -0,0 +1,3 @@
+namespace Account;
+
+public interface IAccountRoot { }
diff --git a/src/Account/IAssemblyMarker.cs b/src/Account/IAssemblyMarker.cs
deleted file mode 100755
index 0c4bd66..0000000
--- a/src/Account/IAssemblyMarker.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace Account;
-
-public interface IAssemblyMarker { }
diff --git a/src/Account/Program.cs b/src/Account/Program.cs
index ee727e1..657143b 100755
--- a/src/Account/Program.cs
+++ b/src/Account/Program.cs
@@ -17,6 +17,6 @@
WebApplication app = builder.Build();
-app.UseAccountModule(environment);
+await app.UseAccountModule(environment);
await app.RunAsync();
diff --git a/src/Account/appsettings.Development.json b/src/Account/appsettings.Development.json
index ec38444..0c208ae 100755
--- a/src/Account/appsettings.Development.json
+++ b/src/Account/appsettings.Development.json
@@ -4,12 +4,5 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
- },
- "Postgres": {
- "Host": "localhost",
- "Port": 5489,
- "Username": "postgres",
- "Password": "postgres",
- "Database": "PlaceApiProfile"
}
}
diff --git a/src/Account/appsettings.json b/src/Account/appsettings.json
index a3526c6..a337d54 100755
--- a/src/Account/appsettings.json
+++ b/src/Account/appsettings.json
@@ -8,24 +8,10 @@
"app": {
"name": "Place Profile Api"
},
- "serilog": {
+ "Serilog": {
+ "applicationName": "identity-service",
+ "excludePaths": ["/ping", "/metrics"],
"level": "information",
- "overrides": {
- "Microsoft.AspNetCore": "Warning",
- "Microsoft.EntityFrameworkCore.Database.Command": "Warning",
- "Microsoft.EntityFrameworkCore.Infrastructure": "Warning"
- },
- "excludePaths": [
- "/",
- "/metrics",
- "/ping"
- ],
- "excludeProperties": [
- "api_key",
- "access_key",
- "password",
- "email"
- ],
"console": {
"enabled": true
},
@@ -37,9 +23,8 @@
"seq": {
"enabled": true,
"url": "http://localhost:5341",
- "apiKey": "secret"
- },
- "tags": {}
+ "token": "secret"
+ }
},
"Swagger": {
"Title": "Place Profile Api",
diff --git a/src/Common/Core.EF/IDataSeeder.cs b/src/Common/Core.EF/IDataSeeder.cs
index 83c494e..9e3fc6e 100644
--- a/src/Common/Core.EF/IDataSeeder.cs
+++ b/src/Common/Core.EF/IDataSeeder.cs
@@ -1,8 +1,10 @@
using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
namespace Core.EF;
-public interface IDataSeeder
+public interface IDataSeeder
+ where TContext : DbContext
{
Task SeedAllAsync();
}
diff --git a/src/Common/Core.EF/ServiceCollectionExtensions.cs b/src/Common/Core.EF/ServiceCollectionExtensions.cs
index 16723e7..b09db9b 100644
--- a/src/Common/Core.EF/ServiceCollectionExtensions.cs
+++ b/src/Common/Core.EF/ServiceCollectionExtensions.cs
@@ -13,6 +13,8 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Npgsql;
namespace Core.EF;
@@ -27,18 +29,27 @@ IConfiguration configuration
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
- string? b = configuration.GetConnectionString(connectionName);
+ string? connectionString = configuration.GetConnectionString(connectionName);
+ if (string.IsNullOrEmpty(connectionString))
+ {
+ throw new InvalidOperationException($"Connection string '{connectionName}' not found.");
+ }
services.AddDbContext(
(sp, options) =>
{
- options.UseNpgsql(
- configuration.GetConnectionString(connectionName),
- dbOptions =>
- {
- dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name);
- }
- );
+ options
+ .UseNpgsql(
+ connectionString,
+ dbOptions =>
+ {
+ dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name);
+ dbOptions.EnableRetryOnFailure(3);
+ }
+ )
+ .EnableSensitiveDataLogging(
+ sp.GetService()?.IsDevelopment() ?? false
+ );
}
);
@@ -47,22 +58,58 @@ IConfiguration configuration
return services;
}
- public static IApplicationBuilder UseMigration(
+ public static async Task UseMigrationAsync(
this IApplicationBuilder app,
IWebHostEnvironment env
)
where TContext : DbContext, IDbContext
{
- MigrateDatabaseAsync(app.ApplicationServices).GetAwaiter().GetResult();
+ ILogger logger = app.ApplicationServices.GetRequiredService>();
+
+ await EnsureDatabaseExistsAsync(app.ApplicationServices, logger);
+ await MigrateDatabaseAsync(app.ApplicationServices, logger);
if (!env.IsEnvironment("test"))
{
- SeedDataAsync(app.ApplicationServices).GetAwaiter().GetResult();
+ await SeedDataAsync(app.ApplicationServices, logger);
}
return app;
}
+ private static async Task EnsureDatabaseExistsAsync(
+ IServiceProvider serviceProvider,
+ ILogger logger
+ )
+ where TContext : DbContext, IDbContext
+ {
+ using IServiceScope scope = serviceProvider.CreateScope();
+ TContext context = scope.ServiceProvider.GetRequiredService();
+ string? connectionString = context.Database.GetConnectionString();
+
+ try
+ {
+ await context.Database.CanConnectAsync();
+ }
+ catch (PostgresException ex) when (ex.SqlState == "3D000") // Database doesn't exist
+ {
+ logger.LogInformation("Database does not exist. Creating database...");
+
+ NpgsqlConnectionStringBuilder builder = new(connectionString);
+ string? databaseName = builder.Database;
+ builder.Database = "postgres";
+
+ await using NpgsqlConnection masterConnection = new(builder.ToString());
+ await masterConnection.OpenAsync();
+
+ using NpgsqlCommand command = masterConnection.CreateCommand();
+ command.CommandText = $"CREATE DATABASE \"{databaseName}\" ENCODING 'UTF8'";
+
+ await command.ExecuteNonQueryAsync();
+ logger.LogInformation("Database created successfully");
+ }
+ }
+
// ref: https://github.com/pdevito3/MessageBusTestingInMemHarness/blob/main/RecipeManagement/src/RecipeManagement/Databases/RecipesDbContext.cs
public static void FilterSoftDeletedProperties(this ModelBuilder modelBuilder)
{
@@ -118,7 +165,10 @@ public static void ToSnakeCaseTables(this ModelBuilder modelBuilder)
}
}
- private static async Task MigrateDatabaseAsync(IServiceProvider serviceProvider)
+ private static async Task MigrateDatabaseAsync(
+ IServiceProvider serviceProvider,
+ ILogger logger
+ )
where TContext : DbContext, IDbContext
{
using IServiceScope scope = serviceProvider.CreateScope();
@@ -126,22 +176,43 @@ private static async Task MigrateDatabaseAsync(IServiceProvider servic
TContext context = scope.ServiceProvider.GetRequiredService();
try
{
+ logger.LogInformation("Applying migrations...");
await context.Database.MigrateAsync();
}
catch (System.Exception e)
{
- Console.WriteLine(e);
+ logger.LogError(e, "An error occurred while applying migrations");
throw;
}
}
- private static async Task SeedDataAsync(IServiceProvider serviceProvider)
+ private static async Task SeedDataAsync(
+ IServiceProvider serviceProvider,
+ ILogger logger
+ )
+ where TContext : DbContext
{
using IServiceScope scope = serviceProvider.CreateScope();
- IEnumerable seeders = scope.ServiceProvider.GetServices();
- foreach (IDataSeeder seeder in seeders)
+ IEnumerable> seeders = scope.ServiceProvider.GetServices<
+ IDataSeeder
+ >();
+
+ foreach (IDataSeeder seeder in seeders)
{
- await seeder.SeedAllAsync();
+ try
+ {
+ logger.LogInformation("Running seeder {SeederType}...", seeder.GetType().Name);
+ await seeder.SeedAllAsync();
+ }
+ catch (Exception e)
+ {
+ logger.LogError(
+ e,
+ "An error occurred while running seeder {SeederType}",
+ seeder.GetType().Name
+ );
+ throw;
+ }
}
}
}
diff --git a/src/Common/Core.Framework/ServiceCollectionExtensions.cs b/src/Common/Core.Framework/ServiceCollectionExtensions.cs
index bdc178e..e1bfff2 100644
--- a/src/Common/Core.Framework/ServiceCollectionExtensions.cs
+++ b/src/Common/Core.Framework/ServiceCollectionExtensions.cs
@@ -1,8 +1,10 @@
using System;
+using Core.Logging;
using Core.Swagger;
using Core.Versioning;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
+using Serilog;
namespace Core.Framework;
@@ -21,6 +23,8 @@ public static WebApplicationBuilder AddCoreFramework(this WebApplicationBuilder
AppOptions appOptions = builder.Configuration.GetSection("app").BindOptions();
AppInfo appInfo = new(appOptions.Name, appOptions.Version);
builder.Services.AddSingleton(appInfo);
+ builder.AddLogging();
+ builder.Services.AddLogger(builder.Configuration);
RenderLogo(appOptions);
builder.Services.AddHttpContextAccessor();
diff --git a/src/Common/Core.Identity/InitializeDatabase.cs b/src/Common/Core.Identity/InitializeDatabase.cs
deleted file mode 100644
index 090f8d8..0000000
--- a/src/Common/Core.Identity/InitializeDatabase.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-namespace Core.Identity;
-
-using System;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-
-///
-/// Extension methods for database initialization and seeding.
-///
-public static class DatabaseInitializer
-{
- ///
- /// Ensures the database is created and migrations are applied.
- /// Also seeds initial data in development environment.
- ///
- public static async Task InitializeDatabaseAsync(this WebApplication app)
- {
- using IServiceScope scope = app.Services.CreateScope();
- IServiceProvider services = scope.ServiceProvider;
- ILogger logger = services.GetRequiredService<
- ILogger
- >();
-
- try
- {
- IdentityApplicationDbContext context =
- services.GetRequiredService();
-
- logger.LogInformation("Starting database migration...");
-
- await context.Database.MigrateAsync();
-
- logger.LogInformation("Database migration completed successfully");
- }
- catch (Exception ex)
- {
- logger.LogError(ex, "An error occurred while initializing the database");
- throw;
- }
- }
-}
diff --git a/src/Identity/AuthenticateExtensions.cs b/src/Identity/AuthenticateExtensions.cs
index 38ab1a6..1110b77 100644
--- a/src/Identity/AuthenticateExtensions.cs
+++ b/src/Identity/AuthenticateExtensions.cs
@@ -2,6 +2,7 @@
using Core.Identity;
using Identity.Authenticate.Endpoints;
using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using ApiVersion = Asp.Versioning.ApiVersion;
@@ -22,7 +23,7 @@ internal static WebApplication WithAuthenticationEndpoints(this WebApplication a
RouteGroupBuilder groupBuilder = app.MapGroup("api/v{apiVersion:apiVersion}")
.WithApiVersionSet(apiVersionSet);
- groupBuilder.MapAuthenticationEndpoints();
+ groupBuilder.MapAuthenticationEndpoints().WithTags("Identity");
return app;
}
diff --git a/src/Identity/IAssemblyMarker.cs b/src/Identity/IAssemblyMarker.cs
deleted file mode 100644
index 6549f54..0000000
--- a/src/Identity/IAssemblyMarker.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace Identity;
-
-public interface IAssemblyMarker { }
diff --git a/src/Identity/IIdentityRoot.cs b/src/Identity/IIdentityRoot.cs
new file mode 100644
index 0000000..6ea7837
--- /dev/null
+++ b/src/Identity/IIdentityRoot.cs
@@ -0,0 +1,3 @@
+namespace Identity;
+
+public interface IIdentityRoot { }
diff --git a/src/Identity/IdentityMdoule.cs b/src/Identity/IdentityMdoule.cs
index 79c3903..fdc8667 100644
--- a/src/Identity/IdentityMdoule.cs
+++ b/src/Identity/IdentityMdoule.cs
@@ -1,3 +1,4 @@
+using System.Threading.Tasks;
using Core.EF;
using Core.Framework;
using Core.Identity;
@@ -28,13 +29,15 @@ WebApplicationBuilder builder
return services;
}
- public static WebApplication UseIdentityModule(
+ public static async Task UseIdentityModule(
this WebApplication app,
IWebHostEnvironment environment
)
{
app.UseCoreFramework();
- app.UseMigration(environment);
+ await app.UseMigrationAsync(environment);
+ app.WithAuthenticationEndpoints();
+
return app;
}
}
diff --git a/src/Identity/Program.cs b/src/Identity/Program.cs
index b6d5bbd..3748aad 100644
--- a/src/Identity/Program.cs
+++ b/src/Identity/Program.cs
@@ -13,8 +13,7 @@
{
- app.UseIdentityModule(environment);
- app.WithAuthenticationEndpoints();
+ await app.UseIdentityModule(environment);
await app.RunAsync();
}
diff --git a/src/Identity/appsettings.json b/src/Identity/appsettings.json
index e97a617..1e2ab5c 100644
--- a/src/Identity/appsettings.json
+++ b/src/Identity/appsettings.json
@@ -16,50 +16,39 @@
"queryStringParam": "api-version",
"mediaTypeParam": "v"
},
- "Identity": {
- "Database": {
- "Host": "localhost",
- "Port": 5489,
- "Username": "postgres",
- "Password": "postgres",
- "Database": "PlaceApiIdentity"
- },
- "Authentication": {
- "TokenExpiration": "01:00:00",
- "RequireConfirmedEmail": true,
- "RequireConfirmedAccount": false
- },
- "Password": {
- "RequireDigit": true,
- "RequireLowercase": true,
- "RequireUppercase": true,
- "RequireNonAlphanumeric": true,
- "RequiredLength": 10,
- "RequiredUniqueChars": 3
- }
- },
- "swagger": {
- "enabled": true,
- "title": "My API",
- "versions": [
- "1.0",
- "2.0"
- ],
- "useAuthentication": true,
- "enableDownload": true,
- "useSwaggerUI": true,
- "useReDoc": true,
- "swaggerUIRoute": "swagger",
- "reDocRoute": "api-docs",
- "uiOptions": {
- "docExpansion": "List",
- "defaultModelsExpandDepth": 1
- }
+ "Swagger": {
+ "Title": "Place - Identity Api",
+ "Description": "Place Profile Api documentation",
+ "Version": "v1",
+ "EnableBearerAuth": true,
+ "SecuritySchemaName": "Bearer",
+ "SecurityScheme": "JWT",
+ "SecurityDescription": "Utiliser le format: Bearer {votre_token}",
+ "EnableVersioning": true,
+ "RoutePrefix": "swagger"
},
"app": {
"name": "Identity Service"
},
"ConnectionStrings": {
"Identity": "Server=localhost;Port=5490;Database=identity_db;User Id=postgres;Password=postgres;Include Error Detail=true"
+ },
+ "Serilog": {
+ "applicationName": "identity-service",
+ "excludePaths": ["/ping", "/metrics"],
+ "level": "information",
+ "console": {
+ "enabled": true
+ },
+ "file": {
+ "enabled": true,
+ "path": "logs/logs.txt",
+ "interval": "day"
+ },
+ "seq": {
+ "enabled": true,
+ "url": "http://localhost:5341",
+ "token": "secret"
+ }
}
}
diff --git a/src/Place.API/Place.API.csproj b/src/Place.API/Place.API.csproj
new file mode 100644
index 0000000..8f1e3bc
--- /dev/null
+++ b/src/Place.API/Place.API.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net9.0
+ enable
+ enable
+ Linux
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Place.API/Program.cs b/src/Place.API/Program.cs
new file mode 100644
index 0000000..1cfc007
--- /dev/null
+++ b/src/Place.API/Program.cs
@@ -0,0 +1,36 @@
+using Account;
+using Core.Framework;
+using Core.MediatR;
+using Identity;
+using Scalar.AspNetCore;
+
+WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
+IConfiguration configuration = builder.Configuration;
+IWebHostEnvironment environment = builder.Environment;
+
+builder.AddCoreFramework();
+
+builder.Services.AddIdentityModule(builder);
+
+builder.Services.AddAccountModule(configuration);
+
+builder.Services.AddCoreMediatR(typeof(IIdentityRoot).Assembly);
+
+builder.Services.AddCoreMediatR(typeof(IAccountRoot).Assembly);
+
+builder.Services.AddOpenApi();
+
+WebApplication app = builder.Build();
+
+app.UseCoreFramework();
+
+await app.UseIdentityModule(environment);
+
+await app.UseAccountModule(environment);
+
+app.MapOpenApi();
+app.MapScalarApiReference();
+
+app.MapGet("/", x => x.Response.WriteAsync("It Works!"));
+
+await app.RunAsync();
diff --git a/src/Place.API/Properties/launchSettings.json b/src/Place.API/Properties/launchSettings.json
new file mode 100644
index 0000000..009f40e
--- /dev/null
+++ b/src/Place.API/Properties/launchSettings.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "http://localhost:5059",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "https://localhost:7076;http://localhost:5059",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/Place.API/appsettings.Development.json b/src/Place.API/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/src/Place.API/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/src/Place.API/appsettings.json b/src/Place.API/appsettings.json
new file mode 100644
index 0000000..e5c60dd
--- /dev/null
+++ b/src/Place.API/appsettings.json
@@ -0,0 +1,62 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "apiVersioning": {
+ "enabled": true,
+ "defaultVersion": "1.0",
+ "assumeDefaultVersionWhenUnspecified": true,
+ "reportApiVersions": true,
+ "addVersionParamToNeutralEndpoints": false,
+ "versionReaderType": "UrlSegment",
+ "headerName": "X-Api-Version",
+ "queryStringParam": "api-version",
+ "mediaTypeParam": "v"
+ },
+ "swagger": {
+ "enabled": true,
+ "title": "My API",
+ "versions": [
+ "1.0",
+ "2.0"
+ ],
+ "useAuthentication": true,
+ "enableDownload": true,
+ "useSwaggerUI": true,
+ "useReDoc": true,
+ "swaggerUIRoute": "swagger",
+ "reDocRoute": "api-docs",
+ "uiOptions": {
+ "docExpansion": "List",
+ "defaultModelsExpandDepth": 1
+ }
+ },
+ "app": {
+ "name": "Place API Root"
+ },
+ "ConnectionStrings": {
+ "Account": "Server=localhost;Port=5490;Database=profile_db;User Id=postgres;Password=postgres;Include Error Detail=true",
+ "Identity": "Server=localhost;Port=5490;Database=identity_db;User Id=postgres;Password=postgres;Include Error Detail=true"
+ },
+ "Serilog": {
+ "applicationName": "identity-service",
+ "excludePaths": ["/ping", "/metrics"],
+ "level": "information",
+ "console": {
+ "enabled": true
+ },
+ "file": {
+ "enabled": true,
+ "path": "logs/logs.txt",
+ "interval": "day"
+ },
+ "seq": {
+ "enabled": true,
+ "url": "http://localhost:5341",
+ "token": "secret"
+ }
+ }
+}
diff --git a/tests/Account.IntegrationTests/Common/ProfileWebAppFactory.cs b/tests/Account.IntegrationTests/Common/ProfileWebAppFactory.cs
index 230f31f..7760195 100755
--- a/tests/Account.IntegrationTests/Common/ProfileWebAppFactory.cs
+++ b/tests/Account.IntegrationTests/Common/ProfileWebAppFactory.cs
@@ -19,7 +19,7 @@ namespace Account.IntegrationTests.Common;
[CollectionDefinition(nameof(ProfileApiCollection))]
public class ProfileApiCollection : ICollectionFixture { }
-public class ProfileWebAppFactory : WebApplicationFactory, IAsyncLifetime
+public class ProfileWebAppFactory : WebApplicationFactory, IAsyncLifetime
{
private readonly PostgreSqlContainer _dbContainer = default!;
private Respawner? _respawner = default!;
diff --git a/tests/Identity.IntegrationTests/IdentityWebAppFactory.cs b/tests/Identity.IntegrationTests/IdentityWebAppFactory.cs
index 94b5ff7..fe32e64 100755
--- a/tests/Identity.IntegrationTests/IdentityWebAppFactory.cs
+++ b/tests/Identity.IntegrationTests/IdentityWebAppFactory.cs
@@ -17,7 +17,7 @@
namespace Identity.IntegrationTests;
-public class IdentityWebAppFactory : WebApplicationFactory, IAsyncLifetime
+public class IdentityWebAppFactory : WebApplicationFactory, IAsyncLifetime
{
private readonly PostgreSqlContainer _dbContainer;