diff options
author | crupest <crupest@outlook.com> | 2022-12-02 18:43:17 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-12-20 20:32:52 +0800 |
commit | 691a23f5f8b7f58a23d8dea841d3576b047b5336 (patch) | |
tree | 4c20ee1fb813898d31220eeb18ee9973c4ad9e77 | |
parent | 608caf10276a8ebccf1a5c4497e71e2157c3340b (diff) | |
download | crupest-691a23f5f8b7f58a23d8dea841d3576b047b5336.tar.gz crupest-691a23f5f8b7f58a23d8dea841d3576b047b5336.tar.bz2 crupest-691a23f5f8b7f58a23d8dea841d3576b047b5336.zip |
Develop secret api.
8 files changed, 152 insertions, 12 deletions
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Config.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Config.cs new file mode 100644 index 0000000..0ca3547 --- /dev/null +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Config.cs @@ -0,0 +1,23 @@ +namespace CrupestApi.Commons; + +public class CrupestApiConfig +{ + public string DataDir { get; set; } = string.Empty; +} + +public static class CrupestApiConfigExtensions +{ + public static IServiceCollection AddCrupestApiConfig(this IServiceCollection services) + { + services.AddOptions<CrupestApiConfig>().BindConfiguration("CrupestApi"); + services.PostConfigure<CrupestApiConfig>(config => + { + if (config.DataDir is null || config.DataDir.Length == 0) + { + config.DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "crupest-api"); + } + }); + + return services; + } +}
\ No newline at end of file diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Files/CrupestApi.Files.csproj b/docker/crupest-api/CrupestApi/CrupestApi.Files/CrupestApi.Files.csproj index 86460e3..2221809 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Files/CrupestApi.Files.csproj +++ b/docker/crupest-api/CrupestApi/CrupestApi.Files/CrupestApi.Files.csproj @@ -4,6 +4,11 @@ <ProjectReference Include="..\CrupestApi.Commons\CrupestApi.Commons.csproj" />
</ItemGroup>
+ <ItemGroup> + <PackageReference Include="Dapper" Version="2.0.123" /> + <PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.0" /> + </ItemGroup>
+
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetType>library</TargetType>
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/CrupestApi.Secrets.csproj b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/CrupestApi.Secrets.csproj index 86460e3..70c83f3 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/CrupestApi.Secrets.csproj +++ b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/CrupestApi.Secrets.csproj @@ -4,6 +4,11 @@ <ProjectReference Include="..\CrupestApi.Commons\CrupestApi.Commons.csproj" />
</ItemGroup>
+ <ItemGroup>
+ <PackageReference Include="Dapper" Version="2.0.123" />
+ <PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.0" />
+ </ItemGroup>
+
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetType>library</TargetType>
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs new file mode 100644 index 0000000..3913a0b --- /dev/null +++ b/docker/crupest-api/CrupestApi/CrupestApi.Secrets/SecretsService.cs @@ -0,0 +1,109 @@ +using CrupestApi.Commons; +using Dapper; +using Microsoft.Data.Sqlite; +using Microsoft.Extensions.Options; + +namespace CrupestApi.Secrets; + +public class SecretsService : ISecretsService +{ + private readonly IOptionsSnapshot<CrupestApiConfig> _crupestApiConfig; + private readonly ILogger<SecretsService> _logger; + + public SecretsService(IOptionsSnapshot<CrupestApiConfig> crupestApiConfig, ILogger<SecretsService> logger) + { + _crupestApiConfig = crupestApiConfig; + _logger = logger; + } + + private string GetDatabasePath() + { + return Path.Combine(_crupestApiConfig.Value.DataDir, "secrets.db"); + } + + private async Task<SqliteConnection> EnsureDatabase() + { + var dataSource = GetDatabasePath(); + var connectionStringBuilder = new SqliteConnectionStringBuilder() + { + DataSource = dataSource + }; + + if (!File.Exists(dataSource)) + { + _logger.LogInformation("Data source {0} does not exist. Create one.", dataSource); + connectionStringBuilder.Mode = SqliteOpenMode.ReadWriteCreate; + var connectionString = connectionStringBuilder.ToString(); + var connection = new SqliteConnection(connectionString); + var transaction = await connection.BeginTransactionAsync(); + + connection.Execute(@" +CREATE TABLE secrets ( + Id INTEGER PRIMARY KEY AUTOINCREMENT, + Key TEXT NOT NULL, + Secret TEXT NOT NULL, + Description TEXT NOT NULL, + ExpireTime TEXT, + Revoked INTEGER NOT NULL, + CreateTime TEXT NOT NULL +); + +CREATE INDEX secrets_key ON secrets (key); + +INSERT INTO secrets (Key, Secret, Description, ExpireTime, Revoked, CreateTime) VALUES (@SecretManagementKey, 'crupest', 'This is the default secret management key.', NULL, 0, @CreateTime); + ", + new + { + SecretManagementKey = SecretsConstants.SecretManagementKey, + CreateTime = DateTime.Now.ToString("O"), + }); + + await transaction.CommitAsync(); + + _logger.LogInformation("{0} created with 'crupest' as the default secret management value. Please immediate revoke it and create a new one.", dataSource); + return connection; + } + else + { + _logger.LogInformation("Data source {0} already exists. Will use it."); + connectionStringBuilder.Mode = SqliteOpenMode.ReadWrite; + var connectionString = connectionStringBuilder.ToString(); + return new SqliteConnection(connectionString); + } + } + + public Task<SecretInfo> CreateSecretAsync(string key, string description, DateTime? expireTime = null) + { + throw new NotImplementedException(); + } + + public Task<List<SecretInfo>> GetSecretListAsync(bool includeExpired = false, bool includeRevoked = false) + { + throw new NotImplementedException(); + } + + public Task<List<SecretInfo>> GetSecretListByKeyAsync(string key, bool includeExpired = false, bool includeRevoked = false) + { + throw new NotImplementedException(); + } + + public Task<SecretInfo> ModifySecretAsync(string secret, SecretModifyRequest modifyRequest) + { + throw new NotImplementedException(); + } + + public Task RevokeSecretAsync(string secret) + { + throw new NotImplementedException(); + } + + public Task<bool> VerifySecretAsync(string key, string secret) + { + throw new NotImplementedException(); + } + + public Task VerifySecretForHttpRequestAsync(HttpRequest request, string key, string queryKey = "secret") + { + throw new NotImplementedException(); + } +} diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs index f5ccc09..ac20af2 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs @@ -1,12 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace CrupestApi.Todos; diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosServiceCollectionExtensions.cs b/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosServiceCollectionExtensions.cs index cdf174d..5041094 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosServiceCollectionExtensions.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosServiceCollectionExtensions.cs @@ -1,4 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; namespace CrupestApi.Todos; @@ -7,7 +6,7 @@ public static class TodosServiceCollectionExtensions { public static IServiceCollection AddTodos(this IServiceCollection services) { - services.AddOptions<TodosConfiguration>().BindConfiguration("Todos"); + services.AddOptions<TodosConfiguration>().BindConfiguration("CrupestApi.Todos"); services.PostConfigure<TodosConfiguration>(config => { if (config.Count == 0) diff --git a/docker/crupest-api/CrupestApi/CrupestApi/Program.cs b/docker/crupest-api/CrupestApi/CrupestApi/Program.cs index ff8f02f..be72617 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi/Program.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi/Program.cs @@ -8,6 +8,8 @@ string configFilePath = Environment.GetEnvironmentVariable("CRUPEST_API_CONFIG_F builder.Configuration.AddJsonFile(configFilePath, optional: false, reloadOnChange: true);
builder.Services.AddJsonOptions();
+builder.Services.AddCrupestApiConfig();
+
builder.Services.AddTodos();
var app = builder.Build();
diff --git a/template/crupest-api-config.json.template b/template/crupest-api-config.json.template index fc5eb85..65a7944 100644 --- a/template/crupest-api-config.json.template +++ b/template/crupest-api-config.json.template @@ -1,8 +1,10 @@ { - "Todos": { - "Username": "$CRUPEST_GITHUB_USERNAME", - "ProjectNumber": "$CRUPEST_GITHUB_PROJECT_NUMBER", - "Token": "$CRUPEST_GITHUB_TOKEN", - "Count": "$CRUPEST_GITHUB_TODO_COUNT" + "CrupestApi": { + "Todos": { + "Username": "$CRUPEST_GITHUB_USERNAME", + "ProjectNumber": "$CRUPEST_GITHUB_PROJECT_NUMBER", + "Token": "$CRUPEST_GITHUB_TOKEN", + "Count": "$CRUPEST_GITHUB_TODO_COUNT" + } } } |