Compare commits
	
		
			23 Commits
		
	
	
		
			feature/ad
			...
			a7aad12742
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a7aad12742 | |||
| 8c3f8f6402 | |||
| 739e9e9c85 | |||
| 927dedb357 | |||
| 8b2fa45fda | |||
| 9634b3f385 | |||
| f342ccdaff | |||
| 7769bf9e67 | |||
|   | 7e0fbc3b31 | ||
| 1c2272c6f3 | |||
| 2bab87fe8d | |||
| cd613cb5b8 | |||
| 39b415065a | |||
|   | 75962160af | ||
| 0f67d57bed | |||
| b3dec4a601 | |||
| 63173eac5a | |||
| d36e24cfbf | |||
| a2a2b6ef8d | |||
| 32131d032b | |||
| 35a0a01221 | |||
| 24a5fd28fb | |||
| 827e5ec270 | 
							
								
								
									
										17
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | **/bin/ | ||||||
|  | **/obj/ | ||||||
|  | **/.vs/ | ||||||
|  | **/.idea/ | ||||||
|  | **/.vscode/ | ||||||
|  | **/*.user | ||||||
|  | **/*.suo | ||||||
|  | **/*.swp | ||||||
|  | **/*.csproj.user | ||||||
|  | **/*.log | ||||||
|  | **/Properties/launchSettings.json | ||||||
|  | **/appsettings.Local.json | ||||||
|  | **/appsettings.*.Development.json | ||||||
|  | .git/ | ||||||
|  | .gitignore | ||||||
|  | Dockerfile | ||||||
|  | docker-compose*.yml | ||||||
| @@ -66,7 +66,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|             var result = await service.GetModuleById(_id, cancellationToken); |             var result = await service.GetModuleById(_id, cancellationToken); | ||||||
|  |  | ||||||
|             if (result == null) |             if (result == null) | ||||||
|                 return NotFound("Entity not found"); |                 return NotFound("Module not found"); | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
| @@ -112,6 +112,10 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         public async Task<IActionResult> ChangeModuleStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) |         public async Task<IActionResult> ChangeModuleStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.ChangeModuleStatus(_id, newStatus, cancellationToken); |             var result = await service.ChangeModuleStatus(_id, newStatus, cancellationToken); | ||||||
|  |  | ||||||
|  |             if (result == null) | ||||||
|  |                 return NotFound("Module not found"); | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -133,7 +137,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         { |         { | ||||||
|             var result = await service.DeleteModule(_id, cancellationToken); |             var result = await service.DeleteModule(_id, cancellationToken); | ||||||
|             if (result == null) |             if (result == null) | ||||||
|                 return NotFound("Entity not found"); |                 return NotFound("Module not found"); | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ using Core.Thalos.BuildingBlocks; | |||||||
| using Core.Thalos.Provider.Contracts; | using Core.Thalos.Provider.Contracts; | ||||||
| using Microsoft.AspNetCore.Authorization; | using Microsoft.AspNetCore.Authorization; | ||||||
| using Microsoft.AspNetCore.Mvc; | using Microsoft.AspNetCore.Mvc; | ||||||
| using Microsoft.Graph; |  | ||||||
| using PermissionRequest = Core.Thalos.Domain.Contexts.Onboarding.Request.PermissionRequest; | using PermissionRequest = Core.Thalos.Domain.Contexts.Onboarding.Request.PermissionRequest; | ||||||
| using StatusEnum = Core.Blueprint.Mongo.StatusEnum; | using StatusEnum = Core.Blueprint.Mongo.StatusEnum; | ||||||
|  |  | ||||||
| @@ -91,7 +90,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|  |  | ||||||
|             if (result == null) |             if (result == null) | ||||||
|             { |             { | ||||||
|                 return NotFound("Entity not found"); |                 return NotFound("Permission not found"); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
| @@ -162,6 +161,10 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         public async Task<IActionResult> ChangePermissionStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) |         public async Task<IActionResult> ChangePermissionStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.ChangePermissionStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); |             var result = await service.ChangePermissionStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); | ||||||
|  |  | ||||||
|  |             if (result == null) | ||||||
|  |                 return NotFound("Permission not found"); | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -60,7 +60,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|  |  | ||||||
|             if (result == null) |             if (result == null) | ||||||
|             { |             { | ||||||
|                 return NotFound("Entity not found"); |                 return NotFound("Role not found"); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
| @@ -126,6 +126,10 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         public async Task<IActionResult> ChangeRoleStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) |         public async Task<IActionResult> ChangeRoleStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.ChangeRoleStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); |             var result = await service.ChangeRoleStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); | ||||||
|  |  | ||||||
|  |             if (result == null) | ||||||
|  |                 return NotFound("Role not found"); | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
| using Asp.Versioning; | using Asp.Versioning; | ||||||
| using Core.Thalos.BuildingBlocks; | using Core.Thalos.BuildingBlocks; | ||||||
| using Core.Thalos.Provider.Contracts; | using Core.Thalos.Provider.Contracts; | ||||||
|  | using Microsoft.AspNetCore.Authorization; | ||||||
| using Microsoft.AspNetCore.Mvc; | using Microsoft.AspNetCore.Mvc; | ||||||
| using StatusEnum = Core.Blueprint.Mongo.StatusEnum; | using StatusEnum = Core.Blueprint.Mongo.StatusEnum; | ||||||
| using TenantRequest = Core.Thalos.Domain.Contexts.Onboarding.Request.TenantRequest; | using TenantRequest = Core.Thalos.Domain.Contexts.Onboarding.Request.TenantRequest; | ||||||
| @@ -21,7 +22,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|     [Produces(MimeTypes.ApplicationJson)] |     [Produces(MimeTypes.ApplicationJson)] | ||||||
|     [Consumes(MimeTypes.ApplicationJson)] |     [Consumes(MimeTypes.ApplicationJson)] | ||||||
|     [ApiController] |     [ApiController] | ||||||
|     // [Authorize(AuthenticationSchemes = Schemes.DefaultScheme)] |     [Authorize(AuthenticationSchemes = Schemes.DefaultScheme)] | ||||||
|     public class TenantController(ITenantProvider service) : ControllerBase |     public class TenantController(ITenantProvider service) : ControllerBase | ||||||
|     { |     { | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -35,7 +36,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         [Consumes(MimeTypes.ApplicationJson)] |         [Consumes(MimeTypes.ApplicationJson)] | ||||||
|         [Produces(MimeTypes.ApplicationJson)] |         [Produces(MimeTypes.ApplicationJson)] | ||||||
|         [ProducesResponseType(typeof(IEnumerable<TenantAdapter>), StatusCodes.Status200OK)] |         [ProducesResponseType(typeof(IEnumerable<TenantAdapter>), StatusCodes.Status200OK)] | ||||||
|         // [Permission("TenantManagement.Read, RoleManagement.Read")] |         [Permission("TenantManagement.Read, RoleManagement.Read")] | ||||||
|         public async Task<IActionResult> GetAllTenantsAsync(CancellationToken cancellationToken) |         public async Task<IActionResult> GetAllTenantsAsync(CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.GetAllTenants(cancellationToken).ConfigureAwait(false); |             var result = await service.GetAllTenants(cancellationToken).ConfigureAwait(false); | ||||||
| @@ -56,14 +57,14 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         [Consumes(MimeTypes.ApplicationJson)] |         [Consumes(MimeTypes.ApplicationJson)] | ||||||
|         [Produces(MimeTypes.ApplicationJson)] |         [Produces(MimeTypes.ApplicationJson)] | ||||||
|         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] |         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] | ||||||
|         // [Permission("TenantManagement.Read")] |         [Permission("TenantManagement.Read")] | ||||||
|         public async Task<IActionResult> GetTenantByIdAsync([FromRoute] string _id, CancellationToken cancellationToken) |         public async Task<IActionResult> GetTenantByIdAsync([FromRoute] string _id, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.GetTenantById(_id, cancellationToken).ConfigureAwait(false); |             var result = await service.GetTenantById(_id, cancellationToken).ConfigureAwait(false); | ||||||
|  |  | ||||||
|             if (result == null) |             if (result == null) | ||||||
|             { |             { | ||||||
|                 return NotFound("Entity not found"); |                 return NotFound("Tenant not found"); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
| @@ -80,7 +81,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         /// <response code="500">The service internal error.</response> |         /// <response code="500">The service internal error.</response> | ||||||
|         [HttpPost] |         [HttpPost] | ||||||
|         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status201Created)] |         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status201Created)] | ||||||
|         // [Permission("TenantManagement.Write")] |         [Permission("TenantManagement.Write")] | ||||||
|         public async Task<IActionResult> CreateTenantAsync([FromBody] TenantRequest newTenant, CancellationToken cancellationToken) |         public async Task<IActionResult> CreateTenantAsync([FromBody] TenantRequest newTenant, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.CreateTenant(newTenant, cancellationToken).ConfigureAwait(false); |             var result = await service.CreateTenant(newTenant, cancellationToken).ConfigureAwait(false); | ||||||
| @@ -103,7 +104,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         [Consumes(MimeTypes.ApplicationJson)] |         [Consumes(MimeTypes.ApplicationJson)] | ||||||
|         [Produces(MimeTypes.ApplicationJson)] |         [Produces(MimeTypes.ApplicationJson)] | ||||||
|         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] |         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] | ||||||
|         // [Permission("TenantManagement.Write")] |         [Permission("TenantManagement.Write")] | ||||||
|         public async Task<IActionResult> UpdateTenantAsync([FromRoute] string _id, [FromBody] TenantAdapter entity, CancellationToken cancellationToken) |         public async Task<IActionResult> UpdateTenantAsync([FromRoute] string _id, [FromBody] TenantAdapter entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             if (_id != entity._Id) |             if (_id != entity._Id) | ||||||
| @@ -112,7 +113,9 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             var result = await service.UpdateTenant(entity, cancellationToken).ConfigureAwait(false); |             var result = await service.UpdateTenant(entity, cancellationToken).ConfigureAwait(false); | ||||||
|             return Ok(result); |  | ||||||
|  |             if (result is not null) return Ok(result); | ||||||
|  |             else return NotFound("Tenant not found"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -129,10 +132,14 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         [Consumes(MimeTypes.ApplicationJson)] |         [Consumes(MimeTypes.ApplicationJson)] | ||||||
|         [Produces(MimeTypes.ApplicationJson)] |         [Produces(MimeTypes.ApplicationJson)] | ||||||
|         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] |         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] | ||||||
|         // [Permission("TenantManagement.Write")] |         [Permission("TenantManagement.Write")] | ||||||
|         public async Task<IActionResult> ChangeTenantStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) |         public async Task<IActionResult> ChangeTenantStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.ChangeTenantStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); |             var result = await service.ChangeTenantStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); | ||||||
|  |  | ||||||
|  |             if (result == null) | ||||||
|  |                 return NotFound("Tenant not found"); | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -148,7 +155,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         [HttpDelete] |         [HttpDelete] | ||||||
|         [Route(Routes.Id)] |         [Route(Routes.Id)] | ||||||
|         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] |         [ProducesResponseType(typeof(TenantAdapter), StatusCodes.Status200OK)] | ||||||
|         // [Permission("TenantManagement.Write")] |         [Permission("TenantManagement.Write")] | ||||||
|         public async Task<IActionResult> DeleteTenantAsync([FromRoute] string _id, CancellationToken cancellationToken) |         public async Task<IActionResult> DeleteTenantAsync([FromRoute] string _id, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.DeleteTenant(_id, cancellationToken).ConfigureAwait(false); |             var result = await service.DeleteTenant(_id, cancellationToken).ConfigureAwait(false); | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ using Core.Thalos.BuildingBlocks; | |||||||
| using Core.Thalos.Provider.Contracts; | using Core.Thalos.Provider.Contracts; | ||||||
| using Microsoft.AspNetCore.Authorization; | using Microsoft.AspNetCore.Authorization; | ||||||
| using Microsoft.AspNetCore.Mvc; | using Microsoft.AspNetCore.Mvc; | ||||||
| using Microsoft.Graph; |  | ||||||
| using StatusEnum = Core.Blueprint.Mongo.StatusEnum; | using StatusEnum = Core.Blueprint.Mongo.StatusEnum; | ||||||
| using UserRequest = Core.Thalos.Domain.Contexts.Onboarding.Request.UserRequest; | using UserRequest = Core.Thalos.Domain.Contexts.Onboarding.Request.UserRequest; | ||||||
|  |  | ||||||
| @@ -54,7 +53,7 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         public async Task<IActionResult> GetUserById([FromRoute] string _id, CancellationToken cancellationToken) |         public async Task<IActionResult> GetUserById([FromRoute] string _id, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.GetUserById(_id, cancellationToken).ConfigureAwait(false); |             var result = await service.GetUserById(_id, cancellationToken).ConfigureAwait(false); | ||||||
|             return result == null ? NotFound("Entity not found") : Ok(result); |             return result == null ? NotFound("User not found") : Ok(result); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -171,6 +170,10 @@ namespace LSA.Core.Thalos.API.Controllers | |||||||
|         public async Task<IActionResult> ChangeUserStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) |         public async Task<IActionResult> ChangeUserStatus([FromRoute] string _id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.ChangeUserStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); |             var result = await service.ChangeUserStatus(_id, newStatus, cancellationToken).ConfigureAwait(false); | ||||||
|  |  | ||||||
|  |             if (result == null) | ||||||
|  |                 return NotFound("User not found"); | ||||||
|  |  | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Core.Blueprint.Logging" Version="1.0.1" /> |     <PackageReference Include="Core.Blueprint.Logging" Version="1.0.0" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
| @@ -0,0 +1,31 @@ | |||||||
|  | using Microsoft.Extensions.Diagnostics.HealthChecks; | ||||||
|  | using MongoDB.Bson; | ||||||
|  | using MongoDB.Driver; | ||||||
|  |  | ||||||
|  | namespace Core.Thalos.DAL.API.HealthCheck | ||||||
|  | { | ||||||
|  |     public class MongoConnectionHealthCheck(string connectionString, string databaseName) : IHealthCheck | ||||||
|  |     { | ||||||
|  |  | ||||||
|  |         public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) | ||||||
|  |         { | ||||||
|  |             var settings = MongoClientSettings.FromConnectionString(connectionString); | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 var mongoClient = new MongoClient(settings); | ||||||
|  |  | ||||||
|  |                 var database = mongoClient.GetDatabase(databaseName); | ||||||
|  |                 var command = new BsonDocument("ping", 1); | ||||||
|  |  | ||||||
|  |                 await database.RunCommandAsync<BsonDocument>(command); | ||||||
|  |  | ||||||
|  |                 return HealthCheckResult.Healthy($"MongoDB is healthy, {databaseName} database from {settings.Server} is reachable."); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 return HealthCheckResult.Degraded($"MongoDB is Degraded, {databaseName} database from {settings?.Server?.Host} is unreachable.", ex); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | using Microsoft.Extensions.Diagnostics.HealthChecks; | ||||||
|  | using StackExchange.Redis; | ||||||
|  |  | ||||||
|  | public sealed class RedisConnectionHealthCheck : IHealthCheck | ||||||
|  | { | ||||||
|  |     private readonly string _connectionString; | ||||||
|  |     public RedisConnectionHealthCheck(string connectionString) => _connectionString = connectionString; | ||||||
|  |  | ||||||
|  |     public async Task<HealthCheckResult> CheckHealthAsync( | ||||||
|  |         HealthCheckContext context, | ||||||
|  |         CancellationToken cancellationToken = default) | ||||||
|  |     { | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             var options = ConfigurationOptions.Parse(_connectionString); | ||||||
|  |             options.AbortOnConnectFail = false; | ||||||
|  |             options.ConnectTimeout = 2000;   // optional, be snappy | ||||||
|  |  | ||||||
|  |             using var mux = await ConnectionMultiplexer.ConnectAsync(options); | ||||||
|  |             if (!mux.IsConnected) return HealthCheckResult.Unhealthy("Redis not connected."); | ||||||
|  |  | ||||||
|  |             var ping = await mux.GetDatabase().PingAsync(); | ||||||
|  |             return HealthCheckResult.Healthy($"Redis OK (ping {ping.TotalMilliseconds:N0} ms)"); | ||||||
|  |         } | ||||||
|  |         catch (Exception ex) | ||||||
|  |         { | ||||||
|  |             return HealthCheckResult.Unhealthy("Redis check failed.", ex); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,50 @@ | |||||||
|  | using Microsoft.Extensions.Diagnostics.HealthChecks; | ||||||
|  | using System.Text.Json; | ||||||
|  |  | ||||||
|  | namespace Core.Thalos.DAL.API.HealthCheck.Writer | ||||||
|  | { | ||||||
|  |     public static class HealthCheckResponseWriter | ||||||
|  |     { | ||||||
|  |         public static Task WriteResponse(HttpContext context, HealthReport result) | ||||||
|  |         { | ||||||
|  |             context.Response.ContentType = "application/json"; | ||||||
|  |  | ||||||
|  |             context.Response.StatusCode = result.Status switch | ||||||
|  |             { | ||||||
|  |                 HealthStatus.Healthy => StatusCodes.Status200OK, | ||||||
|  |                 HealthStatus.Degraded => StatusCodes.Status500InternalServerError, | ||||||
|  |                 HealthStatus.Unhealthy => StatusCodes.Status503ServiceUnavailable, | ||||||
|  |                 _ => StatusCodes.Status500InternalServerError | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             var options = new JsonSerializerOptions | ||||||
|  |             { | ||||||
|  |                 WriteIndented = true, | ||||||
|  |                 PropertyNamingPolicy = JsonNamingPolicy.CamelCase | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             var json = new | ||||||
|  |             { | ||||||
|  |                 status = result.Status.ToString(), | ||||||
|  |                 services = result.Entries.Select(e => new | ||||||
|  |                 { | ||||||
|  |                     key = e.Key, | ||||||
|  |                     status = e.Value.Status.ToString(), | ||||||
|  |                     description = e.Value.Description ?? string.Empty, | ||||||
|  |                     exception = e.Value.Exception?.Message, | ||||||
|  |                     duration = e.Value.Duration.ToString(), | ||||||
|  |  | ||||||
|  |                     statusCode = e.Value.Status switch | ||||||
|  |                     { | ||||||
|  |                         HealthStatus.Healthy => StatusCodes.Status200OK, | ||||||
|  |                         HealthStatus.Degraded => StatusCodes.Status500InternalServerError, | ||||||
|  |                         HealthStatus.Unhealthy => StatusCodes.Status503ServiceUnavailable, | ||||||
|  |                         _ => StatusCodes.Status500InternalServerError | ||||||
|  |                     } | ||||||
|  |                 }) | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             return context.Response.WriteAsync(JsonSerializer.Serialize(json, options)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -4,8 +4,12 @@ using Core.Blueprint.Logging.Configuration; | |||||||
| using Core.Blueprint.Redis.Configuration; | using Core.Blueprint.Redis.Configuration; | ||||||
| using Core.Thalos.BuildingBlocks; | using Core.Thalos.BuildingBlocks; | ||||||
| using Core.Thalos.BuildingBlocks.Configuration; | using Core.Thalos.BuildingBlocks.Configuration; | ||||||
|  | using Core.Thalos.DAL.API.HealthCheck; | ||||||
|  | using Core.Thalos.DAL.API.HealthCheck.Writer; | ||||||
| using Core.Thalos.Provider; | using Core.Thalos.Provider; | ||||||
|  | using Microsoft.AspNetCore.Diagnostics.HealthChecks; | ||||||
| using Microsoft.AspNetCore.HttpLogging; | using Microsoft.AspNetCore.HttpLogging; | ||||||
|  | using Microsoft.Extensions.Diagnostics.HealthChecks; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
| using System.Text.Json.Serialization; | using System.Text.Json.Serialization; | ||||||
|  |  | ||||||
| @@ -64,6 +68,21 @@ builder.Host.ConfigureServices((context, services) => | |||||||
|     }); |     }); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | // Add health checks | ||||||
|  | builder.Services.AddHealthChecks() | ||||||
|  |     .AddCheck( | ||||||
|  |         "mongodb", | ||||||
|  |         new MongoConnectionHealthCheck( | ||||||
|  |             connectionString: builder.Configuration.GetConnectionString("MongoDB")!, | ||||||
|  |             databaseName: builder.Configuration.GetSection("MongoDb:DatabaseName").Value!), | ||||||
|  |         failureStatus: HealthStatus.Unhealthy, | ||||||
|  |         tags: new[] { "db", "mongo" }) | ||||||
|  |     .AddCheck( | ||||||
|  |         "redis", | ||||||
|  |         new RedisConnectionHealthCheck(builder.Configuration.GetConnectionString("Redis")!), | ||||||
|  |         failureStatus: HealthStatus.Unhealthy, | ||||||
|  |         tags: new[] { "db", "redis" }); | ||||||
|  |  | ||||||
| var app = builder.Build(); | var app = builder.Build(); | ||||||
|  |  | ||||||
| app.UseLogging(builder.Configuration); | app.UseLogging(builder.Configuration); | ||||||
| @@ -82,6 +101,10 @@ app.UseAuthentication(); | |||||||
| app.UseAuthorization(); | app.UseAuthorization(); | ||||||
|  |  | ||||||
| app.MapControllers(); | app.MapControllers(); | ||||||
| app.MapHealthChecks("/health"); | app.MapHealthChecks("/health", new HealthCheckOptions | ||||||
|  | { | ||||||
|  |     ResponseWriter = HealthCheckResponseWriter.WriteResponse, | ||||||
|  |     AllowCachingResponses = false | ||||||
|  | }); | ||||||
|  |  | ||||||
| app.Run(); | app.Run(); | ||||||
| @@ -24,7 +24,7 @@ | |||||||
|       "dotnetRunMessages": true, |       "dotnetRunMessages": true, | ||||||
|       "launchBrowser": true, |       "launchBrowser": true, | ||||||
|       "launchUrl": "swagger", |       "launchUrl": "swagger", | ||||||
|       "applicationUrl": "https://localhost:7031;http://localhost:5211", |       "applicationUrl": "https://localhost:44359;http://localhost:5211", | ||||||
|       "environmentVariables": { |       "environmentVariables": { | ||||||
|         "ASPNETCORE_ENVIRONMENT": "Local" |         "ASPNETCORE_ENVIRONMENT": "Local" | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -7,15 +7,16 @@ | |||||||
|   }, |   }, | ||||||
|   "AllowedHosts": "*", |   "AllowedHosts": "*", | ||||||
|   "ConnectionStrings": { |   "ConnectionStrings": { | ||||||
|     "MongoDB": "mongodb://admin_agile:Admin%40agileWebs@portainer.white-enciso.pro:27017/?authMechanism=SCRAM-SHA-256", |     "MongoDB": "mongodb://admin_agile:AdminAgileWebs@portainer.dream-views.com:27017/?authMechanism=SCRAM-SHA-256", | ||||||
|     "Redis": "100.123.31.103:6379" |     //"MongoDB": "mongodb://admin_agile:Admin%40agileWebs@portainer.white-enciso.pro:27017/?authMechanism=SCRAM-SHA-256", | ||||||
|  |     "Redis": "172.22.0.2:6379" | ||||||
|   }, |   }, | ||||||
|   "MongoDb": { |   "MongoDb": { | ||||||
|     "DatabaseName": "Thalos", |     "DatabaseName": "Thalos", | ||||||
|     "LocalAudience": "" |     "LocalAudience": "" | ||||||
|   }, |   }, | ||||||
|   "DetailedErrors": true, |   "DetailedErrors": true, | ||||||
|   "UseRedisCache": true, |   "UseRedisCache": false, | ||||||
|   "CacheSettings": { |   "CacheSettings": { | ||||||
|     "DefaultCacheDurationInMinutes": 3 |     "DefaultCacheDurationInMinutes": 3 | ||||||
|   }, |   }, | ||||||
| @@ -24,12 +25,12 @@ | |||||||
|     "LayerName": "dal" |     "LayerName": "dal" | ||||||
|   }, |   }, | ||||||
|   "Vault": { |   "Vault": { | ||||||
|     "Address": "http://100.123.31.103:8200", |     "Address": "https://vault.dream-views.com/", | ||||||
|     "Token": "hvs.e37LQvLuPhTd5ALS5QQ03Cwm", |     "Token": "hvs.TGz6P3AsKpYuODMrs11Msiza", | ||||||
|     "SecretMount": "secret" |     "SecretMount": "thalos" | ||||||
|   }, |   }, | ||||||
|   "IdentityProviders": { |   "IdentityProviders": { | ||||||
|     "Google": true, |     "Google": true, | ||||||
|     "Azure":  true |     "Azure": false | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -54,5 +54,13 @@ namespace Core.Thalos.Domain.Contexts.Onboarding.Request | |||||||
|         [BsonRepresentation(BsonType.ObjectId)] |         [BsonRepresentation(BsonType.ObjectId)] | ||||||
|         [JsonPropertyName("roleId")] |         [JsonPropertyName("roleId")] | ||||||
|         public string RoleId { get; set; } = null!; |         public string RoleId { get; set; } = null!; | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets or sets the tenant ID of the user. | ||||||
|  |         /// </summary> | ||||||
|  |         [BsonElement("tenantId")] | ||||||
|  |         [BsonRepresentation(BsonType.ObjectId)] | ||||||
|  |         [JsonPropertyName("tenantId")] | ||||||
|  |         public string TenantId { get; set; } = null!; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,8 +7,8 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Core.Blueprint.KeyVault" Version="1.0.3" /> |     <PackageReference Include="Core.Blueprint.KeyVault" Version="1.0.0" /> | ||||||
|     <PackageReference Include="Core.Thalos.BuildingBlocks" Version="1.1.1" /> |     <PackageReference Include="Core.Thalos.BuildingBlocks" Version="1.0.5" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<ModuleAdapter> ChangeModuleStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); |         ValueTask<ModuleAdapter?> ChangeModuleStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Updates a Module by its identifier. |         /// Updates a Module by its identifier. | ||||||
| @@ -72,7 +72,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<ModuleAdapter> UpdateModule(ModuleAdapter entity, CancellationToken cancellationToken); |         ValueTask<ModuleAdapter?> UpdateModule(ModuleAdapter entity, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Deletes a Module by its identifier. |         /// Deletes a Module by its identifier. | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<PermissionAdapter> ChangePermissionStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); |         ValueTask<PermissionAdapter?> ChangePermissionStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Updates a Permission. |         /// Updates a Permission. | ||||||
| @@ -72,7 +72,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<PermissionAdapter> UpdatePermission(PermissionAdapter entity, CancellationToken cancellationToken); |         ValueTask<PermissionAdapter?> UpdatePermission(PermissionAdapter entity, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Deletes a Permission by its identifier. |         /// Deletes a Permission by its identifier. | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<RoleAdapter> ChangeRoleStatus(string _id, Core.Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); |         ValueTask<RoleAdapter?> ChangeRoleStatus(string _id, Core.Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Updates a Role. |         /// Updates a Role. | ||||||
| @@ -62,7 +62,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<RoleAdapter> UpdateRole(RoleAdapter entity, CancellationToken cancellationToken); |         ValueTask<RoleAdapter?> UpdateRole(RoleAdapter entity, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Adds an application to the Role's list of applications. |         /// Adds an application to the Role's list of applications. | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<TenantAdapter> ChangeTenantStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); |         ValueTask<TenantAdapter?> ChangeTenantStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Updates a Tenant. |         /// Updates a Tenant. | ||||||
| @@ -62,7 +62,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<TenantAdapter> UpdateTenant(TenantAdapter entity, CancellationToken cancellationToken); |         ValueTask<TenantAdapter?> UpdateTenant(TenantAdapter entity, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Deletes a Tenant by its identifier. |         /// Deletes a Tenant by its identifier. | ||||||
|   | |||||||
| @@ -72,7 +72,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{UserAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{UserAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<UserAdapter> ChangeUserStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); |         ValueTask<UserAdapter?> ChangeUserStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Updates a User. |         /// Updates a User. | ||||||
| @@ -82,7 +82,7 @@ namespace Core.Thalos.Provider.Contracts | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{UserAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{UserAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         ValueTask<UserAdapter> UpdateUser(UserAdapter entity, CancellationToken cancellationToken); |         ValueTask<UserAdapter?> UpdateUser(UserAdapter entity, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Logs in the User. |         /// Logs in the User. | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Core.Blueprint.Mongo" Version="1.0.0" /> |     <PackageReference Include="Core.Blueprint.Mongo" Version="1.0.0" /> | ||||||
|     <PackageReference Include="Core.Blueprint.Redis" Version="1.0.2" /> |     <PackageReference Include="Core.Blueprint.Redis" Version="1.0.0" /> | ||||||
|     <PackageReference Include="Mapster" Version="7.4.2-pre02" /> |     <PackageReference Include="Mapster" Version="7.4.2-pre02" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -131,12 +131,17 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<ModuleAdapter> ChangeModuleStatus(string _id, StatusEnum newStatus, CancellationToken cancellationToken) |         public async ValueTask<ModuleAdapter?> ChangeModuleStatus(string _id, StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var entity = await repository.FindByIdAsync(_id); |             var entity = await repository.FindByIdAsync(_id); | ||||||
|             entity.Status = newStatus; |  | ||||||
|             await repository.ReplaceOneAsync(entity); |             if (entity is not null) | ||||||
|             return entity; |             { | ||||||
|  |                 entity.Status = newStatus; | ||||||
|  |  | ||||||
|  |                 return repository.ReplaceOneAsync(entity).Result; | ||||||
|  |             } | ||||||
|  |             else return null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -147,10 +152,10 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{ModuleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<ModuleAdapter> UpdateModule(ModuleAdapter entity, CancellationToken cancellationToken) |         public async ValueTask<ModuleAdapter?> UpdateModule(ModuleAdapter entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             await repository.ReplaceOneAsync(entity); |             var updatedEntity = await repository.ReplaceOneAsync(entity); | ||||||
|             return entity; |             return updatedEntity; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|   | |||||||
| @@ -130,12 +130,17 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<PermissionAdapter> ChangePermissionStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) |         public async ValueTask<PermissionAdapter?> ChangePermissionStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var entity = await repository.FindByIdAsync(_id); |             var entity = await repository.FindByIdAsync(_id); | ||||||
|             entity.Status = newStatus; |  | ||||||
|             await repository.ReplaceOneAsync(entity); |             if (entity is not null) | ||||||
|             return entity; |             { | ||||||
|  |                 entity.Status = newStatus; | ||||||
|  |  | ||||||
|  |                 return repository.ReplaceOneAsync(entity).Result; | ||||||
|  |             } | ||||||
|  |             else return null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -146,10 +151,10 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{PermissionAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<PermissionAdapter> UpdatePermission(PermissionAdapter entity, CancellationToken cancellationToken) |         public async ValueTask<PermissionAdapter?> UpdatePermission(PermissionAdapter entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             await repository.ReplaceOneAsync(entity); |             var updatedEntity = await repository.ReplaceOneAsync(entity); | ||||||
|             return entity; |             return updatedEntity; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|   | |||||||
| @@ -100,13 +100,17 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<RoleAdapter> ChangeRoleStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) |         public async ValueTask<RoleAdapter?> ChangeRoleStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var entity = await repository.FindByIdAsync(_id); |             var entity = await repository.FindByIdAsync(_id); | ||||||
|             entity.Status = newStatus; |  | ||||||
|  |  | ||||||
|             await repository.ReplaceOneAsync(entity); |             if (entity is not null) | ||||||
|             return entity; |             { | ||||||
|  |                 entity.Status = newStatus; | ||||||
|  |  | ||||||
|  |                 return repository.ReplaceOneAsync(entity).Result; | ||||||
|  |             } | ||||||
|  |             else return null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -117,10 +121,10 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{RoleAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<RoleAdapter> UpdateRole(RoleAdapter entity, CancellationToken cancellationToken) |         public async ValueTask<RoleAdapter?> UpdateRole(RoleAdapter entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             await repository.ReplaceOneAsync(entity); |             var updatedEntity = await repository.ReplaceOneAsync(entity); | ||||||
|             return entity; |             return updatedEntity; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|   | |||||||
| @@ -99,13 +99,17 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<TenantAdapter> ChangeTenantStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) |         public async ValueTask<TenantAdapter?> ChangeTenantStatus(string _id, Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var entity = await repository.FindByIdAsync(_id); |             var entity = await repository.FindByIdAsync(_id); | ||||||
|             entity.Status = newStatus; |  | ||||||
|  |  | ||||||
|             await repository.ReplaceOneAsync(entity); |             if (entity is not null) | ||||||
|             return entity; |             { | ||||||
|  |                 entity.Status = newStatus; | ||||||
|  |  | ||||||
|  |                 return repository.ReplaceOneAsync(entity).Result; | ||||||
|  |             } | ||||||
|  |             else return null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -116,10 +120,10 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. |         /// A <see cref="ValueTask{TenantAdapter}"/> representing the asynchronous execution of the service. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         public async ValueTask<TenantAdapter> UpdateTenant(TenantAdapter entity, CancellationToken cancellationToken) |         public async ValueTask<TenantAdapter?> UpdateTenant(TenantAdapter entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             await repository.ReplaceOneAsync(entity); |             var updatedEntity = await repository.ReplaceOneAsync(entity); | ||||||
|             return entity; |             return updatedEntity; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllUsers"); |             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllUsers"); | ||||||
|             var cachedData = await cacheProvider.GetAsync<IEnumerable<UserAdapter>>(cacheKey) ?? []; |             var cachedData = await cacheProvider.GetAsync<IEnumerable<UserAdapter>>(cacheKey) ?? []; | ||||||
|  |  | ||||||
|             //if (cachedData.Any()) return cachedData; |             if (cachedData.Any()) return cachedData; | ||||||
|  |  | ||||||
|             var users = await repository.AsQueryable(); |             var users = await repository.AsQueryable(); | ||||||
|  |  | ||||||
| @@ -146,14 +146,17 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <param name="newStatus">The new status of the user.</param> |         /// <param name="newStatus">The new status of the user.</param> | ||||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing |         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||||
|         /// the asynchronous execution of the service.</returns> |         /// the asynchronous execution of the service.</returns> | ||||||
|         public async ValueTask<UserAdapter> ChangeUserStatus(string _id, Core.Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) |         public async ValueTask<UserAdapter?> ChangeUserStatus(string _id, Core.Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var entity = await repository.FindByIdAsync(_id); |             var entity = await repository.FindByIdAsync(_id); | ||||||
|             entity.Status = newStatus; |  | ||||||
|  |  | ||||||
|             await repository.ReplaceOneAsync(entity); |             if (entity is not null) | ||||||
|  |             { | ||||||
|  |                 entity.Status = newStatus; | ||||||
|  |  | ||||||
|             return entity; |                 return repository.ReplaceOneAsync(entity).Result; | ||||||
|  |             } | ||||||
|  |             else return null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -163,11 +166,10 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|         /// <param name="_id">The User mongo identifier.</param> |         /// <param name="_id">The User mongo identifier.</param> | ||||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing |         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||||
|         /// the asynchronous execution of the service.</returns> |         /// the asynchronous execution of the service.</returns> | ||||||
|         public async ValueTask<UserAdapter> UpdateUser(UserAdapter entity, CancellationToken cancellationToken) |         public async ValueTask<UserAdapter?> UpdateUser(UserAdapter entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             await repository.ReplaceOneAsync(entity); |             var updatedEntity = await repository.ReplaceOneAsync(entity); | ||||||
|  |             return updatedEntity; | ||||||
|             return entity; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -219,116 +221,144 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|             { |             { | ||||||
|                 var pipeline = new[] |                 var pipeline = new[] | ||||||
|                 { |                 { | ||||||
|                     new BsonDocument("$match", new BsonDocument |             new BsonDocument("$match", new BsonDocument | ||||||
|  |             { | ||||||
|  |                 { "email", new BsonDocument | ||||||
|                     { |                     { | ||||||
|                         { "email", new BsonDocument |                         { "$regex", $"^{Regex.Escape(email)}$" }, | ||||||
|                             { |                         { "$options", "i" } | ||||||
|                                 { "$regex", $"^{Regex.Escape(email)}$" }, |                     } | ||||||
|                                 { "$options", "i" } |                 }, | ||||||
|                             } |                 { "status", Core.Blueprint.Mongo.StatusEnum.Active.ToString() } | ||||||
|                         }, |             }), | ||||||
|                         { "status", Core.Blueprint.Mongo.StatusEnum.Active.ToString() } |             new BsonDocument("$lookup", new BsonDocument | ||||||
|                     }), |             { | ||||||
|  |                 { "from", "Roles" }, | ||||||
|                     new BsonDocument("$lookup", new BsonDocument |                 { "localField", "roleId" }, | ||||||
|  |                 { "foreignField", "_id" }, | ||||||
|  |                 { "as", "role" } | ||||||
|  |             }), | ||||||
|  |             new BsonDocument("$unwind", "$role"), | ||||||
|  |             new BsonDocument("$match", new BsonDocument("role.status", Core.Blueprint.Mongo.StatusEnum.Active.ToString())), | ||||||
|  |             new BsonDocument("$lookup", new BsonDocument | ||||||
|  |             { | ||||||
|  |                 { "from", "Tenants" }, | ||||||
|  |                 { "localField", "tenantId" }, | ||||||
|  |                 { "foreignField", "_id" }, | ||||||
|  |                 { "as", "tenant" } | ||||||
|  |             }), | ||||||
|  |             new BsonDocument("$unwind", "$tenant"), | ||||||
|  |             new BsonDocument("$addFields", new BsonDocument | ||||||
|  |             { | ||||||
|  |                 { "role.permissions", new BsonDocument("$map", new BsonDocument | ||||||
|                     { |                     { | ||||||
|                         { "from", "Roles" }, |                         { "input", "$role.permissions" }, | ||||||
|                         { "localField", "roleId" }, |                         { "as", "perm" }, | ||||||
|                         { "foreignField", "_id" }, |                         { "in", new BsonDocument("$toObjectId", "$$perm") } | ||||||
|                         { "as", "role" } |  | ||||||
|                     }), |  | ||||||
|  |  | ||||||
|                     new BsonDocument("$unwind", "$role"), |  | ||||||
|                     new BsonDocument("$match", new BsonDocument("role.status", Core.Blueprint.Mongo.StatusEnum.Active.ToString())), |  | ||||||
|  |  | ||||||
|                     new BsonDocument("$addFields", new BsonDocument |  | ||||||
|                     { |  | ||||||
|                         { "role.permissions", new BsonDocument("$map", new BsonDocument |  | ||||||
|                             { |  | ||||||
|                                 { "input", "$role.permissions" }, |  | ||||||
|                                 { "as", "perm" }, |  | ||||||
|                                 { "in", new BsonDocument("$toObjectId", "$$perm") } |  | ||||||
|                             }) |  | ||||||
|                         }, |  | ||||||
|                         { "role.modules", new BsonDocument("$map", new BsonDocument |  | ||||||
|                             { |  | ||||||
|                                 { "input", "$role.modules" }, |  | ||||||
|                                 { "as", "mod" }, |  | ||||||
|                                 { "in", new BsonDocument("$toObjectId", "$$mod") } |  | ||||||
|                             }) |  | ||||||
|                         } |  | ||||||
|                     }), |  | ||||||
|  |  | ||||||
|                     new BsonDocument("$lookup", new BsonDocument |  | ||||||
|                     { |  | ||||||
|                         { "from", "Permissions" }, |  | ||||||
|                         { "localField", "role.permissions" }, |  | ||||||
|                         { "foreignField", "_id" }, |  | ||||||
|                         { "as", "permissions" } |  | ||||||
|                     }), |  | ||||||
|                     new BsonDocument("$lookup", new BsonDocument |  | ||||||
|                     { |  | ||||||
|                         { "from", "Modules" }, |  | ||||||
|                         { "localField", "role.modules" }, |  | ||||||
|                         { "foreignField", "_id" }, |  | ||||||
|                         { "as", "modules" } |  | ||||||
|                     }), |  | ||||||
|                     new BsonDocument("$project", new BsonDocument |  | ||||||
|                     { |  | ||||||
|                         { "_id", 1 }, |  | ||||||
|                         { "guid", 1 }, |  | ||||||
|                         { "email", 1 }, |  | ||||||
|                         { "name", 1 }, |  | ||||||
|                         { "middleName", 1 }, |  | ||||||
|                         { "lastName", 1 }, |  | ||||||
|                         { "displayName", 1 }, |  | ||||||
|                         { "roleId", 1 }, |  | ||||||
|                         { "companies", 1 }, |  | ||||||
|                         { "projects", 1 }, |  | ||||||
|                         { "lastLogIn", 1 }, |  | ||||||
|                         { "lastLogOut", 1 }, |  | ||||||
|                         { "createdBy", 1 }, |  | ||||||
|                         { "updatedBy", 1 }, |  | ||||||
|                         { "status", 1 }, |  | ||||||
|                         { "createdAt", 1 }, |  | ||||||
|                         { "updatedAt", 1 }, |  | ||||||
|                         { "role._id", 1 }, |  | ||||||
|                         { "role.name", 1 }, |  | ||||||
|                         { "role.description", 1 }, |  | ||||||
|                         { "role.applications", 1 }, |  | ||||||
|                         { "role.permissions", 1 }, |  | ||||||
|                         { "role.modules", 1 }, |  | ||||||
|                         { "role.status", 1 }, |  | ||||||
|                         { "role.createdAt", 1 }, |  | ||||||
|                         { "role.updatedAt", 1 }, |  | ||||||
|                         { "role.createdBy", 1 }, |  | ||||||
|                         { "role.updatedBy", 1 }, |  | ||||||
|                         { "permissions", 1 }, |  | ||||||
|                         { "modules", 1 } |  | ||||||
|                     }) |                     }) | ||||||
|                 }; |                 }, | ||||||
|  |                 { "role.modules", new BsonDocument("$map", new BsonDocument | ||||||
|  |                     { | ||||||
|  |                         { "input", "$role.modules" }, | ||||||
|  |                         { "as", "mod" }, | ||||||
|  |                         { "in", new BsonDocument("$toObjectId", "$$mod") } | ||||||
|  |                     }) | ||||||
|  |                 } | ||||||
|  |             }), | ||||||
|  |             new BsonDocument("$lookup", new BsonDocument | ||||||
|  |             { | ||||||
|  |                 { "from", "Permissions" }, | ||||||
|  |                 { "localField", "role.permissions" }, | ||||||
|  |                 { "foreignField", "_id" }, | ||||||
|  |                 { "as", "permissions" } | ||||||
|  |             }), | ||||||
|  |             new BsonDocument("$lookup", new BsonDocument | ||||||
|  |             { | ||||||
|  |                 { "from", "Modules" }, | ||||||
|  |                 { "localField", "role.modules" }, | ||||||
|  |                 { "foreignField", "_id" }, | ||||||
|  |                 { "as", "modules" } | ||||||
|  |             }), | ||||||
|  |             new BsonDocument("$project", new BsonDocument | ||||||
|  |             { | ||||||
|  |                 { "_id", 1 }, | ||||||
|  |                 { "guid", 1 }, | ||||||
|  |                 { "email", 1 }, | ||||||
|  |                 { "name", 1 }, | ||||||
|  |                 { "middleName", 1 }, | ||||||
|  |                 { "lastName", 1 }, | ||||||
|  |                 { "displayName", 1 }, | ||||||
|  |                 { "roleId", 1 }, | ||||||
|  |                 { "companies", 1 }, | ||||||
|  |                 { "projects", 1 }, | ||||||
|  |                 { "lastLogIn", 1 }, | ||||||
|  |                 { "lastLogOut", 1 }, | ||||||
|  |                 { "createdBy", 1 }, | ||||||
|  |                 { "updatedBy", 1 }, | ||||||
|  |                 { "status", 1 }, | ||||||
|  |                 { "createdAt", 1 }, | ||||||
|  |                 { "updatedAt", 1 }, | ||||||
|  |                 { "role._id", 1 }, | ||||||
|  |                 { "role.name", 1 }, | ||||||
|  |                 { "role.description", 1 }, | ||||||
|  |                 { "role.applications", 1 }, | ||||||
|  |                 { "role.permissions", 1 }, | ||||||
|  |                 { "role.modules", 1 }, | ||||||
|  |                 { "role.status", 1 }, | ||||||
|  |                 { "role.createdAt", 1 }, | ||||||
|  |                 { "role.updatedAt", 1 }, | ||||||
|  |                 { "role.createdBy", 1 }, | ||||||
|  |                 { "role.updatedBy", 1 }, | ||||||
|  |                 { "tenant._id", 1 }, | ||||||
|  |                 { "tenant.name", 1 }, | ||||||
|  |                 { "tenant.taxIdentifier", 1 }, | ||||||
|  |                 { "tenant.addressLine1", 1 }, | ||||||
|  |                 { "tenant.addressLine2", 1 }, | ||||||
|  |                 { "tenant.city", 1 }, | ||||||
|  |                 { "tenant.state", 1 }, | ||||||
|  |                 { "tenant.country", 1 }, | ||||||
|  |                 { "tenant.postalCode", 1 }, | ||||||
|  |                 { "tenant.contactEmail", 1 }, | ||||||
|  |                 { "tenant.contactPhone", 1 }, | ||||||
|  |                 { "tenant.website", 1 }, | ||||||
|  |                 { "tenant.connectionString", 1 }, | ||||||
|  |                 { "tenant.isolated", 1 }, | ||||||
|  |                 { "tenant.status", 1 }, | ||||||
|  |                 { "tenant.createdAt", 1 }, | ||||||
|  |                 { "tenant.updatedAt", 1 }, | ||||||
|  |                 { "tenant.createdBy", 1 }, | ||||||
|  |                 { "tenant.updatedBy", 1 }, | ||||||
|  |                 { "permissions", 1 }, | ||||||
|  |                 { "modules", 1 } | ||||||
|  |             }) | ||||||
|  |         }; | ||||||
|  |  | ||||||
|                 var result = await repository.FindOnePipelineAsync<BsonDocument>(pipeline); |                 var result = await repository.FindOnePipelineAsync<BsonDocument>(pipeline); | ||||||
|  |  | ||||||
|                 if (result is null) return null; |                 if (result is null) return null; | ||||||
|  |  | ||||||
|  |                 DateTime SafeToUtc(BsonValue value) | ||||||
|  |                 { | ||||||
|  |                     if (value == null || value.IsBsonNull) return DateTime.MinValue; | ||||||
|  |                     return value.IsBsonDateTime ? value.ToUniversalTime() : DateTime.MinValue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 var tokenAdapter = new TokenAdapter |                 var tokenAdapter = new TokenAdapter | ||||||
|                 { |                 { | ||||||
|                     User = new UserAdapter |                     User = new UserAdapter | ||||||
|                     { |                     { | ||||||
|                         Id = result["_id"]?.ToString() ?? "", |                         _Id = result["_id"]?.ToString() ?? "", | ||||||
|                         Guid = result.Contains("guid") && !result["guid"].IsBsonNull ? result["guid"].AsString : string.Empty, |  | ||||||
|                         Email = result.Contains("email") && !result["email"].IsBsonNull ? result["email"].AsString : string.Empty, |                         Email = result.Contains("email") && !result["email"].IsBsonNull ? result["email"].AsString : string.Empty, | ||||||
|                         Name = result.Contains("name") && !result["name"].IsBsonNull ? result["name"].AsString : string.Empty, |                         Name = result.Contains("name") && !result["name"].IsBsonNull ? result["name"].AsString : string.Empty, | ||||||
|                         MiddleName = result.Contains("middleName") && !result["middleName"].IsBsonNull ? result["middleName"].AsString : string.Empty, |                         MiddleName = result.Contains("middleName") && !result["middleName"].IsBsonNull ? result["middleName"].AsString : string.Empty, | ||||||
|                         LastName = result.Contains("lastName") && !result["lastName"].IsBsonNull ? result["lastName"].AsString : string.Empty, |                         LastName = result.Contains("lastName") && !result["lastName"].IsBsonNull ? result["lastName"].AsString : string.Empty, | ||||||
|                         DisplayName = result.Contains("displayName") && !result["displayName"].IsBsonNull ? result["displayName"].AsString : string.Empty, |                         DisplayName = result.Contains("displayName") && !result["displayName"].IsBsonNull ? result["displayName"].AsString : string.Empty, | ||||||
|                         RoleId = result.Contains("roleId") && !result["roleId"].IsBsonNull ? result["roleId"].ToString() : string.Empty, |                         RoleId = result.Contains("roleId") && !result["roleId"].IsBsonNull ? result["roleId"].ToString() : string.Empty, | ||||||
|                         LastLogIn = result.Contains("lastLogIn") && !result["lastLogIn"].IsBsonNull ? result["lastLogIn"].ToUniversalTime() : DateTime.MinValue, |                         LastLogIn = SafeToUtc(result.Contains("lastLogIn") ? result["lastLogIn"] : null), | ||||||
|                         LastLogOut = result.Contains("lastLogOut") && !result["lastLogOut"].IsBsonNull ? result["lastLogOut"].ToUniversalTime() : DateTime.MinValue, |                         LastLogOut = SafeToUtc(result.Contains("lastLogOut") ? result["lastLogOut"] : null), | ||||||
|                         CreatedAt = result.Contains("createdAt") && !result["createdAt"].IsBsonNull ? result["createdAt"].ToUniversalTime() : DateTime.MinValue, |                         CreatedAt = SafeToUtc(result.Contains("createdAt") ? result["createdAt"] : null), | ||||||
|  |                         UpdatedAt = SafeToUtc(result.Contains("updatedAt") ? result["updatedAt"] : null), | ||||||
|                         CreatedBy = result.Contains("createdBy") && !result["createdBy"].IsBsonNull ? result["createdBy"].AsString : string.Empty, |                         CreatedBy = result.Contains("createdBy") && !result["createdBy"].IsBsonNull ? result["createdBy"].AsString : string.Empty, | ||||||
|                         UpdatedAt = result.Contains("updatedAt") && !result["updatedAt"].IsBsonNull ? result["updatedAt"].ToUniversalTime() : DateTime.MinValue, |  | ||||||
|                         UpdatedBy = result.Contains("updatedBy") && !result["updatedBy"].IsBsonNull ? result["updatedBy"].AsString : string.Empty, |                         UpdatedBy = result.Contains("updatedBy") && !result["updatedBy"].IsBsonNull ? result["updatedBy"].AsString : string.Empty, | ||||||
|                         Status = result.Contains("status") && !result["status"].IsBsonNull |                         Status = result.Contains("status") && !result["status"].IsBsonNull | ||||||
|                             ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["status"].AsString) |                             ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["status"].AsString) | ||||||
| @@ -374,39 +404,100 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|                              !result["role"]["status"].IsBsonNull |                              !result["role"]["status"].IsBsonNull | ||||||
|                             ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["role"]["status"].AsString) |                             ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["role"]["status"].AsString) | ||||||
|                             : Core.Blueprint.Mongo.StatusEnum.Inactive, |                             : Core.Blueprint.Mongo.StatusEnum.Inactive, | ||||||
|                         CreatedAt = result.Contains("role") && result["role"].IsBsonDocument && |                         CreatedAt = SafeToUtc(result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("createdAt") | ||||||
|                             result["role"].AsBsonDocument.Contains("createdAt") && |                             ? result["role"]["createdAt"] | ||||||
|                             !result["role"]["createdAt"].IsBsonNull |                             : null), | ||||||
|                             ? result["role"]["createdAt"].ToUniversalTime() |                         UpdatedAt = SafeToUtc(result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("updatedAt") | ||||||
|                             : DateTime.MinValue, |                             ? result["role"]["updatedAt"] | ||||||
|                         UpdatedAt = result.Contains("role") && result["role"].IsBsonDocument && |                             : null), | ||||||
|                             result["role"].AsBsonDocument.Contains("updatedAt") && |  | ||||||
|                             !result["role"]["updatedAt"].IsBsonNull |  | ||||||
|                             ? result["role"]["updatedAt"].ToUniversalTime() |  | ||||||
|                             : DateTime.MinValue, |  | ||||||
|                         CreatedBy = result.Contains("role") && result["role"].IsBsonDocument && |                         CreatedBy = result.Contains("role") && result["role"].IsBsonDocument && | ||||||
|                             result["role"].AsBsonDocument.Contains("createdBy") && |                             result["role"].AsBsonDocument.Contains("createdBy") && !result["role"]["createdBy"].IsBsonNull | ||||||
|                             !result["role"]["createdBy"].IsBsonNull |  | ||||||
|                             ? result["role"]["createdBy"].AsString |                             ? result["role"]["createdBy"].AsString | ||||||
|                             : string.Empty, |                             : string.Empty, | ||||||
|                         UpdatedBy = result.Contains("role") && result["role"].IsBsonDocument && |                         UpdatedBy = result.Contains("role") && result["role"].IsBsonDocument && | ||||||
|                             result["role"].AsBsonDocument.Contains("updatedBy") && |                             result["role"].AsBsonDocument.Contains("updatedBy") && !result["role"]["updatedBy"].IsBsonNull | ||||||
|                             !result["role"]["updatedBy"].IsBsonNull |  | ||||||
|                             ? result["role"]["updatedBy"].AsString |                             ? result["role"]["updatedBy"].AsString | ||||||
|                             : string.Empty |                             : string.Empty | ||||||
|                     }, |                     }, | ||||||
|  |                     Tenant = result.Contains("tenant") && result["tenant"].IsBsonDocument | ||||||
|  |                     ? new TenantAdapter | ||||||
|  |                     { | ||||||
|  |                         Id = result.Contains("tenant") && result["tenant"].IsBsonDocument && result["tenant"].AsBsonDocument.Contains("_id") | ||||||
|  |                             ? result["tenant"]["_id"]?.ToString() ?? "" | ||||||
|  |                             : string.Empty, | ||||||
|  |                         Name = result["tenant"].AsBsonDocument.Contains("name") && !result["tenant"]["name"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["name"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         TaxIdentifier = result["tenant"].AsBsonDocument.Contains("taxIdentifier") && !result["tenant"]["taxIdentifier"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["taxIdentifier"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         AddressLine1 = result["tenant"].AsBsonDocument.Contains("addressLine1") && !result["tenant"]["addressLine1"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["addressLine1"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         AddressLine2 = result["tenant"].AsBsonDocument.Contains("addressLine2") && !result["tenant"]["addressLine2"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["addressLine2"].AsString | ||||||
|  |                             : null, | ||||||
|  |                         City = result["tenant"].AsBsonDocument.Contains("city") && !result["tenant"]["city"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["city"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         State = result["tenant"].AsBsonDocument.Contains("state") && !result["tenant"]["state"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["state"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         Country = result["tenant"].AsBsonDocument.Contains("country") && !result["tenant"]["country"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["country"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         PostalCode = result["tenant"].AsBsonDocument.Contains("postalCode") && !result["tenant"]["postalCode"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["postalCode"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         ContactEmail = result["tenant"].AsBsonDocument.Contains("contactEmail") && !result["tenant"]["contactEmail"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["contactEmail"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         ContactPhone = result["tenant"].AsBsonDocument.Contains("contactPhone") && !result["tenant"]["contactPhone"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["contactPhone"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         Website = result["tenant"].AsBsonDocument.Contains("website") && !result["tenant"]["website"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["website"].AsString | ||||||
|  |                             : null, | ||||||
|  |                         ConnectionString = result["tenant"].AsBsonDocument.Contains("connectionString") && !result["tenant"]["connectionString"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["connectionString"].AsString | ||||||
|  |                             : null, | ||||||
|  |                         Isolated = result["tenant"].AsBsonDocument.Contains("isolated") && !result["tenant"]["isolated"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["isolated"].ToBoolean() | ||||||
|  |                             : false, | ||||||
|  |                         CreatedAt = SafeToUtc(result.Contains("tenant") && result["tenant"].IsBsonDocument && result["tenant"].AsBsonDocument.Contains("createdAt") | ||||||
|  |                             ? result["tenant"]["createdAt"] | ||||||
|  |                             : null), | ||||||
|  |                         UpdatedAt = SafeToUtc(result.Contains("tenant") && result["tenant"].IsBsonDocument && result["tenant"].AsBsonDocument.Contains("updatedAt") | ||||||
|  |                             ? result["tenant"]["updatedAt"] | ||||||
|  |                             : null), | ||||||
|  |                         CreatedBy = result["tenant"].AsBsonDocument.Contains("createdBy") && !result["tenant"]["createdBy"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["createdBy"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         UpdatedBy = result["tenant"].AsBsonDocument.Contains("updatedBy") && !result["tenant"]["updatedBy"].IsBsonNull | ||||||
|  |                             ? result["tenant"]["updatedBy"].AsString | ||||||
|  |                             : string.Empty, | ||||||
|  |                         Status = result["tenant"].AsBsonDocument.Contains("status") && !result["tenant"]["status"].IsBsonNull | ||||||
|  |                             ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["tenant"]["status"].AsString) | ||||||
|  |                             : Core.Blueprint.Mongo.StatusEnum.Active | ||||||
|  |                     } | ||||||
|  |                     : null, | ||||||
|                     Permissions = result.Contains("permissions") && result["permissions"].IsBsonArray |                     Permissions = result.Contains("permissions") && result["permissions"].IsBsonArray | ||||||
|                         ? result["permissions"].AsBsonArray |                         ? result["permissions"].AsBsonArray | ||||||
|                             .Where(p => p != null && p.IsBsonDocument) |                             .Where(p => p != null && p.IsBsonDocument) | ||||||
|                             .Select(p => BsonSerializer.Deserialize<PermissionAdapter>(p.AsBsonDocument)) |                             .Select(p => BsonSerializer.Deserialize<PermissionAdapter>(p.AsBsonDocument)) | ||||||
|                             .Where(p => p.Status == Core.Blueprint.Mongo.StatusEnum.Active) |                             .Where(p => p.Status == Core.Blueprint.Mongo.StatusEnum.Active) | ||||||
|                             .ToList() |                             .ToList() | ||||||
|                         : new List<PermissionAdapter>() |                         : new List<PermissionAdapter>(), | ||||||
|  |                     Modules = result.Contains("modules") && result["modules"].IsBsonArray | ||||||
|  |                     ? result["modules"].AsBsonArray | ||||||
|  |                         .Where(p => p != null && p.IsBsonDocument) | ||||||
|  |                         .Select(p => BsonSerializer.Deserialize<ModuleAdapter>(p.AsBsonDocument)) | ||||||
|  |                         .Where(p => p.Status == Core.Blueprint.Mongo.StatusEnum.Active) | ||||||
|  |                         .ToList() | ||||||
|  |                     : new List<ModuleAdapter>() | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|  |  | ||||||
|                 return tokenAdapter; |                 return tokenAdapter; | ||||||
|  |  | ||||||
|             } |             } | ||||||
|             catch (Exception ex) |             catch (Exception ex) | ||||||
|             { |             { | ||||||
| @@ -414,6 +505,7 @@ namespace Core.Thalos.Provider.Providers.Onboarding | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Deletes an User by _id. |         /// Deletes an User by _id. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | # ============ Build ============ | ||||||
|  | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build | ||||||
|  | WORKDIR /src | ||||||
|  |  | ||||||
|  | # Copia opcional del nuget.config si existe en el root | ||||||
|  | COPY nuget.config* ./ | ||||||
|  |  | ||||||
|  | # Copiamos csprojs primero para aprovechar caché de restore | ||||||
|  | COPY Core.Thalos.Domain/Core.Thalos.Domain.csproj Core.Thalos.Domain/ | ||||||
|  | COPY Core.Thalos.Provider/Core.Thalos.Provider.csproj Core.Thalos.Provider/ | ||||||
|  | COPY Core.Thalos.Infraestructure/Core.Thalos.Infrastructure.csproj Core.Thalos.Infraestructure/ | ||||||
|  | COPY Core.Thalos.DAL.API/Core.Thalos.DAL.API.csproj Core.Thalos.DAL.API/ | ||||||
|  |  | ||||||
|  | RUN dotnet restore Core.Thalos.DAL.API/Core.Thalos.DAL.API.csproj | ||||||
|  |  | ||||||
|  | # Copiamos el resto y compilamos | ||||||
|  | COPY . . | ||||||
|  | RUN dotnet build Core.Thalos.DAL.API/Core.Thalos.DAL.API.csproj -c Release -o /app/build | ||||||
|  |  | ||||||
|  | # ============ Publish ============ | ||||||
|  | FROM build AS publish | ||||||
|  | RUN dotnet publish Core.Thalos.DAL.API/Core.Thalos.DAL.API.csproj -c Release -o /app/publish \ | ||||||
|  |     --no-restore | ||||||
|  |  | ||||||
|  | # ============ Runtime ============ | ||||||
|  | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final | ||||||
|  | # (Opcional) instalar curl para healthcheck HTTP | ||||||
|  | RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* | ||||||
|  |  | ||||||
|  | WORKDIR /app | ||||||
|  | EXPOSE 8080 | ||||||
|  | # Usuario no-root | ||||||
|  | RUN useradd -m appuser | ||||||
|  | USER appuser | ||||||
|  |  | ||||||
|  | ENV ASPNETCORE_URLS=http://+:8080 | ||||||
|  | # Usa env vars y/o UserSecrets; no guardes tokens en la imagen.  :contentReference[oaicite:4]{index=4} | ||||||
|  |  | ||||||
|  | COPY --from=publish /app/publish ./ | ||||||
|  | ENTRYPOINT ["dotnet", "Core.Thalos.DAL.API.dll"] | ||||||
							
								
								
									
										9
									
								
								nuget.config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								nuget.config
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <configuration> | ||||||
|  |   <packageSources> | ||||||
|  |     <!-- Tu BaGet primero --> | ||||||
|  |     <add key="BaGet" value="https://nuget.dream-views.com/v3/index.json" protocolVersion="3" /> | ||||||
|  |     <!-- NuGet oficial como fallback (si quieres) --> | ||||||
|  |     <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> | ||||||
|  |   </packageSources> | ||||||
|  | </configuration> | ||||||
		Reference in New Issue
	
	Block a user