Compare commits

..

No commits in common. "592e8a1b4230e8c20f81d781dc3e42f687d97d23" and "535bafa73a44e0f62e7caa0a87589e8982e7dd61" have entirely different histories.

6 changed files with 17 additions and 55 deletions

View File

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

View File

@ -7,7 +7,6 @@ using Mirea.Api.Dto.Common;
using Mirea.Api.Dto.Requests; using Mirea.Api.Dto.Requests;
using Mirea.Api.Dto.Responses; using Mirea.Api.Dto.Responses;
using Mirea.Api.Endpoint.Common.Attributes; using Mirea.Api.Endpoint.Common.Attributes;
using Mirea.Api.Endpoint.Common.Exceptions;
using Mirea.Api.Endpoint.Common.Services; using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Endpoint.Common.Settings; using Mirea.Api.Endpoint.Common.Settings;
using Mirea.Api.Security.Common.Dto.Requests; using Mirea.Api.Security.Common.Dto.Requests;
@ -166,29 +165,4 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
[Authorize] [Authorize]
[CacheMaxAge(0, 0, 1)] [CacheMaxAge(0, 0, 1)]
public ActionResult<AuthRoles> GetRole() => Ok(AuthRoles.Admin); 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> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Company>Winsomnia</Company> <Company>Winsomnia</Company>
<Version>1.0.0-b3</Version> <Version>1.0.0-b0</Version>
<AssemblyVersion>1.0.1.3</AssemblyVersion> <AssemblyVersion>1.0.1.0</AssemblyVersion>
<FileVersion>1.0.1.3</FileVersion> <FileVersion>1.0.1.0</FileVersion>
<AssemblyName>Mirea.Api.Endpoint</AssemblyName> <AssemblyName>Mirea.Api.Endpoint</AssemblyName>
<RootNamespace>$(AssemblyName)</RootNamespace> <RootNamespace>$(AssemblyName)</RootNamespace>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
@ -23,21 +23,20 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Cronos" Version="0.8.4" /> <PackageReference Include="Cronos" Version="0.8.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.7">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </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.Formatting.Compact" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.8" /> <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.7" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.2" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.7.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Versioning" Version="2.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore.Versioning" Version="2.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,11 +1,10 @@
using Konscious.Security.Cryptography; using Konscious.Security.Cryptography;
using System; using System;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
namespace Mirea.Api.Security.Services; namespace Mirea.Api.Security.Services;
public partial class PasswordHashService public class PasswordHashService
{ {
public int SaltSize { private get; init; } public int SaltSize { private get; init; }
public int HashSize { private get; init; } public int HashSize { private get; init; }
@ -54,15 +53,4 @@ public partial class PasswordHashService
public bool VerifyPassword(string password, string saltBase64, string hashBase64) => public bool VerifyPassword(string password, string saltBase64, string hashBase64) =>
VerifyPassword(password, Convert.FromBase64String(saltBase64), Convert.FromBase64String(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" Version="11.9.2" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" /> <PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" />
<PackageReference Include="MediatR" Version="12.4.0" /> <PackageReference Include="MediatR" Version="12.4.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.7" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

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