Release v1.0.0 #16
							
								
								
									
										17
									
								
								ApiDto/Common/CacheType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								ApiDto/Common/CacheType.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | namespace Mirea.Api.Dto.Common; | ||||||
|  |  | ||||||
|  | /// <summary> | ||||||
|  | /// Specifies the types of caching mechanisms available. | ||||||
|  | /// </summary> | ||||||
|  | public enum CacheType | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Memcached caching type. | ||||||
|  |     /// </summary> | ||||||
|  |     Memcached, | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Redis caching type. | ||||||
|  |     /// </summary> | ||||||
|  |     Redis | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								ApiDto/Common/DatabaseType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								ApiDto/Common/DatabaseType.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | namespace Mirea.Api.Dto.Common; | ||||||
|  |  | ||||||
|  | /// <summary> | ||||||
|  | /// Specifies the types of databases supported. | ||||||
|  | /// </summary> | ||||||
|  | public enum DatabaseType | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// MySQL database type. | ||||||
|  |     /// </summary> | ||||||
|  |     Mysql, | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// SQLite database type. | ||||||
|  |     /// </summary> | ||||||
|  |     Sqlite, | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// PostgreSQL database type. | ||||||
|  |     /// </summary> | ||||||
|  |     PostgresSql | ||||||
|  | } | ||||||
| @@ -10,27 +10,18 @@ public class CreateUserRequest | |||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Gets or sets the email address of the user. |     /// Gets or sets the email address of the user. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <remarks> |  | ||||||
|     /// The email address is a required field. |  | ||||||
|     /// </remarks> |  | ||||||
|     [Required] |     [Required] | ||||||
|     public required string Email { get; set; } |     public required string Email { get; set; } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Gets or sets the username of the user. |     /// Gets or sets the username of the user. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <remarks> |  | ||||||
|     /// The username is a required field. |  | ||||||
|     /// </remarks> |  | ||||||
|     [Required] |     [Required] | ||||||
|     public required string Username { get; set; } |     public required string Username { get; set; } | ||||||
|  |  | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Gets or sets the password of the user. |     /// Gets or sets the password of the user. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <remarks> |  | ||||||
|     /// The password is a required field. |  | ||||||
|     /// </remarks> |  | ||||||
|     [Required] |     [Required] | ||||||
|     public required string Password { get; set; } |     public required string Password { get; set; } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,16 +1,17 @@ | |||||||
| using Mirea.Api.Dto.Common; | using Mirea.Api.Dto.Common; | ||||||
| using System; | using System.ComponentModel.DataAnnotations; | ||||||
| 
 | 
 | ||||||
| namespace Mirea.Api.Dto.Responses; | namespace Mirea.Api.Dto.Responses; | ||||||
| 
 | 
 | ||||||
| /// <summary> | /// <summary> | ||||||
| /// Represents the response containing information about available OAuth providers. | /// Represents the response containing information about available OAuth providers. | ||||||
| /// </summary> | /// </summary> | ||||||
| public class AvailableProvidersResponse | public class AvailableOAuthProvidersResponse | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Gets or sets the name of the OAuth provider. |     /// Gets or sets the name of the OAuth provider. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|  |     [Required] | ||||||
|     public required string ProviderName { get; set; } |     public required string ProviderName { get; set; } | ||||||
| 
 | 
 | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -19,7 +20,8 @@ public class AvailableProvidersResponse | |||||||
|     public OAuthProvider Provider { get; set; } |     public OAuthProvider Provider { get; set; } | ||||||
| 
 | 
 | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Gets or sets the redirect URI for the OAuth provider. |     /// Gets or sets the redirect URL for the OAuth provider's authorization process. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public required Uri Redirect { get; set; } |     [Required] | ||||||
|  |     public required string Redirect { get; set; } | ||||||
| } | } | ||||||
							
								
								
									
										29
									
								
								ApiDto/Responses/Configuration/CacheResponse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								ApiDto/Responses/Configuration/CacheResponse.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | using Mirea.Api.Dto.Common; | ||||||
|  |  | ||||||
|  | namespace Mirea.Api.Dto.Responses.Configuration; | ||||||
|  |  | ||||||
|  | /// <summary> | ||||||
|  | /// Represents a response containing cache configuration details. | ||||||
|  | /// </summary> | ||||||
|  | public class CacheResponse | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the type of cache database. | ||||||
|  |     /// </summary> | ||||||
|  |     public CacheType Type { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the server address. | ||||||
|  |     /// </summary> | ||||||
|  |     public string? Server { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the port number. | ||||||
|  |     /// </summary> | ||||||
|  |     public int Port { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the password. | ||||||
|  |     /// </summary> | ||||||
|  |     public string? Password { get; set; } | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								ApiDto/Responses/Configuration/DatabaseResponse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								ApiDto/Responses/Configuration/DatabaseResponse.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | using Mirea.Api.Dto.Common; | ||||||
|  |  | ||||||
|  | namespace Mirea.Api.Dto.Responses.Configuration; | ||||||
|  |  | ||||||
|  | /// <summary> | ||||||
|  | /// Represents a response containing database configuration details. | ||||||
|  | /// </summary> | ||||||
|  | public class DatabaseResponse | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the type of database. | ||||||
|  |     /// </summary> | ||||||
|  |     public DatabaseType Type { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the server address. | ||||||
|  |     /// </summary> | ||||||
|  |     public string? Server { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the port number. | ||||||
|  |     /// </summary> | ||||||
|  |     public int Port { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the database name. | ||||||
|  |     /// </summary> | ||||||
|  |     public string? Database { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the username. | ||||||
|  |     /// </summary> | ||||||
|  |     public string? User { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets a value indicating whether SSL is enabled. | ||||||
|  |     /// </summary> | ||||||
|  |     public bool Ssl { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the password. | ||||||
|  |     /// </summary> | ||||||
|  |     public string? Password { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the path to database. Only for Sqlite | ||||||
|  |     /// </summary> | ||||||
|  |     public string? PathToDatabase { get; set; } | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								ApiDto/Responses/TotpKeyResponse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								ApiDto/Responses/TotpKeyResponse.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | namespace Mirea.Api.Dto.Responses; | ||||||
|  |  | ||||||
|  | /// <summary> | ||||||
|  | /// Represents the response containing the TOTP (Time-Based One-Time Password) key details. | ||||||
|  | /// </summary> | ||||||
|  | public class TotpKeyResponse | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the secret key used for TOTP generation. | ||||||
|  |     /// </summary> | ||||||
|  |     public required string Secret { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the image (QR code) representing the TOTP key. | ||||||
|  |     /// </summary> | ||||||
|  |     public required string Image { get; set; } | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								ApiDto/Responses/UserResponse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								ApiDto/Responses/UserResponse.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | using Mirea.Api.Dto.Common; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.ComponentModel.DataAnnotations; | ||||||
|  |  | ||||||
|  | namespace Mirea.Api.Dto.Responses; | ||||||
|  |  | ||||||
|  | /// <summary> | ||||||
|  | /// Represents a response containing user information. | ||||||
|  | /// </summary> | ||||||
|  | public class UserResponse | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the email address of the user. | ||||||
|  |     /// </summary> | ||||||
|  |     [Required] | ||||||
|  |     public required string Email { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets the username of the user. | ||||||
|  |     /// </summary> | ||||||
|  |     [Required] | ||||||
|  |     public required string Username { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets a value indicating whether the user has two-factor authentication enabled. | ||||||
|  |     /// </summary> | ||||||
|  |     [Required] | ||||||
|  |     public bool TwoFactorAuthenticatorEnabled { get; set; } | ||||||
|  |  | ||||||
|  |     /// <summary> | ||||||
|  |     /// Gets or sets a collection of OAuth providers used by the user. | ||||||
|  |     /// </summary> | ||||||
|  |     [Required] | ||||||
|  |     public required IEnumerable<OAuthProvider> UsedOAuthProviders { get; set; } | ||||||
|  | } | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.Extensions.Configuration; | using Microsoft.Extensions.Configuration; | ||||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||||
|  | using Mirea.Api.Dto.Common; | ||||||
| using Mirea.Api.Endpoint.Configuration.Model; | using Mirea.Api.Endpoint.Configuration.Model; | ||||||
| using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; |  | ||||||
|  |  | ||||||
| namespace Mirea.Api.Endpoint.Configuration.Core.Startup; | namespace Mirea.Api.Endpoint.Configuration.Core.Startup; | ||||||
|  |  | ||||||
| @@ -10,7 +10,7 @@ public static class CacheConfiguration | |||||||
|     public static IServiceCollection AddCustomRedis(this IServiceCollection services, IConfiguration configuration, IHealthChecksBuilder? healthChecksBuilder = null) |     public static IServiceCollection AddCustomRedis(this IServiceCollection services, IConfiguration configuration, IHealthChecksBuilder? healthChecksBuilder = null) | ||||||
|     { |     { | ||||||
|         var cache = configuration.Get<GeneralConfig>()?.CacheSettings; |         var cache = configuration.Get<GeneralConfig>()?.CacheSettings; | ||||||
|         if (cache?.TypeDatabase != CacheSettings.CacheEnum.Redis) |         if (cache?.TypeDatabase != CacheType.Redis) | ||||||
|             return services; |             return services; | ||||||
|  |  | ||||||
|         services.AddStackExchangeRedisCache(options => |         services.AddStackExchangeRedisCache(options => | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| using Microsoft.Extensions.Configuration; | using Microsoft.Extensions.Configuration; | ||||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||||
|  | using Mirea.Api.Dto.Common; | ||||||
| using Mirea.Api.Endpoint.Common.Services.Security; | using Mirea.Api.Endpoint.Common.Services.Security; | ||||||
| using Mirea.Api.Endpoint.Configuration.Model; | using Mirea.Api.Endpoint.Configuration.Model; | ||||||
| using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; |  | ||||||
| using Mirea.Api.Security; | using Mirea.Api.Security; | ||||||
| using Mirea.Api.Security.Common.Interfaces; | using Mirea.Api.Security.Common.Interfaces; | ||||||
|  |  | ||||||
| @@ -16,7 +16,7 @@ public static class SecureConfiguration | |||||||
|  |  | ||||||
|         services.AddSingleton<IRevokedToken, MemoryRevokedTokenService>(); |         services.AddSingleton<IRevokedToken, MemoryRevokedTokenService>(); | ||||||
|  |  | ||||||
|         if (configuration.Get<GeneralConfig>()?.CacheSettings?.TypeDatabase == CacheSettings.CacheEnum.Redis) |         if (configuration.Get<GeneralConfig>()?.CacheSettings?.TypeDatabase == CacheType.Redis) | ||||||
|             services.AddSingleton<ICacheService, DistributedCacheService>(); |             services.AddSingleton<ICacheService, DistributedCacheService>(); | ||||||
|         else |         else | ||||||
|             services.AddSingleton<ICacheService, MemoryCacheService>(); |             services.AddSingleton<ICacheService, MemoryCacheService>(); | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using Mirea.Api.Endpoint.Configuration.Validation.Attributes; | using Mirea.Api.Dto.Common; | ||||||
|  | using Mirea.Api.Endpoint.Configuration.Validation.Attributes; | ||||||
| using Mirea.Api.Endpoint.Configuration.Validation.Interfaces; | using Mirea.Api.Endpoint.Configuration.Validation.Interfaces; | ||||||
|  |  | ||||||
| namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; | namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; | ||||||
| @@ -6,18 +7,12 @@ namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; | |||||||
| [RequiredSettings] | [RequiredSettings] | ||||||
| public class CacheSettings : IIsConfigured | public class CacheSettings : IIsConfigured | ||||||
| { | { | ||||||
|     public enum CacheEnum |     public CacheType TypeDatabase { get; set; } | ||||||
|     { |  | ||||||
|         Memcached, |  | ||||||
|         Redis |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public CacheEnum TypeDatabase { get; set; } |  | ||||||
|     public string? ConnectionString { get; set; } |     public string? ConnectionString { get; set; } | ||||||
|  |  | ||||||
|     public bool IsConfigured() |     public bool IsConfigured() | ||||||
|     { |     { | ||||||
|         return TypeDatabase == CacheEnum.Memcached || |         return TypeDatabase == CacheType.Memcached || | ||||||
|                !string.IsNullOrEmpty(ConnectionString); |                !string.IsNullOrEmpty(ConnectionString); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| using Mirea.Api.DataAccess.Persistence.Common; | using Mirea.Api.DataAccess.Persistence.Common; | ||||||
|  | using Mirea.Api.Dto.Common; | ||||||
| using Mirea.Api.Endpoint.Configuration.Validation.Attributes; | using Mirea.Api.Endpoint.Configuration.Validation.Attributes; | ||||||
| using Mirea.Api.Endpoint.Configuration.Validation.Interfaces; | using Mirea.Api.Endpoint.Configuration.Validation.Interfaces; | ||||||
| using System; | using System; | ||||||
| @@ -9,22 +10,16 @@ namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; | |||||||
| [RequiredSettings] | [RequiredSettings] | ||||||
| public class DbSettings : IIsConfigured | public class DbSettings : IIsConfigured | ||||||
| { | { | ||||||
|     public enum DatabaseEnum |     public DatabaseType TypeDatabase { get; set; } | ||||||
|     { |  | ||||||
|         Mysql, |  | ||||||
|         Sqlite, |  | ||||||
|         PostgresSql |  | ||||||
|     } |  | ||||||
|     public DatabaseEnum TypeDatabase { get; set; } |  | ||||||
|     public required string ConnectionStringSql { get; set; } |     public required string ConnectionStringSql { get; set; } | ||||||
|  |  | ||||||
|     [JsonIgnore] |     [JsonIgnore] | ||||||
|     public DatabaseProvider DatabaseProvider => |     public DatabaseProvider DatabaseProvider => | ||||||
|         TypeDatabase switch |         TypeDatabase switch | ||||||
|         { |         { | ||||||
|             DatabaseEnum.PostgresSql => DatabaseProvider.Postgresql, |             DatabaseType.PostgresSql => DatabaseProvider.Postgresql, | ||||||
|             DatabaseEnum.Mysql => DatabaseProvider.Mysql, |             DatabaseType.Mysql => DatabaseProvider.Mysql, | ||||||
|             DatabaseEnum.Sqlite => DatabaseProvider.Sqlite, |             DatabaseType.Sqlite => DatabaseProvider.Sqlite, | ||||||
|             _ => throw new ArgumentOutOfRangeException() |             _ => throw new ArgumentOutOfRangeException() | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,15 +4,21 @@ using Microsoft.AspNetCore.Http; | |||||||
| using Microsoft.AspNetCore.Mvc; | using Microsoft.AspNetCore.Mvc; | ||||||
| using Microsoft.Data.Sqlite; | using Microsoft.Data.Sqlite; | ||||||
| using Microsoft.Extensions.Caching.Memory; | using Microsoft.Extensions.Caching.Memory; | ||||||
|  | using Microsoft.Extensions.Options; | ||||||
|  | using Mirea.Api.Dto.Common; | ||||||
| using Mirea.Api.Dto.Requests; | using Mirea.Api.Dto.Requests; | ||||||
| using Mirea.Api.Dto.Requests.Configuration; | using Mirea.Api.Dto.Requests.Configuration; | ||||||
|  | using Mirea.Api.Dto.Responses; | ||||||
|  | using Mirea.Api.Dto.Responses.Configuration; | ||||||
| using Mirea.Api.Endpoint.Common.Attributes; | using Mirea.Api.Endpoint.Common.Attributes; | ||||||
| using Mirea.Api.Endpoint.Common.Exceptions; | using Mirea.Api.Endpoint.Common.Exceptions; | ||||||
| using Mirea.Api.Endpoint.Common.Interfaces; | using Mirea.Api.Endpoint.Common.Interfaces; | ||||||
|  | using Mirea.Api.Endpoint.Common.MapperDto; | ||||||
| using Mirea.Api.Endpoint.Common.Services; | using Mirea.Api.Endpoint.Common.Services; | ||||||
| using Mirea.Api.Endpoint.Configuration.Model; | using Mirea.Api.Endpoint.Configuration.Model; | ||||||
| using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; | using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; | ||||||
| using Mirea.Api.Endpoint.Configuration.Validation.Validators; | using Mirea.Api.Endpoint.Configuration.Validation.Validators; | ||||||
|  | using Mirea.Api.Security.Common.Domain; | ||||||
| using Mirea.Api.Security.Services; | using Mirea.Api.Security.Services; | ||||||
| using MySqlConnector; | using MySqlConnector; | ||||||
| using Npgsql; | using Npgsql; | ||||||
| @@ -36,7 +42,8 @@ public class SetupController( | |||||||
|     ISetupToken setupToken, |     ISetupToken setupToken, | ||||||
|     IMaintenanceModeNotConfigureService notConfigureService, |     IMaintenanceModeNotConfigureService notConfigureService, | ||||||
|     IMemoryCache cache, |     IMemoryCache cache, | ||||||
|     PasswordHashService passwordHashService) : BaseController |     PasswordHashService passwordHashService, | ||||||
|  |     IOptionsSnapshot<Admin> user) : BaseController | ||||||
| { | { | ||||||
|     private const string CacheGeneralKey = "config_general"; |     private const string CacheGeneralKey = "config_general"; | ||||||
|     private const string CacheAdminKey = "config_admin"; |     private const string CacheAdminKey = "config_admin"; | ||||||
| @@ -95,7 +102,12 @@ public class SetupController( | |||||||
|         return Ok(true); |         return Ok(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private ActionResult<bool> SetDatabase<TConnection, TException>(string connectionString, DbSettings.DatabaseEnum databaseType) |     [HttpGet("IsConfiguredToken")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     public ActionResult<bool> IsConfiguredToken() => | ||||||
|  |         Ok(true); | ||||||
|  |  | ||||||
|  |     private void SetDatabase<TConnection, TException>(string connectionString, DatabaseType databaseType) | ||||||
|         where TConnection : class, IDbConnection, new() |         where TConnection : class, IDbConnection, new() | ||||||
|         where TException : Exception |         where TException : Exception | ||||||
|     { |     { | ||||||
| @@ -118,8 +130,6 @@ public class SetupController( | |||||||
|                 TypeDatabase = databaseType |                 TypeDatabase = databaseType | ||||||
|             }; |             }; | ||||||
|             GeneralConfig = general; |             GeneralConfig = general; | ||||||
|  |  | ||||||
|             return Ok(true); |  | ||||||
|         } |         } | ||||||
|         catch (TException ex) |         catch (TException ex) | ||||||
|         { |         { | ||||||
| @@ -138,7 +148,20 @@ public class SetupController( | |||||||
|         if (request.Ssl) |         if (request.Ssl) | ||||||
|             connectionString += ";SSL Mode=Require;"; |             connectionString += ";SSL Mode=Require;"; | ||||||
|  |  | ||||||
|         return SetDatabase<NpgsqlConnection, NpgsqlException>(connectionString, DbSettings.DatabaseEnum.PostgresSql); |  | ||||||
|  |         SetDatabase<NpgsqlConnection, NpgsqlException>(connectionString, DatabaseType.PostgresSql); | ||||||
|  |         cache.Set("database", new DatabaseResponse | ||||||
|  |         { | ||||||
|  |             Type = DatabaseType.PostgresSql, | ||||||
|  |             Database = request.Database, | ||||||
|  |             Password = request.Password, | ||||||
|  |             Ssl = request.Ssl, | ||||||
|  |             Port = request.Port, | ||||||
|  |             Server = request.Server, | ||||||
|  |             User = request.User | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         return Ok(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [HttpPost("SetMysql")] |     [HttpPost("SetMysql")] | ||||||
| @@ -152,7 +175,19 @@ public class SetupController( | |||||||
|         if (request.Ssl) |         if (request.Ssl) | ||||||
|             connectionString += "SslMode=Require;"; |             connectionString += "SslMode=Require;"; | ||||||
|  |  | ||||||
|         return SetDatabase<MySqlConnection, MySqlException>(connectionString, DbSettings.DatabaseEnum.Mysql); |         SetDatabase<MySqlConnection, MySqlException>(connectionString, DatabaseType.Mysql); | ||||||
|  |         cache.Set("database", new DatabaseResponse | ||||||
|  |         { | ||||||
|  |             Type = DatabaseType.Mysql, | ||||||
|  |             Database = request.Database, | ||||||
|  |             Password = request.Password, | ||||||
|  |             Ssl = request.Ssl, | ||||||
|  |             Port = request.Port, | ||||||
|  |             Server = request.Server, | ||||||
|  |             User = request.User | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         return Ok(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [HttpPost("SetSqlite")] |     [HttpPost("SetSqlite")] | ||||||
| @@ -179,14 +214,26 @@ public class SetupController( | |||||||
|         var filePath = Path.Combine(path, "database.db3"); |         var filePath = Path.Combine(path, "database.db3"); | ||||||
|         var connectionString = $"Data Source={filePath}"; |         var connectionString = $"Data Source={filePath}"; | ||||||
|  |  | ||||||
|         var result = SetDatabase<SqliteConnection, SqliteException>(connectionString, DbSettings.DatabaseEnum.Sqlite); |         SetDatabase<SqliteConnection, SqliteException>(connectionString, DatabaseType.Sqlite); | ||||||
|  |  | ||||||
|         foreach (var file in Directory.GetFiles(path)) |         foreach (var file in Directory.GetFiles(path)) | ||||||
|             System.IO.File.Delete(file); |             System.IO.File.Delete(file); | ||||||
|  |  | ||||||
|         return result; |         cache.Set("database", new DatabaseResponse | ||||||
|  |         { | ||||||
|  |             Type = DatabaseType.Sqlite, | ||||||
|  |             PathToDatabase = path | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         return Ok(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("DatabaseConfiguration")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||||
|  |     public ActionResult<DatabaseRequest> DatabaseConfiguration() => | ||||||
|  |         cache.TryGetValue<DatabaseResponse>("database", out var response) ? Ok(response) : NoContent(); | ||||||
|  |  | ||||||
|     [HttpPost("SetRedis")] |     [HttpPost("SetRedis")] | ||||||
|     [TokenAuthentication] |     [TokenAuthentication] | ||||||
|     [BadRequestResponse] |     [BadRequestResponse] | ||||||
| @@ -205,10 +252,17 @@ public class SetupController( | |||||||
|             general.CacheSettings = new CacheSettings |             general.CacheSettings = new CacheSettings | ||||||
|             { |             { | ||||||
|                 ConnectionString = connectionString, |                 ConnectionString = connectionString, | ||||||
|                 TypeDatabase = CacheSettings.CacheEnum.Redis |                 TypeDatabase = CacheType.Redis | ||||||
|             }; |             }; | ||||||
|             GeneralConfig = general; |             GeneralConfig = general; | ||||||
|  |  | ||||||
|  |             cache.Set("cache", new CacheResponse | ||||||
|  |             { | ||||||
|  |                 Type = CacheType.Redis, | ||||||
|  |                 Server = request.Server, | ||||||
|  |                 Password = request.Password, | ||||||
|  |                 Port = request.Port | ||||||
|  |             }); | ||||||
|             return Ok(true); |             return Ok(true); | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
| @@ -226,20 +280,29 @@ public class SetupController( | |||||||
|         general.CacheSettings = new CacheSettings |         general.CacheSettings = new CacheSettings | ||||||
|         { |         { | ||||||
|             ConnectionString = null, |             ConnectionString = null, | ||||||
|             TypeDatabase = CacheSettings.CacheEnum.Memcached |             TypeDatabase = CacheType.Memcached | ||||||
|         }; |         }; | ||||||
|         GeneralConfig = general; |         GeneralConfig = general; | ||||||
|  |  | ||||||
|  |         cache.Set("cache", new CacheResponse | ||||||
|  |         { | ||||||
|  |             Type = CacheType.Memcached | ||||||
|  |         }); | ||||||
|         return Ok(true); |         return Ok(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("CacheConfiguration")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||||
|  |     public ActionResult<CacheResponse> CacheConfiguration() => | ||||||
|  |         cache.TryGetValue<CacheResponse>("cache", out var response) ? Ok(response) : NoContent(); | ||||||
|  |  | ||||||
|     [HttpPost("CreateAdmin")] |     [HttpPost("CreateAdmin")] | ||||||
|     [TokenAuthentication] |     [TokenAuthentication] | ||||||
|     [BadRequestResponse] |     [BadRequestResponse] | ||||||
|     public ActionResult<string> CreateAdmin([FromBody] CreateUserRequest user) |     public ActionResult<string> CreateAdmin([FromBody] CreateUserRequest user) | ||||||
|     { |     { | ||||||
|         if (!PasswordHashService.HasPasswordInPolicySecurity(user.Password)) |         new PasswordPolicyService(GeneralConfig.PasswordPolicy).ValidatePasswordOrThrow(user.Password); | ||||||
|             throw new ControllerArgumentException("The password must be at least 8 characters long and contain at least one uppercase letter and one special character."); |  | ||||||
|  |  | ||||||
|         if (!MailAddress.TryCreate(user.Email, out _)) |         if (!MailAddress.TryCreate(user.Email, out _)) | ||||||
|             throw new ControllerArgumentException("The email address is incorrect."); |             throw new ControllerArgumentException("The email address is incorrect."); | ||||||
| @@ -258,6 +321,73 @@ public class SetupController( | |||||||
|         return Ok(true); |         return Ok(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("UpdateAdminConfiguration")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     public ActionResult UpdateAdminConfiguration() | ||||||
|  |     { | ||||||
|  |         if (string.IsNullOrEmpty(user.Value.Email)) | ||||||
|  |             return Ok(); | ||||||
|  |  | ||||||
|  |         if (!cache.TryGetValue<Admin>(CacheAdminKey, out var admin)) | ||||||
|  |         { | ||||||
|  |             admin = user.Value; | ||||||
|  |             cache.Set(CacheAdminKey, admin); | ||||||
|  |             return Ok(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         admin!.OAuthProviders = user.Value.OAuthProviders; | ||||||
|  |  | ||||||
|  |         if (string.IsNullOrEmpty(admin.Email)) | ||||||
|  |             admin.Email = user.Value.Email; | ||||||
|  |  | ||||||
|  |         if (string.IsNullOrEmpty(admin.Username)) | ||||||
|  |             admin.Username = user.Value.Username; | ||||||
|  |  | ||||||
|  |         cache.Set(CacheAdminKey, admin); | ||||||
|  |         return Ok(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("AdminConfiguration")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||||
|  |     public ActionResult<UserResponse> AdminConfiguration() => | ||||||
|  |         cache.TryGetValue<Admin>(CacheAdminKey, out var admin) ? Ok(new UserResponse() | ||||||
|  |         { | ||||||
|  |             Email = admin!.Email, | ||||||
|  |             Username = admin.Username, | ||||||
|  |             TwoFactorAuthenticatorEnabled = admin.TwoFactorAuthenticator != TwoFactorAuthenticator.None, | ||||||
|  |             UsedOAuthProviders = admin.OAuthProviders == null ? [] : admin.OAuthProviders.Keys.Select(x => x.ConvertToDto()) | ||||||
|  |         }) : NoContent(); | ||||||
|  |  | ||||||
|  |     [HttpGet("GenerateTotpKey")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     public ActionResult<string> GenerateTotpKey() | ||||||
|  |     { | ||||||
|  |         if (cache.TryGetValue<string>("totpSecret", out var secret)) | ||||||
|  |             return secret!; | ||||||
|  |  | ||||||
|  |         secret = GeneratorKey.GenerateAlphaNumericBase32Compatible(16); | ||||||
|  |         cache.Set("totpSecret", secret); | ||||||
|  |         return secret; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("VerifyTotp")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     public ActionResult<bool> VerifyTotp([FromQuery] string code) | ||||||
|  |     { | ||||||
|  |         var isCorrect = cache.TryGetValue<string>("totpSecret", out var secret) && | ||||||
|  |                         new TotpService(secret!).VerifyToken(code); | ||||||
|  |  | ||||||
|  |         if (!isCorrect || !cache.TryGetValue<Admin>(CacheAdminKey, out var admin)) | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|  |         admin!.Secret = secret; | ||||||
|  |         admin.TwoFactorAuthenticator = TwoFactorAuthenticator.Totp; | ||||||
|  |         cache.Set(CacheAdminKey, admin); | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     [HttpPost("SetLogging")] |     [HttpPost("SetLogging")] | ||||||
|     [TokenAuthentication] |     [TokenAuthentication] | ||||||
|     [BadRequestResponse] |     [BadRequestResponse] | ||||||
| @@ -292,9 +422,22 @@ public class SetupController( | |||||||
|         general.LogSettings = settings; |         general.LogSettings = settings; | ||||||
|         GeneralConfig = general; |         GeneralConfig = general; | ||||||
|  |  | ||||||
|  |         cache.Set("logging", new LoggingRequest | ||||||
|  |         { | ||||||
|  |             EnableLogToFile = settings.EnableLogToFile, | ||||||
|  |             LogFileName = settings.LogFileName, | ||||||
|  |             LogFilePath = settings.LogFilePath | ||||||
|  |         }); | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("LoggingConfiguration")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||||
|  |     public ActionResult<LoggingRequest> LoggingConfiguration() => | ||||||
|  |         cache.TryGetValue<LoggingRequest>("logging", out var data) ? Ok(data) : NoContent(); | ||||||
|  |  | ||||||
|     [HttpPost("SetEmail")] |     [HttpPost("SetEmail")] | ||||||
|     [TokenAuthentication] |     [TokenAuthentication] | ||||||
|     [BadRequestResponse] |     [BadRequestResponse] | ||||||
| @@ -318,9 +461,16 @@ public class SetupController( | |||||||
|         general.EmailSettings = settings; |         general.EmailSettings = settings; | ||||||
|         GeneralConfig = general; |         GeneralConfig = general; | ||||||
|  |  | ||||||
|  |         cache.Set("email", settings); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("EmailConfiguration")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||||
|  |     public ActionResult<EmailRequest> EmailConfiguration() => | ||||||
|  |         cache.TryGetValue<EmailRequest>("email", out var data) ? Ok(data) : NoContent(); | ||||||
|  |  | ||||||
|     [HttpPost("SetSchedule")] |     [HttpPost("SetSchedule")] | ||||||
|     [TokenAuthentication] |     [TokenAuthentication] | ||||||
|     [BadRequestResponse] |     [BadRequestResponse] | ||||||
| @@ -349,8 +499,20 @@ public class SetupController( | |||||||
|  |  | ||||||
|         GeneralConfig = general; |         GeneralConfig = general; | ||||||
|  |  | ||||||
|  |         cache.Set("schedule", new ScheduleConfigurationRequest() | ||||||
|  |         { | ||||||
|  |             StartTerm = general.ScheduleSettings.StartTerm, | ||||||
|  |             CronUpdateSchedule = general.ScheduleSettings.CronUpdateSchedule | ||||||
|  |         }); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("ScheduleConfiguration")] | ||||||
|  |     [TokenAuthentication] | ||||||
|  |     [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||||
|  |     public ActionResult<ScheduleConfigurationRequest> ScheduleConfiguration() => | ||||||
|  |         cache.TryGetValue<ScheduleConfigurationRequest>("schedule", out var data) ? Ok(data) : NoContent(); | ||||||
|  |  | ||||||
|     [HttpPost("SetPasswordPolicy")] |     [HttpPost("SetPasswordPolicy")] | ||||||
|     [TokenAuthentication] |     [TokenAuthentication] | ||||||
|     public ActionResult<bool> SetPasswordPolicy([FromBody] PasswordPolicy? policy = null) |     public ActionResult<bool> SetPasswordPolicy([FromBody] PasswordPolicy? policy = null) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user