Compare commits
8 Commits
351cc28181
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ede7baae6 | |||
| c42fb5eb00 | |||
| dbc21959eb | |||
| a97e4e2219 | |||
| 35965591f5 | |||
| 38b63455d4 | |||
| fbfa21f89a | |||
| e3cdf1fb32 |
@@ -22,7 +22,7 @@ namespace Core.Blueprint.KeyVault
|
||||
/// <returns>
|
||||
/// A <see cref="Tuple"/> containing a status message and a boolean indicating whether the secret was successfully deleted.
|
||||
/// </returns>
|
||||
ValueTask<Tuple<string, bool>> DeleteSecretAsync(string secretName, CancellationToken cancellationToken);
|
||||
ValueTask<(string Message, bool Deleted)> DeleteSecretAsync(string secretName, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a secret from Azure Key Vault.
|
||||
@@ -33,7 +33,7 @@ namespace Core.Blueprint.KeyVault
|
||||
/// A <see cref="Tuple"/> containing the <see cref="KeyVaultResponse"/> with secret details
|
||||
/// and an optional error message if the secret was not found.
|
||||
/// </returns>
|
||||
ValueTask<Tuple<KeyVaultResponse, string?>> GetSecretAsync(string secretName, CancellationToken cancellationToken);
|
||||
ValueTask<(KeyVaultResponse Secret, string? Message)> GetSecretAsync(string secretName, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing secret in Azure Key Vault. If the secret does not exist, an error is returned.
|
||||
@@ -43,6 +43,6 @@ namespace Core.Blueprint.KeyVault
|
||||
/// <returns>
|
||||
/// A <see cref="Tuple"/> containing the updated <see cref="KeyVaultResponse"/> and an optional error message if the secret was not found.
|
||||
/// </returns>
|
||||
ValueTask<Tuple<KeyVaultResponse, string>> UpdateSecretAsync(KeyVaultRequest newSecret, CancellationToken cancellationToken);
|
||||
ValueTask<(KeyVaultResponse Secret, string? Message)> UpdateSecretAsync(KeyVaultRequest newSecret, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Azure.Security.KeyVault.Secrets;
|
||||
using VaultSharp;
|
||||
using VaultSharp.V1.AuthMethods.Token;
|
||||
using Core.Blueprint.KeyVault.Configuration;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Net.Http.Json;
|
||||
using VaultSharp;
|
||||
using VaultSharp.Core;
|
||||
using VaultSharp.V1.AuthMethods.Token;
|
||||
|
||||
namespace Core.Blueprint.KeyVault;
|
||||
|
||||
@@ -67,7 +67,7 @@ public sealed class KeyVaultProvider : IKeyVaultProvider
|
||||
/// <returns>
|
||||
/// A <see cref="Tuple"/> containing a status message and a boolean indicating whether the secret was successfully deleted.
|
||||
/// </returns>
|
||||
public async ValueTask<Tuple<string, bool>> DeleteSecretAsync(string secretName, CancellationToken cancellationToken)
|
||||
public async ValueTask<(string Message, bool Deleted)> DeleteSecretAsync(string secretName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (environment == "Local")
|
||||
{
|
||||
@@ -88,7 +88,7 @@ public sealed class KeyVaultProvider : IKeyVaultProvider
|
||||
/// <summary>
|
||||
/// Retrieves a secret from Azure Key Vault or HashiCorp Vault.
|
||||
/// </summary>
|
||||
public async ValueTask<Tuple<KeyVaultResponse, string?>> GetSecretAsync(string secretName, CancellationToken cancellationToken)
|
||||
public async ValueTask<(KeyVaultResponse Secret, string? Message)> GetSecretAsync(string secretName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (environment == "Local")
|
||||
{
|
||||
@@ -108,7 +108,7 @@ public sealed class KeyVaultProvider : IKeyVaultProvider
|
||||
}
|
||||
catch (VaultSharp.Core.VaultApiException ex) when (ex.HttpStatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
return new(new KeyVaultResponse(), "Key Not Found");
|
||||
return new(new KeyVaultResponse { }, "Key Not Found");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public sealed class KeyVaultProvider : IKeyVaultProvider
|
||||
/// <summary>
|
||||
/// Updates an existing secret in Azure Key Vault or HashiCorp Vault. If the secret does not exist, an error is returned.
|
||||
/// </summary>
|
||||
public async ValueTask<Tuple<KeyVaultResponse, string>> UpdateSecretAsync(KeyVaultRequest newSecret, CancellationToken cancellationToken)
|
||||
public async ValueTask<(KeyVaultResponse Secret, string? Message)> UpdateSecretAsync(KeyVaultRequest newSecret, CancellationToken cancellationToken)
|
||||
{
|
||||
var existingSecret = await this.GetSecretAsync(newSecret.Name, cancellationToken);
|
||||
if (!string.IsNullOrEmpty(existingSecret.Item2))
|
||||
|
||||
@@ -104,11 +104,13 @@ namespace Core.Blueprint.Mongo
|
||||
void ReplaceOne(TDocument document);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously replaces an existing document with a new one.
|
||||
/// Asynchronously replaces an existing document in the collection and returns the updated version.
|
||||
/// </summary>
|
||||
/// <param name="document">The document to replace the existing one.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task ReplaceOneAsync(TDocument document);
|
||||
/// <param name="document">The document with the updated data. Its _Id is used to locate the existing document.</param>
|
||||
/// <returns>
|
||||
/// The updated document if the replacement was successful; otherwise, <c>null</c> if no matching document was found.
|
||||
/// </returns>
|
||||
Task<TDocument?> ReplaceOneAsync(TDocument document);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a single document by the provided filter expression.
|
||||
|
||||
@@ -175,16 +175,27 @@ namespace Core.Blueprint.Mongo
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously replaces an existing document in the collection.
|
||||
/// Asynchronously replaces an existing document in the collection and returns the updated version.
|
||||
/// </summary>
|
||||
/// <param name="document">The document with the updated data.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public virtual async Task ReplaceOneAsync(TDocument document)
|
||||
/// <param name="document">The document with the updated data. Its _Id is used to locate the existing document.</param>
|
||||
/// <returns>
|
||||
/// The updated document if the replacement was successful; otherwise, <c>null</c> if no matching document was found.
|
||||
/// </returns>
|
||||
public virtual async Task<TDocument?> ReplaceOneAsync(TDocument document)
|
||||
{
|
||||
var filter = Builders<TDocument>.Filter.Eq(doc => doc._Id, document._Id);
|
||||
await _collection.FindOneAndReplaceAsync(filter, document);
|
||||
|
||||
var options = new FindOneAndReplaceOptions<TDocument>
|
||||
{
|
||||
ReturnDocument = ReturnDocument.After // return the updated document
|
||||
};
|
||||
|
||||
var result = await _collection.FindOneAndReplaceAsync(filter, document, options);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a single document from the collection based on the provided filter expression.
|
||||
/// </summary>
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Core.Blueprint.Redis.Configuration
|
||||
|
||||
// Register RedisCacheProvider
|
||||
services.AddSingleton<IRedisCacheProvider>(provider =>
|
||||
new RedisCacheProvider(redisConnectionString, provider.GetRequiredService<ILogger<RedisCacheProvider>>()));
|
||||
new RedisCacheProvider(redisConnectionString, provider.GetRequiredService<ILogger<RedisCacheProvider>>(), configuration));
|
||||
|
||||
// Get CacheSettings and register with the ICacheSettings interface
|
||||
var cacheSettings = configuration.GetSection("CacheSettings").Get<CacheSettings>();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StackExchange.Redis;
|
||||
using System.Text.Json;
|
||||
@@ -12,6 +13,7 @@ namespace Core.Blueprint.Redis
|
||||
{
|
||||
private IDatabase _cacheDatabase = null!;
|
||||
private readonly ILogger<RedisCacheProvider> _logger;
|
||||
private readonly bool _useRedis;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RedisCacheProvider"/> class.
|
||||
@@ -19,34 +21,52 @@ namespace Core.Blueprint.Redis
|
||||
/// <param name="connectionString">The Redis connection string.</param>
|
||||
/// <param name="logger">The logger instance for logging operations.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when connection string is null or empty.</exception>
|
||||
public RedisCacheProvider(string connectionString, ILogger<RedisCacheProvider> logger)
|
||||
public RedisCacheProvider(string connectionString, ILogger<RedisCacheProvider> logger, IConfiguration configuration)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(connectionString))
|
||||
throw new ArgumentNullException(nameof(connectionString), "Redis connection string cannot be null or empty.");
|
||||
|
||||
_logger = logger;
|
||||
_useRedis = configuration.GetValue<bool>("UseRedisCache", false);
|
||||
_cacheDatabase = InitializeRedisAsync(connectionString).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and establishes a connection to Redis using the provided connection string.
|
||||
/// Initializes and establishes a connection to Redis based on the environment.
|
||||
/// Uses a local connection in development, and Azure with token credentials in other environments.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">The Redis connection string.</param>
|
||||
/// <returns>An <see cref="IDatabase"/> instance representing the Redis cache database.</returns>
|
||||
/// <exception cref="Exception">Thrown when the connection to Redis fails.</exce
|
||||
async Task<IDatabase> InitializeRedisAsync(string connectionString)
|
||||
/// <exception cref="Exception">Thrown when the connection to Redis fails.</exception>
|
||||
async Task<IDatabase?> InitializeRedisAsync(string connectionString)
|
||||
{
|
||||
try
|
||||
{
|
||||
var configurationOptions = await ConfigurationOptions.Parse($"{connectionString}")
|
||||
.ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential());
|
||||
if (_useRedis)
|
||||
{
|
||||
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty;
|
||||
ConnectionMultiplexer connectionMultiplexer;
|
||||
|
||||
configurationOptions.AbortOnConnectFail = false;
|
||||
var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions);
|
||||
if (environment.Equals("Local", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(connectionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
var configurationOptions = await ConfigurationOptions.Parse(connectionString)
|
||||
.ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential());
|
||||
|
||||
_logger.LogInformation("Successfully connected to Redis.");
|
||||
configurationOptions.AbortOnConnectFail = false;
|
||||
|
||||
return connectionMultiplexer.GetDatabase();
|
||||
connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Successfully connected to Redis.");
|
||||
|
||||
return connectionMultiplexer.GetDatabase();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -65,15 +85,21 @@ namespace Core.Blueprint.Redis
|
||||
{
|
||||
try
|
||||
{
|
||||
var value = await _cacheDatabase.StringGetAsync(key);
|
||||
if (value.IsNullOrEmpty)
|
||||
if (_useRedis is not false)
|
||||
{
|
||||
_logger.LogInformation($"Cache miss for key: {key}");
|
||||
return default;
|
||||
var value = await _cacheDatabase.StringGetAsync(key);
|
||||
|
||||
if (value.IsNullOrEmpty)
|
||||
{
|
||||
_logger.LogInformation($"Cache miss for key: {key}");
|
||||
return default;
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Cache hit for key: {key}");
|
||||
return JsonSerializer.Deserialize<TEntity>(value);
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Cache hit for key: {key}");
|
||||
return JsonSerializer.Deserialize<TEntity>(value);
|
||||
return default;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -92,9 +118,12 @@ namespace Core.Blueprint.Redis
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = JsonSerializer.Serialize(value);
|
||||
await _cacheDatabase.StringSetAsync(key, json, expiry);
|
||||
_logger.LogInformation($"Cache item set with key: {key}");
|
||||
if (_useRedis is not false)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(value);
|
||||
await _cacheDatabase.StringSetAsync(key, json, expiry);
|
||||
_logger.LogInformation($"Cache item set with key: {key}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -111,8 +140,11 @@ namespace Core.Blueprint.Redis
|
||||
{
|
||||
try
|
||||
{
|
||||
await _cacheDatabase.KeyDeleteAsync(key);
|
||||
_logger.LogInformation($"Cache item removed with key: {key}");
|
||||
if (_useRedis is not false)
|
||||
{
|
||||
await _cacheDatabase.KeyDeleteAsync(key);
|
||||
_logger.LogInformation($"Cache item removed with key: {key}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -130,9 +162,13 @@ namespace Core.Blueprint.Redis
|
||||
{
|
||||
try
|
||||
{
|
||||
var exists = await _cacheDatabase.KeyExistsAsync(key);
|
||||
_logger.LogInformation($"Cache item exists check for key: {key} - {exists}");
|
||||
return exists;
|
||||
if (_useRedis is not false)
|
||||
{
|
||||
var exists = await _cacheDatabase.KeyExistsAsync(key);
|
||||
_logger.LogInformation($"Cache item exists check for key: {key} - {exists}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -150,15 +186,18 @@ namespace Core.Blueprint.Redis
|
||||
{
|
||||
try
|
||||
{
|
||||
var value = await _cacheDatabase.StringGetAsync(key);
|
||||
if (!value.IsNullOrEmpty)
|
||||
if (_useRedis is not false)
|
||||
{
|
||||
await _cacheDatabase.StringSetAsync(key, value, expiry);
|
||||
_logger.LogInformation($"Cache item refreshed with key: {key}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning($"Cache item with key: {key} does not exist, cannot refresh");
|
||||
var value = await _cacheDatabase.StringGetAsync(key);
|
||||
if (!value.IsNullOrEmpty)
|
||||
{
|
||||
await _cacheDatabase.StringSetAsync(key, value, expiry);
|
||||
_logger.LogInformation($"Cache item refreshed with key: {key}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning($"Cache item with key: {key} does not exist, cannot refresh");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -20,15 +20,12 @@ namespace Core.Blueprint.SQLServer.Configuration
|
||||
{
|
||||
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty;
|
||||
|
||||
if (environment != "Local")
|
||||
{
|
||||
var chainedCredentials = new ChainedTokenCredential(
|
||||
new ManagedIdentityCredential(),
|
||||
new SharedTokenCacheCredential(),
|
||||
new VisualStudioCredential(),
|
||||
new VisualStudioCodeCredential()
|
||||
);
|
||||
}
|
||||
|
||||
services.AddScoped(typeof(IEntityRepository<,>), typeof(EntityRepository<,>));
|
||||
|
||||
|
||||
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