Compare commits

...

3 Commits

Author SHA1 Message Date
592e8a1b42 feat: add renew password
Some checks failed
Build and Deploy Docker Container / build-and-deploy (push) Failing after 1m34s
.NET Test Pipeline / build-and-test (push) Has been cancelled
2024-08-27 22:52:07 +03:00
a27549092b refactor: move checking password 2024-08-27 22:51:14 +03:00
f27d07fb5a build: upgrade ref 2024-08-27 22:50:21 +03:00
6 changed files with 55 additions and 17 deletions

View File

@ -23,7 +23,6 @@ using System.IO;
using System.Net.Mail;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace Mirea.Api.Endpoint.Controllers.Configuration;
@ -31,7 +30,7 @@ namespace Mirea.Api.Endpoint.Controllers.Configuration;
[ApiController]
[MaintenanceModeIgnore]
[ApiExplorerSettings(IgnoreApi = true)]
public partial class SetupController(
public class SetupController(
ISetupToken setupToken,
IMaintenanceModeNotConfigureService notConfigureService,
IMemoryCache cache,
@ -212,7 +211,7 @@ public partial class SetupController(
[BadRequestResponse]
public ActionResult<string> CreateAdmin([FromBody] CreateUserRequest user)
{
if (user.Password.Length < 8 || !PasswordExistUpperLetter().IsMatch(user.Password) || !PasswordExistSpecialSymbol().IsMatch(user.Password))
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.");
if (!MailAddress.TryCreate(user.Email, out _))

View File

@ -7,6 +7,7 @@ using Mirea.Api.Dto.Common;
using Mirea.Api.Dto.Requests;
using Mirea.Api.Dto.Responses;
using Mirea.Api.Endpoint.Common.Attributes;
using Mirea.Api.Endpoint.Common.Exceptions;
using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Endpoint.Common.Settings;
using Mirea.Api.Security.Common.Dto.Requests;
@ -165,4 +166,29 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
[Authorize]
[CacheMaxAge(0, 0, 1)]
public ActionResult<AuthRoles> GetRole() => Ok(AuthRoles.Admin);
[HttpPost("RenewPassword")]
[ApiExplorerSettings(IgnoreApi = true)]
[Localhost]
[BadRequestResponse]
public ActionResult<string> RenewPassword([FromBody] string? password = null)
{
if (string.IsNullOrEmpty(password))
password = string.Empty;
else if (!PasswordHashService.HasPasswordInPolicySecurity(password))
throw new ControllerArgumentException("The password must be at least 8 characters long and contain at least one uppercase letter and one special character.");
while (!PasswordHashService.HasPasswordInPolicySecurity(password))
password = GeneratorKey.GenerateAlphaNumeric(16, includes: "!@#%^");
var (salt, hash) = passwordService.HashPassword(password);
var admin = user.Value;
admin.Salt = salt;
admin.PasswordHash = hash;
admin.SaveSetting();
return Ok(password);
}
}

View File

@ -5,9 +5,9 @@
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<Company>Winsomnia</Company>
<Version>1.0.0-b0</Version>
<AssemblyVersion>1.0.1.0</AssemblyVersion>
<FileVersion>1.0.1.0</FileVersion>
<Version>1.0.0-b3</Version>
<AssemblyVersion>1.0.1.3</AssemblyVersion>
<FileVersion>1.0.1.3</FileVersion>
<AssemblyName>Mirea.Api.Endpoint</AssemblyName>
<RootNamespace>$(AssemblyName)</RootNamespace>
<OutputType>Exe</OutputType>
@ -23,20 +23,21 @@
<ItemGroup>
<PackageReference Include="Cronos" Version="0.8.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.7">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.7" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.8" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.7.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Versioning" Version="2.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
</ItemGroup>
<ItemGroup>

View File

@ -1,10 +1,11 @@
using Konscious.Security.Cryptography;
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Mirea.Api.Security.Services;
public class PasswordHashService
public partial class PasswordHashService
{
public int SaltSize { private get; init; }
public int HashSize { private get; init; }
@ -53,4 +54,15 @@ public class PasswordHashService
public bool VerifyPassword(string password, string saltBase64, string hashBase64) =>
VerifyPassword(password, Convert.FromBase64String(saltBase64), Convert.FromBase64String(hashBase64));
public static bool HasPasswordInPolicySecurity(string password) =>
password.Length >= 8 &&
PasswordExistSpecialSymbol().IsMatch(password) &&
PasswordExistUpperLetter().IsMatch(password);
[GeneratedRegex("[A-Z]+")]
private static partial Regex PasswordExistUpperLetter();
[GeneratedRegex("[!@#$%^&*]+")]
private static partial Regex PasswordExistSpecialSymbol();
}

View File

@ -16,7 +16,7 @@
<PackageReference Include="FluentValidation" Version="11.9.2" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" />
<PackageReference Include="MediatR" Version="12.4.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
</ItemGroup>
<ItemGroup>

View File

@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
</ItemGroup>