aboutsummaryrefslogtreecommitdiff
path: root/docker/crupest-api/CrupestApi
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-12-10 16:56:33 +0800
committercrupest <crupest@outlook.com>2022-12-20 20:32:53 +0800
commitf208e75f9e074a3faab489de1093f660b87c2ec7 (patch)
tree2c2379c5155b7cef31c56c6559418ce1d66128a5 /docker/crupest-api/CrupestApi
parent8c478bb1a07a55b9056ada029e0d6f9fe34d8d38 (diff)
downloadcrupest-f208e75f9e074a3faab489de1093f660b87c2ec7.tar.gz
crupest-f208e75f9e074a3faab489de1093f660b87c2ec7.tar.bz2
crupest-f208e75f9e074a3faab489de1093f660b87c2ec7.zip
Develop secret api. v24
Diffstat (limited to 'docker/crupest-api/CrupestApi')
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs2
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs53
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs18
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs10
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs7
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/DbConnectionFactory.cs1
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs83
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Secrets/ISecretsService.cs23
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretInfo.cs31
-rw-r--r--docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs196
10 files changed, 163 insertions, 261 deletions
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs
index c6791c6..62fb9e5 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons.Tests/Crud/TableInfoTest.cs
@@ -24,7 +24,7 @@ public class TableInfoTest
[Fact]
public void GenerateSelectSqlTest()
{
- var (sql, parameters) = _tableInfo.GenerateSelectSql(WhereClause.Create().Eq("Name", "Hello"));
+ var (sql, parameters) = _tableInfo.GenerateSelectSql(null, WhereClause.Create().Eq("Name", "Hello"));
var parameterName = parameters.ParameterNames.First();
// TODO: Is there a way to auto detect parameters?
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
index 88b5ced..f1fb99b 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs
@@ -86,16 +86,39 @@ public class ColumnInfo
protected void OnBeforeInsert(ColumnInfo column, ref object? value)
{
- TryCoerceStringFromNullToEmpty(ref value);
- if (column.IsNotNull && !column.IsAutoIncrement)
+ if (column.IsClientGenerate && value is not null)
+ {
+ throw new Exception($"Column {column.ColumnName} can't be set manually.");
+ }
+
+ var defaultValueGeneratorMethod = DefaultValueGeneratorMethod;
+ if (defaultValueGeneratorMethod is not null)
{
- throw new Exception($"Column {column.ColumnName} can't be empty.");
+ value = defaultValueGeneratorMethod.Invoke(null, new object[] { });
}
+
+
+ OnBeforeSet(column, ref value);
}
protected void OnBeforeUpdate(ColumnInfo column, ref object? value)
{
+ OnBeforeSet(column, ref value);
+
+ if (column.IsNoUpdate)
+ {
+ throw new Exception($"Column {column.ColumnName} not updatable.");
+ }
+ }
+
+ protected void OnBeforeSet(ColumnInfo column, ref object? value)
+ {
TryCoerceStringFromNullToEmpty(ref value);
+
+ if (value is null && column.IsNotNull)
+ {
+ throw new Exception($"Column {column.ColumnName} can't be null.");
+ }
}
public string ColumnName
@@ -108,9 +131,33 @@ public class ColumnInfo
}
}
+ public MethodInfo? DefaultValueGeneratorMethod
+ {
+ get
+ {
+ object? value = Metadata.GetValueOrDefault(ColumnMetadataKeys.DefaultValueGenerator);
+ Debug.Assert(value is null || value is string);
+ MethodInfo? result;
+ if (value is null)
+ {
+ string methodName = ColumnName + "DefaultValueGenerator";
+ result = Table.EntityType.GetMethod(methodName, BindingFlags.Static);
+ }
+ else
+ {
+ string methodName = (string)value;
+ result = Table.EntityType.GetMethod(methodName, BindingFlags.Static) ?? throw new Exception("The default value generator does not exist.");
+ }
+
+ return result;
+ }
+ }
+
public bool IsPrimaryKey => Metadata.GetValueOrDefault(ColumnMetadataKeys.IsPrimaryKey) is true;
public bool IsAutoIncrement => Metadata.GetValueOrDefault(ColumnMetadataKeys.IsAutoIncrement) is true;
public bool IsNotNull => IsPrimaryKey || Metadata.GetValueOrDefault(ColumnMetadataKeys.NotNull) is true;
+ public bool IsClientGenerate => Metadata.GetValueOrDefault(ColumnMetadataKeys.ClientGenerate) is true;
+ public bool IsNoUpdate => Metadata.GetValueOrDefault(ColumnMetadataKeys.NoUpdate) is true;
public ColumnIndexType Index => Metadata.GetValueOrDefault<ColumnIndexType?>(ColumnMetadataKeys.Index) ?? ColumnIndexType.None;
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs
index 91e49f8..1ca2ce8 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnMetadata.cs
@@ -17,6 +17,18 @@ public static class ColumnMetadataKeys
/// This indicates that you take care of generate this column value when create entity. User calling the api can not specify the value.
/// </summary>
public const string ClientGenerate = nameof(ColumnAttribute.DefaultEmptyForString);
+
+ /// <summary>
+ /// The default value generator method name in entity type. Default to null, aka, search for ColumnNameDefaultValueGenerator.
+ /// </summary>
+ /// <returns></returns>
+ public const string DefaultValueGenerator = nameof(ColumnAttribute.DefaultValueGenerator);
+
+ /// <summary>
+ /// The column can only be set when inserted, can't be changed in update.
+ /// </summary>
+ /// <returns></returns>
+ public const string NoUpdate = nameof(ColumnAttribute.NoUpdate);
}
public interface IColumnMetadata
@@ -87,6 +99,12 @@ public class ColumnAttribute : Attribute, IColumnMetadata
/// <see cref="ColumnMetadataKeys.ClientGenerate"/>
public bool ClientGenerate { get; init; }
+ /// <see cref="ColumnMetadataKeys.DefaultValueGenerator"/>
+ public string? DefaultValueGenerator { get; init; }
+
+ /// <see cref="ColumnMetadataKeys.NoUpdate"/>
+ public bool NoUpdate { get; init; }
+
public bool TryGetValue(string key, out object? value)
{
var property = GetType().GetProperty(key);
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
index e098aca..811b2e6 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudService.cs
@@ -40,6 +40,16 @@ public class CrudService<TEntity> : IDisposable where TEntity : class
return _table.Select(_dbConnection, filter).Cast<TEntity>().ToList();
}
+ public bool Exists(IWhereClause? filter)
+ {
+ return _table.SelectCount(_dbConnection, filter) > 0;
+ }
+
+ public int Count(IWhereClause? filter)
+ {
+ return _table.SelectCount(_dbConnection, filter);
+ }
+
public int Insert(IInsertClause insertClause)
{
return _table.Insert(_dbConnection, insertClause);
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs
index aa25a23..3467625 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/CrudWebApplicationExtensions.cs
@@ -2,8 +2,13 @@ namespace CrupestApi.Commons.Crud;
public static class CrudWebApplicationExtensions
{
- public static IApplicationBuilder UseCrud(this IApplicationBuilder app, string path)
+ public static WebApplication UseCrud(this WebApplication app, string path)
{
+ app.MapGet(path, async (context) =>
+ {
+
+ });
+
return app;
}
}
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/DbConnectionFactory.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/DbConnectionFactory.cs
index 2ee01ca..e8f8abf 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/DbConnectionFactory.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/DbConnectionFactory.cs
@@ -4,7 +4,6 @@ using Microsoft.Extensions.Options;
namespace CrupestApi.Commons.Crud;
-// TODO: Implement and register this service.
public interface IDbConnectionFactory
{
IDbConnection Get(string? name = null);
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
index 28dc1ad..5bb19ad 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs
@@ -207,7 +207,7 @@ CREATE TABLE {tableName}(
}
}
- public (string sql, DynamicParameters parameters) GenerateSelectSql(IWhereClause? whereClause, IOrderByClause? orderByClause = null, int? skip = null, int? limit = null, string? dbProviderId = null)
+ public (string sql, DynamicParameters parameters) GenerateSelectSql(string? what, IWhereClause? whereClause, IOrderByClause? orderByClause = null, int? skip = null, int? limit = null, string? dbProviderId = null)
{
CheckRelatedColumns(whereClause);
CheckRelatedColumns(orderByClause);
@@ -215,7 +215,7 @@ CREATE TABLE {tableName}(
var parameters = new DynamicParameters();
StringBuilder result = new StringBuilder()
- .Append("SELECT * FROM ")
+ .Append($"SELECT {what ?? "*"} FROM ")
.Append(TableName);
if (whereClause is not null)
@@ -372,49 +372,43 @@ CREATE TABLE {tableName}(
return result;
}
- private object? ConvertFromDynamicToEntity(dynamic d)
+ public virtual int SelectCount(IDbConnection dbConnection, IWhereClause? where = null, IOrderByClause? orderBy = null, int? skip = null, int? limit = null)
{
- if (d is null) return null;
+ var (sql, parameters) = GenerateSelectSql("COUNT(*)", where, orderBy, skip, limit);
+ return dbConnection.QuerySingle<int>(sql, parameters);
- Type dynamicType = d.GetType();
-
- var result = Activator.CreateInstance(EntityType);
-
- foreach (var column in ColumnInfos)
- {
- var propertyInfo = column.PropertyInfo;
- if (propertyInfo is not null)
- {
- var dynamicProperty = dynamicType.GetProperty(column.ColumnName);
- if (dynamicProperty is null) continue;
- object? value = dynamicProperty.GetValue(d);
- value = column.ColumnType.ConvertFromDatabase(value);
- propertyInfo.SetValue(result, value);
- }
- }
-
- return result;
}
public virtual IEnumerable<object?> Select(IDbConnection dbConnection, IWhereClause? where = null, IOrderByClause? orderBy = null, int? skip = null, int? limit = null)
{
- var (sql, parameters) = GenerateSelectSql(where, orderBy, skip, limit);
+ return Select<IEnumerable<object?>>(dbConnection, null, where, orderBy, skip, limit);
+ }
+
+ public virtual IEnumerable<TResult> Select<TResult>(IDbConnection dbConnection, string? what, IWhereClause? where = null, IOrderByClause? orderBy = null, int? skip = null, int? limit = null)
+ {
+ var (sql, parameters) = GenerateSelectSql(what, where, orderBy, skip, limit);
return dbConnection.Query<dynamic>(sql, parameters).Select(d =>
{
- var e = ConvertFromDynamicToEntity(d);
+ Type dynamicType = d.GetType();
+
+ var result = Activator.CreateInstance<TResult>();
foreach (var column in ColumnInfos)
{
+ object? value = null;
+ var dynamicProperty = dynamicType.GetProperty(column.ColumnName);
+ if (dynamicProperty is not null) value = dynamicProperty.GetValue(d);
+ column.Hooks.AfterSelect(column, ref value);
+ if (value is not null)
+ value = column.ColumnType.ConvertFromDatabase(value);
var propertyInfo = column.PropertyInfo;
if (propertyInfo is not null)
{
- var value = propertyInfo.GetValue(e);
- column.Hooks.AfterSelect(column, ref value);
- propertyInfo.SetValue(e, value);
+ propertyInfo.SetValue(result, value);
}
}
- return e;
+ return result;
});
}
@@ -422,12 +416,20 @@ CREATE TABLE {tableName}(
{
var (sql, parameters) = GenerateInsertSql(insert);
- foreach (var item in insert.Items)
+ foreach (var column in ColumnInfos)
{
- var column = GetColumn(item.ColumnName);
- var value = item.Value;
+ InsertItem? item = insert.Items.FirstOrDefault(i => i.ColumnName == column.ColumnName);
+ var value = item?.Value;
column.Hooks.BeforeInsert(column, ref value);
- item.Value = value;
+ if (item is null)
+ {
+ if (value is not null)
+ insert.Items.Add(new InsertItem(column.ColumnName, value));
+ }
+ else
+ {
+ item.Value = value;
+ }
}
return dbConnection.Execute(sql, ConvertParameters(parameters));
@@ -437,13 +439,22 @@ CREATE TABLE {tableName}(
{
var (sql, parameters) = GenerateUpdateSql(where, update);
- foreach (var item in update.Items)
+ foreach (var column in ColumnInfos)
{
- var column = GetColumn(item.ColumnName);
- var value = item.Value;
+ UpdateItem? item = update.Items.FirstOrDefault(i => i.ColumnName == column.ColumnName);
+ var value = item?.Value;
column.Hooks.BeforeUpdate(column, ref value);
- item.Value = value;
+ if (item is null)
+ {
+ if (value is not null)
+ update.Items.Add(new UpdateItem(column.ColumnName, value));
+ }
+ else
+ {
+ item.Value = value;
+ }
}
+
return dbConnection.Execute(sql, ConvertParameters(parameters));
}
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/ISecretsService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/ISecretsService.cs
deleted file mode 100644
index b5de436..0000000
--- a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/ISecretsService.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace CrupestApi.Secrets;
-
-public interface ISecretsService
-{
- Task<SecretInfo?> GetSecretAsync(string secret);
-
- Task<List<SecretInfo>> GetSecretListAsync(bool includeExpired = false, bool includeRevoked = false);
-
- Task<List<SecretInfo>> GetSecretListByKeyAsync(string key, bool includeExpired = false, bool includeRevoked = false);
-
- Task VerifySecretAsync(string? key, string? secret);
-
- // Check if "secret" query param exists and is only one. Then check the secret is valid for given key.
- // If check fails, will throw a VerifySecretException with proper message that can be send to client.
- Task VerifySecretForHttpRequestAsync(HttpRequest request, string? key = null, string queryKey = "secret");
-
- Task<SecretInfo> CreateSecretAsync(string key, string description, DateTime? expireTime = null);
-
- Task RevokeSecretAsync(string secret);
-
- // Throw SecretNotExistException if request secret does not exist.
- Task<SecretInfo> ModifySecretAsync(string secret, SecretModifyRequest modifyRequest);
-}
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretInfo.cs
index 009bde9..e6af39b 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretInfo.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretInfo.cs
@@ -1,3 +1,5 @@
+using System.Security.Cryptography;
+using System.Text;
using CrupestApi.Commons.Crud;
namespace CrupestApi.Secrets;
@@ -6,7 +8,7 @@ public class SecretInfo
{
[Column(NotNull = true)]
public string Key { get; set; } = default!;
- [Column(NotNull = true, ClientGenerate = true)]
+ [Column(NotNull = true, ClientGenerate = true, NoUpdate = true)]
public string Secret { get; set; } = default!;
[Column(DefaultEmptyForString = true)]
public string Description { get; set; } = default!;
@@ -16,4 +18,31 @@ public class SecretInfo
public bool Revoked { get; set; }
[Column(NotNull = true)]
public DateTime CreateTime { get; set; }
+
+ private static RandomNumberGenerator RandomNumberGenerator = RandomNumberGenerator.Create();
+
+ private static string GenerateRandomKey(int length)
+ {
+ const string alphanum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ var result = new StringBuilder(length);
+ lock (RandomNumberGenerator)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ result.Append(alphanum[RandomNumberGenerator.GetInt32(alphanum.Length)]);
+ }
+ }
+ return result.ToString();
+ }
+
+
+ public static string SecretDefaultValueGenerator()
+ {
+ return GenerateRandomKey(16);
+ }
+
+ public static DateTime CreateTimeDefaultValueGenerator()
+ {
+ return DateTime.UtcNow;
+ }
}
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs
index 5a49121..b8912cb 100644
--- a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs
+++ b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs
@@ -5,7 +5,7 @@ using Dapper;
namespace CrupestApi.Secrets;
-public class SecretsService : CrudService<SecretInfo>, ISecretsService
+public class SecretsService : CrudService<SecretInfo>
{
private readonly ILogger<SecretsService> _logger;
@@ -14,198 +14,4 @@ public class SecretsService : CrudService<SecretInfo>, ISecretsService
{
_logger = loggerFactory.CreateLogger<SecretsService>();
}
-
- public async Task<SecretInfo> CreateSecretAsync(SecretInfo secretInfo)
- {
- if (secretInfo.Secret is not null)
- {
- throw new ArgumentException("Secret is auto generated. Don't specify it explicit.");
- }
-
- secretInfo.Secret = GenerateRandomKey(16);
- secretInfo.CreateTime = DateTime.Now;
-
- await InsertAsync(_table.GenerateInsertClauseFromEntity(secretInfo));
-
- return secretInfo;
- }
-
- public async Task<List<SecretInfo>> GetSecretListAsync(bool includeExpired = false, bool includeRevoked = false)
- {
- return (await QueryAsync()).ToList();
- }
-
- public async Task<List<SecretInfo>> GetSecretListByKeyAsync(string key, bool includeExpired = false, bool includeRevoked = false)
- {
- WhereClause where = WhereClause.Create();
-
- where.Eq(nameof(SecretInfo.Key), key);
-
- if (!includeExpired)
- {
- where.Add(nameof(SecretInfo.ExpireTime), "<=", )
- }
-
- if (!includeRevoked)
- {
- where.Eq(nameof(SecretInfo.Revoked), false);
- }
-
- return (await QueryAsync(where)).ToList();
- }
-
- public async Task<SecretInfo> ModifySecretAsync(string secret, SecretModifyRequest modifyRequest)
- {
- var dbConnection = await EnsureDatabase();
-
- var secretInfo = await GetSecretAsync(dbConnection, secret);
-
- if (secretInfo is null)
- {
- throw new EntityNotExistException("Secret not found.");
- }
-
- var queryParams = new DynamicParameters();
- var updateColumnList = new List<string>();
-
- if (modifyRequest.Key is not null)
- {
- queryParams.Add("Key", modifyRequest.Key);
- updateColumnList.Add("Key");
- }
-
- if (modifyRequest.Description is not null)
- {
- queryParams.Add("Description", modifyRequest.Description);
- updateColumnList.Add("Description");
- }
-
- if (modifyRequest.SetExpireTime is true)
- {
- queryParams.Add("ExpireTime", modifyRequest.ExpireTime?.ToString("O"));
- updateColumnList.Add("ExpireTime");
- }
-
- if (modifyRequest.Revoked is true && secretInfo.Revoked is not true)
- {
- queryParams.Add("Revoked", true);
- updateColumnList.Add("Revoked");
- }
-
- if (updateColumnList.Count == 0)
- {
- return secretInfo;
- }
-
- queryParams.Add("Secret", secret);
-
- var updateColumnString = updateColumnList.GenerateUpdateColumnString();
-
- var changeCount = await dbConnection.ExecuteAsync($@"
-UPDATE secrets SET {updateColumnString} WHERE Secret = @Secret;
- ", queryParams);
-
- Debug.Assert(changeCount == 1);
-
- return secretInfo;
- }
-
- public async Task RevokeSecretAsync(string secret)
- {
- await ModifySecretAsync(secret, new SecretModifyRequest
- {
- Revoked = true,
- });
- }
-
- public async Task VerifySecretAsync(string? key, string? secret)
- {
- var dbConnection = await EnsureDatabase();
-
- if (secret is null)
- {
- if (key is not null)
- {
- throw new VerifySecretException(key, "A secret with given key is needed.");
- }
- }
-
- var entity = await dbConnection.QueryFirstOrDefaultAsync<SecretInfo>(@"
-SELECT Id, Key, Secret, Description, ExpireTime, Revoked, CreateTime FROM secrets WHERE Key = @Key AND Secret = @Secret
- ", new
- {
- Key = key,
- Secret = secret,
- });
-
- if (entity is null)
- {
- throw new VerifySecretException(key, "Secret token is invalid.");
- }
-
- if (entity.Revoked is true)
- {
- throw new VerifySecretException(key, "Secret token is revoked.");
- }
-
- if (entity.ExpireTime is not null && DateTime.ParseExact(entity.ExpireTime, "O", null) > DateTime.Now)
- {
- throw new VerifySecretException(key, "Secret token is expired.");
- }
-
- if (key is not null)
- {
- if (entity.Key != key)
- {
- throw new VerifySecretException(key, "Secret is not for this key", VerifySecretException.ErrorKind.Forbidden);
- }
- }
- }
-
- public async Task VerifySecretForHttpRequestAsync(HttpRequest request, string? key, string queryKey = "secret")
- {
- string? secret = null;
-
- var authorizationHeaders = request.Headers.Authorization.ToList();
- if (authorizationHeaders.Count > 1)
- {
- _logger.LogWarning("There are multiple Authorization headers in the request. Will use the last one.");
- }
- if (authorizationHeaders.Count > 0)
- {
- var authorizationHeader = authorizationHeaders[^1] ?? "";
- if (!authorizationHeader.StartsWith("Bearer "))
- {
- throw new VerifySecretException(key, "Authorization header must start with 'Bearer '.");
- }
-
- secret = authorizationHeader.Substring("Bearer ".Length).Trim();
- }
-
- var secretQueryParam = request.Query[queryKey].ToList();
- if (secretQueryParam.Count > 1)
- {
- _logger.LogWarning($"There are multiple '{queryKey}' query parameters in the request. Will use the last one.");
- }
- if (secretQueryParam.Count > 0)
- {
- if (secret is not null)
- {
- _logger.LogWarning("Secret found both in Authorization header and query parameter. Will use the one in query parameter.");
- }
- secret = secretQueryParam[^1] ?? "";
- }
-
- await VerifySecretAsync(key, secret);
- }
-
- public Task<SecretInfo?> GetSecretAsync(string secret)
- {
- throw new NotImplementedException();
- }
-
- public Task<SecretInfo> CreateSecretAsync(string key, string description, DateTime? expireTime = null)
- {
- throw new NotImplementedException();
- }
}