feat: add a return of the data that has been configured
This commit is contained in:
@ -4,15 +4,21 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Mirea.Api.Dto.Common;
|
||||
using Mirea.Api.Dto.Requests;
|
||||
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.Exceptions;
|
||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
||||
using Mirea.Api.Endpoint.Common.MapperDto;
|
||||
using Mirea.Api.Endpoint.Common.Services;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Validators;
|
||||
using Mirea.Api.Security.Common.Domain;
|
||||
using Mirea.Api.Security.Services;
|
||||
using MySqlConnector;
|
||||
using Npgsql;
|
||||
@ -36,7 +42,8 @@ public class SetupController(
|
||||
ISetupToken setupToken,
|
||||
IMaintenanceModeNotConfigureService notConfigureService,
|
||||
IMemoryCache cache,
|
||||
PasswordHashService passwordHashService) : BaseController
|
||||
PasswordHashService passwordHashService,
|
||||
IOptionsSnapshot<Admin> user) : BaseController
|
||||
{
|
||||
private const string CacheGeneralKey = "config_general";
|
||||
private const string CacheAdminKey = "config_admin";
|
||||
@ -95,7 +102,12 @@ public class SetupController(
|
||||
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 TException : Exception
|
||||
{
|
||||
@ -118,8 +130,6 @@ public class SetupController(
|
||||
TypeDatabase = databaseType
|
||||
};
|
||||
GeneralConfig = general;
|
||||
|
||||
return Ok(true);
|
||||
}
|
||||
catch (TException ex)
|
||||
{
|
||||
@ -138,7 +148,20 @@ public class SetupController(
|
||||
if (request.Ssl)
|
||||
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")]
|
||||
@ -152,7 +175,19 @@ public class SetupController(
|
||||
if (request.Ssl)
|
||||
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")]
|
||||
@ -179,14 +214,26 @@ public class SetupController(
|
||||
var filePath = Path.Combine(path, "database.db3");
|
||||
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))
|
||||
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")]
|
||||
[TokenAuthentication]
|
||||
[BadRequestResponse]
|
||||
@ -205,10 +252,17 @@ public class SetupController(
|
||||
general.CacheSettings = new CacheSettings
|
||||
{
|
||||
ConnectionString = connectionString,
|
||||
TypeDatabase = CacheSettings.CacheEnum.Redis
|
||||
TypeDatabase = CacheType.Redis
|
||||
};
|
||||
GeneralConfig = general;
|
||||
|
||||
cache.Set("cache", new CacheResponse
|
||||
{
|
||||
Type = CacheType.Redis,
|
||||
Server = request.Server,
|
||||
Password = request.Password,
|
||||
Port = request.Port
|
||||
});
|
||||
return Ok(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -226,20 +280,29 @@ public class SetupController(
|
||||
general.CacheSettings = new CacheSettings
|
||||
{
|
||||
ConnectionString = null,
|
||||
TypeDatabase = CacheSettings.CacheEnum.Memcached
|
||||
TypeDatabase = CacheType.Memcached
|
||||
};
|
||||
GeneralConfig = general;
|
||||
|
||||
cache.Set("cache", new CacheResponse
|
||||
{
|
||||
Type = CacheType.Memcached
|
||||
});
|
||||
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")]
|
||||
[TokenAuthentication]
|
||||
[BadRequestResponse]
|
||||
public ActionResult<string> CreateAdmin([FromBody] CreateUserRequest user)
|
||||
{
|
||||
if (!PasswordHashService.HasPasswordInPolicySecurity(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.");
|
||||
new PasswordPolicyService(GeneralConfig.PasswordPolicy).ValidatePasswordOrThrow(user.Password);
|
||||
|
||||
if (!MailAddress.TryCreate(user.Email, out _))
|
||||
throw new ControllerArgumentException("The email address is incorrect.");
|
||||
@ -258,6 +321,73 @@ public class SetupController(
|
||||
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")]
|
||||
[TokenAuthentication]
|
||||
[BadRequestResponse]
|
||||
@ -292,9 +422,22 @@ public class SetupController(
|
||||
general.LogSettings = settings;
|
||||
GeneralConfig = general;
|
||||
|
||||
cache.Set("logging", new LoggingRequest
|
||||
{
|
||||
EnableLogToFile = settings.EnableLogToFile,
|
||||
LogFileName = settings.LogFileName,
|
||||
LogFilePath = settings.LogFilePath
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[HttpGet("LoggingConfiguration")]
|
||||
[TokenAuthentication]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public ActionResult<LoggingRequest> LoggingConfiguration() =>
|
||||
cache.TryGetValue<LoggingRequest>("logging", out var data) ? Ok(data) : NoContent();
|
||||
|
||||
[HttpPost("SetEmail")]
|
||||
[TokenAuthentication]
|
||||
[BadRequestResponse]
|
||||
@ -318,9 +461,16 @@ public class SetupController(
|
||||
general.EmailSettings = settings;
|
||||
GeneralConfig = general;
|
||||
|
||||
cache.Set("email", settings);
|
||||
return true;
|
||||
}
|
||||
|
||||
[HttpGet("EmailConfiguration")]
|
||||
[TokenAuthentication]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public ActionResult<EmailRequest> EmailConfiguration() =>
|
||||
cache.TryGetValue<EmailRequest>("email", out var data) ? Ok(data) : NoContent();
|
||||
|
||||
[HttpPost("SetSchedule")]
|
||||
[TokenAuthentication]
|
||||
[BadRequestResponse]
|
||||
@ -349,8 +499,20 @@ public class SetupController(
|
||||
|
||||
GeneralConfig = general;
|
||||
|
||||
cache.Set("schedule", new ScheduleConfigurationRequest()
|
||||
{
|
||||
StartTerm = general.ScheduleSettings.StartTerm,
|
||||
CronUpdateSchedule = general.ScheduleSettings.CronUpdateSchedule
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
[HttpGet("ScheduleConfiguration")]
|
||||
[TokenAuthentication]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public ActionResult<ScheduleConfigurationRequest> ScheduleConfiguration() =>
|
||||
cache.TryGetValue<ScheduleConfigurationRequest>("schedule", out var data) ? Ok(data) : NoContent();
|
||||
|
||||
[HttpPost("SetPasswordPolicy")]
|
||||
[TokenAuthentication]
|
||||
public ActionResult<bool> SetPasswordPolicy([FromBody] PasswordPolicy? policy = null)
|
||||
|
Reference in New Issue
Block a user