Compare commits
	
		
			2 Commits
		
	
	
		
			feature/ad
			...
			feature/im
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 626105cf0c | |||
| eda79010ce | 
| @@ -4,7 +4,6 @@ using Microsoft.Extensions.Configuration; | |||||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||||
| using Microsoft.Extensions.Options; | using Microsoft.Extensions.Options; | ||||||
| using MongoDB.Driver; | using MongoDB.Driver; | ||||||
| using static MongoDB.Driver.WriteConcern; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Mongo.Configuration | namespace Core.Blueprint.DAL.Mongo.Configuration | ||||||
| { | { | ||||||
| @@ -26,48 +25,40 @@ namespace Core.Blueprint.DAL.Mongo.Configuration | |||||||
|             var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; |             var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; | ||||||
|  |  | ||||||
|             services.AddSingleton<IMongoContext, MongoContext>(); |             services.AddSingleton<IMongoContext, MongoContext>(); | ||||||
|             string ConnectionString = configuration.GetSection("ConnectionStrings:MongoDB").Value ?? string.Empty; |  | ||||||
|             string Databasename = configuration.GetSection("MongoDb:DatabaseName").Value ?? string.Empty; |  | ||||||
|             string Audience = string.Empty; |  | ||||||
|  |  | ||||||
|             if (!environment.Equals("Local", StringComparison.OrdinalIgnoreCase)) |             var ConnectionString = configuration.GetSection("ConnectionStrings:MongoDB").Value ?? string.Empty; | ||||||
|             { |             var Databasename = configuration.GetSection("MongoDb:DatabaseName").Value ?? string.Empty; | ||||||
|                 Audience = configuration.GetSection("MongoDb:Audience").Value ?? string.Empty; |             var Audience = (environment == "Local") | ||||||
|             } |                 ? configuration.GetSection("MongoDb:LocalAudience").Value | ||||||
|  |                 : configuration.GetSection("MongoDb:Audience").Value; | ||||||
|  |  | ||||||
|             if (string.IsNullOrEmpty(ConnectionString) || string.IsNullOrEmpty(Databasename)) |             if (string.IsNullOrEmpty(ConnectionString) || string.IsNullOrEmpty(Databasename) || string.IsNullOrEmpty(Audience)) | ||||||
|             { |  | ||||||
|                 throw new InvalidOperationException("Mongo connection is not configured correctly."); |                 throw new InvalidOperationException("Mongo connection is not configured correctly."); | ||||||
|             } |  | ||||||
|  |  | ||||||
|             services.Configure(delegate (MongoDbSettings options) |             services.Configure<MongoDbSettings>(options => | ||||||
|             { |             { | ||||||
|                 options.ConnectionString = ConnectionString; |                 options.ConnectionString = ConnectionString; | ||||||
|                 options.Databasename = Databasename; |                 options.Databasename = Databasename; | ||||||
|  |                 options.Audience = Audience; | ||||||
|                 if (!environment.Equals("Local", StringComparison.OrdinalIgnoreCase)) |  | ||||||
|                 { |  | ||||||
|                     options.Audience = Audience; |  | ||||||
|                 } |  | ||||||
|             }); |             }); | ||||||
|             services.AddSingleton((Func<IServiceProvider, IMongoClient>)delegate (IServiceProvider serviceProvider) |  | ||||||
|  |             services.AddSingleton<IMongoClient>(serviceProvider => | ||||||
|             { |             { | ||||||
|                 MongoDbSettings value2 = serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value; |                 var settings = serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value; | ||||||
|                 MongoClientSettings mongoClientSettings = MongoClientSettings.FromConnectionString(value2.ConnectionString); |                 var mongoClientSettings = MongoClientSettings.FromConnectionString(settings.ConnectionString); | ||||||
|  |                 mongoClientSettings.Credential = MongoCredential.CreateOidcCredential(new AzureIdentityProvider(settings.Audience)); | ||||||
|                 if (!environment.Equals("Local", StringComparison.OrdinalIgnoreCase))  |  | ||||||
|                 { |  | ||||||
|                     mongoClientSettings.Credential = MongoCredential.CreateOidcCredential(new AzureIdentityProvider(value2.Audience)); |  | ||||||
|                 } |  | ||||||
|                      |  | ||||||
|                 return new MongoClient(mongoClientSettings); |                 return new MongoClient(mongoClientSettings); | ||||||
|             }); |             }); | ||||||
|             services.AddSingleton(delegate (IServiceProvider serviceProvider) |  | ||||||
|  |             services.AddSingleton<IMongoDatabase>(serviceProvider => | ||||||
|             { |             { | ||||||
|                 MongoDbSettings value = serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value; |                 var settings = serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value; | ||||||
|                 return serviceProvider.GetRequiredService<IMongoClient>().GetDatabase(value.Databasename); |                 var client = serviceProvider.GetRequiredService<IMongoClient>(); | ||||||
|  |                 return client.GetDatabase(settings.Databasename); | ||||||
|             }); |             }); | ||||||
|             services.AddSingleton((Func<IServiceProvider, IMongoDbSettings>)((IServiceProvider serviceProvider) => serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value)); |  | ||||||
|  |             services.AddSingleton<IMongoDbSettings>(serviceProvider => serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value); | ||||||
|  |  | ||||||
|             return services; |             return services; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,12 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> |  | ||||||
| <configuration> |  | ||||||
| 	<packageSources> |  | ||||||
| 		<add key="Gitea" value="https://gitea.white-enciso.pro/api/packages/AgileWebs/nuget" /> |  | ||||||
| 	</packageSources> |  | ||||||
| 	<packageSourceCredentials> |  | ||||||
| 		<Gitea> |  | ||||||
| 			<Username>oscarmmtz</Username> |  | ||||||
| 			<ClearTextPassword>544831e1ceaf52958e02c5de4d23cbde9e7a860a</ClearTextPassword> |  | ||||||
| 		</Gitea> |  | ||||||
| 	</packageSourceCredentials> |  | ||||||
| </configuration> |  | ||||||
| @@ -21,6 +21,8 @@ namespace Core.Blueprint.Caching.Configuration | |||||||
|         { |         { | ||||||
|             // TODO for the following variable we'll need to add in the appsettings.json the following config: "UseRedisCache": true, |             // TODO for the following variable we'll need to add in the appsettings.json the following config: "UseRedisCache": true, | ||||||
|             bool useRedis = configuration.GetValue<bool>("UseRedisCache"); |             bool useRedis = configuration.GetValue<bool>("UseRedisCache"); | ||||||
|  |             //TODO decide wheter to use appsettings or the following ENV variable | ||||||
|  |             useRedis = Environment.GetEnvironmentVariable("CORE_BLUEPRINT_PACKAGES_USE_REDIS")?.ToLower() == "true"; | ||||||
|  |  | ||||||
|             if (useRedis) |             if (useRedis) | ||||||
|             { |             { | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ | |||||||
|     <TargetFramework>net8.0</TargetFramework> |     <TargetFramework>net8.0</TargetFramework> | ||||||
|     <ImplicitUsings>enable</ImplicitUsings> |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|     <Nullable>enable</Nullable> |     <Nullable>enable</Nullable> | ||||||
| 	<PackageId>Core.Blueprint.Redis</PackageId> |  | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
| @@ -35,29 +35,14 @@ namespace Core.Blueprint.Caching | |||||||
|         /// <param name="connectionString">The Redis connection string.</param> |         /// <param name="connectionString">The Redis connection string.</param> | ||||||
|         /// <returns>An <see cref="IDatabase"/> instance representing the Redis cache database.</returns> |         /// <returns>An <see cref="IDatabase"/> instance representing the Redis cache database.</returns> | ||||||
|         /// <exception cref="Exception">Thrown when the connection to Redis fails.</exce |         /// <exception cref="Exception">Thrown when the connection to Redis fails.</exce | ||||||
|         public async Task<IDatabase> InitializeRedisAsync(string connectionString) |         async Task<IDatabase> InitializeRedisAsync(string connectionString) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; |                 var configurationOptions = await ConfigurationOptions.Parse($"{connectionString}") | ||||||
|  |                     .ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()); | ||||||
|                 ConfigurationOptions configurationOptions; |  | ||||||
|  |  | ||||||
|                 if (environment.Equals("Local", StringComparison.OrdinalIgnoreCase)) |  | ||||||
|                 { |  | ||||||
|                     // Use simple local Redis config |  | ||||||
|                     configurationOptions = ConfigurationOptions.Parse(connectionString); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     // Use Azure Redis config |  | ||||||
|                     configurationOptions = await ConfigurationOptions |  | ||||||
|                         .Parse(connectionString) |  | ||||||
|                         .ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 configurationOptions.AbortOnConnectFail = false; |                 configurationOptions.AbortOnConnectFail = false; | ||||||
|  |  | ||||||
|                 var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions); |                 var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions); | ||||||
|  |  | ||||||
|                 _logger.LogInformation("Successfully connected to Redis."); |                 _logger.LogInformation("Successfully connected to Redis."); | ||||||
|   | |||||||
| @@ -11,23 +11,37 @@ namespace Core.Blueprint.Storage.Configuration | |||||||
|     { |     { | ||||||
|         public static IServiceCollection AddBlobStorage(this IServiceCollection services, IConfiguration configuration) |         public static IServiceCollection AddBlobStorage(this IServiceCollection services, IConfiguration configuration) | ||||||
|         { |         { | ||||||
|  |  | ||||||
|             var blobConnection = configuration.GetConnectionString("BlobStorage"); |             var blobConnection = configuration.GetConnectionString("BlobStorage"); | ||||||
|  |  | ||||||
|             if (blobConnection == null || string.IsNullOrWhiteSpace(blobConnection)) |             if (string.IsNullOrWhiteSpace(blobConnection)) | ||||||
|             { |  | ||||||
|                 throw new ArgumentException("The BlobStorage configuration section is missing or empty."); |                 throw new ArgumentException("The BlobStorage configuration section is missing or empty."); | ||||||
|             } |  | ||||||
|  |  | ||||||
|             var chainedCredentials = new ChainedTokenCredential( |             var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; | ||||||
|                     new ManagedIdentityCredential(), |  | ||||||
|                     new SharedTokenCacheCredential(), |  | ||||||
|                     new VisualStudioCredential(), |  | ||||||
|                     new VisualStudioCodeCredential() |  | ||||||
|                 ); |  | ||||||
|             services.AddAzureClients(cfg => |             services.AddAzureClients(cfg => | ||||||
|             { |             { | ||||||
|                 cfg.AddBlobServiceClient(new Uri(blobConnection)).WithCredential(chainedCredentials); |                 if (environment == "Local") | ||||||
|  |                 { | ||||||
|  |                     var accountKey = configuration.GetSection("BlobStorage:AccountKey").Value; | ||||||
|  |                     var accountName = configuration.GetSection("BlobStorage:AccountName").Value; | ||||||
|  |  | ||||||
|  |                     if(string.IsNullOrEmpty(accountKey) && string.IsNullOrEmpty(accountName)) | ||||||
|  |                         throw new ArgumentException("The BlobStorage configuration section is missing or empty."); | ||||||
|  |  | ||||||
|  |                     cfg.AddBlobServiceClient(configuration.GetConnectionString("BlobStorage")); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     var chainedCredentials = new ChainedTokenCredential( | ||||||
|  |                         new ManagedIdentityCredential(), | ||||||
|  |                         new SharedTokenCacheCredential(), | ||||||
|  |                         new VisualStudioCredential(), | ||||||
|  |                         new VisualStudioCodeCredential() | ||||||
|  |                     ); | ||||||
|  |  | ||||||
|  |                     cfg.AddBlobServiceClient(new Uri(blobConnection)) | ||||||
|  |                         .WithCredential(chainedCredentials); | ||||||
|  |                 } | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|             services.AddScoped<IBlobStorageProvider, BlobStorageProvider>(); |             services.AddScoped<IBlobStorageProvider, BlobStorageProvider>(); | ||||||
|   | |||||||
| @@ -162,7 +162,7 @@ namespace Core.Blueprint.Storage.Contracts | |||||||
|         /// </remarks> |         /// </remarks> | ||||||
|         /// <exception cref="ArgumentNullException">Thrown if <paramref name="blobName"/> is null or empty.</exception> |         /// <exception cref="ArgumentNullException">Thrown if <paramref name="blobName"/> is null or empty.</exception> | ||||||
|         /// <exception cref="StorageException">Thrown if there is an issue communicating with the Azure Blob service.</exception> |         /// <exception cref="StorageException">Thrown if there is an issue communicating with the Azure Blob service.</exception> | ||||||
|         BlobDownloadUriAdapter GenerateBlobDownloadUri(string blobName); |         ValueTask<BlobDownloadUriAdapter?> GenerateBlobDownloadUri(string blobName); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Retrieves the hierarchical folder structure. |         /// Retrieves the hierarchical folder structure. | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using Azure; | using Azure; | ||||||
|  | using Azure.Storage; | ||||||
| using Azure.Storage.Blobs; | using Azure.Storage.Blobs; | ||||||
| using Azure.Storage.Blobs.Models; | using Azure.Storage.Blobs.Models; | ||||||
| using Azure.Storage.Blobs.Specialized; | using Azure.Storage.Blobs.Specialized; | ||||||
| @@ -6,6 +7,7 @@ using Azure.Storage.Sas; | |||||||
| using Core.Blueprint.Storage.Adapters; | using Core.Blueprint.Storage.Adapters; | ||||||
| using Core.Blueprint.Storage.Contracts; | using Core.Blueprint.Storage.Contracts; | ||||||
| using Microsoft.Extensions.Configuration; | using Microsoft.Extensions.Configuration; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace Core.Blueprint.Storage.Provider | namespace Core.Blueprint.Storage.Provider | ||||||
| { | { | ||||||
| @@ -15,10 +17,12 @@ namespace Core.Blueprint.Storage.Provider | |||||||
|         private readonly BlobContainerClient _blobContainerClient; |         private readonly BlobContainerClient _blobContainerClient; | ||||||
|         private readonly string _containerName; |         private readonly string _containerName; | ||||||
|         private readonly Trie _trie = new Trie(); |         private readonly Trie _trie = new Trie(); | ||||||
|  |         private readonly IConfiguration _configuration; | ||||||
|  |  | ||||||
|         public BlobStorageProvider(BlobServiceClient blobServiceClient, IConfiguration configuration) |         public BlobStorageProvider(BlobServiceClient blobServiceClient, IConfiguration configuration) | ||||||
|         { |         { | ||||||
|             _blobServiceClient = blobServiceClient; |             _blobServiceClient = blobServiceClient; | ||||||
|  |             _configuration = configuration; | ||||||
|             _containerName = configuration.GetSection("BlobStorage:ContainerName").Value ?? ""; |             _containerName = configuration.GetSection("BlobStorage:ContainerName").Value ?? ""; | ||||||
|  |  | ||||||
|             if (string.IsNullOrEmpty(_containerName)) |             if (string.IsNullOrEmpty(_containerName)) | ||||||
| @@ -278,7 +282,8 @@ namespace Core.Blueprint.Storage.Provider | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="blobName">The name of the blob for which the download URI is being generated.</param> |         /// <param name="blobName">The name of the blob for which the download URI is being generated.</param> | ||||||
|         /// <returns> |         /// <returns> | ||||||
|         /// An instance of <see cref="BlobDownloadUriAdapter"/> containing the generated URI, blob name, and status. |         /// An instance of <see cref="BlobDownloadUriAdapter"/> containing the generated URI, blob name, and status, | ||||||
|  |         /// or <c>null</c> if the blob does not exist. | ||||||
|         /// </returns> |         /// </returns> | ||||||
|         /// <remarks> |         /// <remarks> | ||||||
|         /// The generated URI includes a Shared Access Signature (SAS) token, which allows secure, time-limited access to the blob. |         /// The generated URI includes a Shared Access Signature (SAS) token, which allows secure, time-limited access to the blob. | ||||||
| @@ -286,22 +291,36 @@ namespace Core.Blueprint.Storage.Provider | |||||||
|         /// </remarks> |         /// </remarks> | ||||||
|         /// <exception cref="ArgumentNullException">Thrown if <paramref name="blobName"/> is null or empty.</exception> |         /// <exception cref="ArgumentNullException">Thrown if <paramref name="blobName"/> is null or empty.</exception> | ||||||
|         /// <exception cref="StorageException">Thrown if there is an issue communicating with the Azure Blob service.</exception> |         /// <exception cref="StorageException">Thrown if there is an issue communicating with the Azure Blob service.</exception> | ||||||
|         public BlobDownloadUriAdapter GenerateBlobDownloadUri(string blobName) |         public async ValueTask<BlobDownloadUriAdapter?> GenerateBlobDownloadUri(string blobName) | ||||||
|         { |         { | ||||||
|             var delegationKey = _blobServiceClient.GetUserDelegationKey(DateTimeOffset.UtcNow, |             if (string.IsNullOrWhiteSpace(blobName)) | ||||||
|                                                                     DateTimeOffset.UtcNow.AddHours(2)); |                 throw new ArgumentNullException(nameof(blobName), "Blob name cannot be null or empty."); | ||||||
|  |  | ||||||
|             var blob = _blobContainerClient.GetBlobClient(blobName); |             var blob = _blobContainerClient.GetBlobClient(blobName); | ||||||
|  |  | ||||||
|             var sasBuilder = new BlobSasBuilder() |             if (!await blob.ExistsAsync()) | ||||||
|  |                 return null; | ||||||
|  |  | ||||||
|  |             var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; | ||||||
|  |  | ||||||
|  |             if (environment == "Local") | ||||||
|  |             { | ||||||
|  |                 return GenerateDownloadUri(blob); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var delegationKey = await _blobServiceClient.GetUserDelegationKeyAsync( | ||||||
|  |                 DateTimeOffset.UtcNow, | ||||||
|  |                 DateTimeOffset.UtcNow.AddHours(2)); | ||||||
|  |  | ||||||
|  |             var sasBuilder = new BlobSasBuilder | ||||||
|             { |             { | ||||||
|                 BlobContainerName = blob.BlobContainerName, |                 BlobContainerName = blob.BlobContainerName, | ||||||
|                 BlobName = blob.Name, |                 BlobName = blob.Name, | ||||||
|                 Resource = "b", |                 Resource = "b", | ||||||
|                 StartsOn = DateTimeOffset.UtcNow, |                 StartsOn = DateTimeOffset.UtcNow, | ||||||
|                 ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(5), |                 ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(5) | ||||||
|             }; |             }; | ||||||
|             sasBuilder.SetPermissions(BlobAccountSasPermissions.Read); |             sasBuilder.SetPermissions(BlobSasPermissions.Read); | ||||||
|             sasBuilder.Protocol = SasProtocol.Https; |             sasBuilder.Protocol = SasProtocol.Https; | ||||||
|  |  | ||||||
|             var blobUriBuilder = new BlobUriBuilder(blob.Uri) |             var blobUriBuilder = new BlobUriBuilder(blob.Uri) | ||||||
| @@ -317,6 +336,45 @@ namespace Core.Blueprint.Storage.Provider | |||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Generates a download URI for a blob using a Shared Access Signature in local (Azurite) environment. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="blob">The blob client for which the URI is being generated.</param> | ||||||
|  |         /// <returns>An instance of <see cref="BlobDownloadUriAdapter"/> containing the SAS URI and metadata.</returns> | ||||||
|  |         private BlobDownloadUriAdapter GenerateDownloadUri(BlobClient blob) | ||||||
|  |         { | ||||||
|  |             var sasBuilder = new BlobSasBuilder | ||||||
|  |             { | ||||||
|  |                 BlobContainerName = blob.BlobContainerName, | ||||||
|  |                 BlobName = blob.Name, | ||||||
|  |                 Resource = "b", | ||||||
|  |                 StartsOn = DateTimeOffset.UtcNow, | ||||||
|  |                 ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(5) | ||||||
|  |             }; | ||||||
|  |             sasBuilder.SetPermissions(BlobSasPermissions.Read); | ||||||
|  |             sasBuilder.Protocol = SasProtocol.HttpsAndHttp; | ||||||
|  |  | ||||||
|  |             var accountName = _configuration["BlobStorage:AccountName"]; | ||||||
|  |             var accountKey = _configuration["BlobStorage:AccountKey"]; | ||||||
|  |  | ||||||
|  |             var storageCredentials = new StorageSharedKeyCredential(accountName, accountKey); | ||||||
|  |             var sasToken = sasBuilder.ToSasQueryParameters(storageCredentials); | ||||||
|  |  | ||||||
|  |             var blobUriBuilder = new BlobUriBuilder(blob.Uri) | ||||||
|  |             { | ||||||
|  |                 Sas = sasToken | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             return new BlobDownloadUriAdapter | ||||||
|  |             { | ||||||
|  |                 Uri = blobUriBuilder.ToUri(), | ||||||
|  |                 Name = blob.Name, | ||||||
|  |                 Status = "Available" | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Retrieves the hierarchical folder structure. |         /// Retrieves the hierarchical folder structure. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user