Правки админки, вход

This commit is contained in:
Халимов Рустам
2026-03-31 23:55:38 +03:00
parent bce8f92101
commit 2c6d6f831f
13 changed files with 264 additions and 51 deletions

View File

@@ -0,0 +1,68 @@
using BCrypt.Net;
using Knot.Contracts.Auth.Application.Abstractions;
using Knot.Contracts.Auth.Domain;
using Knot.Modules.Admin.Application.Admin.DTOs;
using Knot.Shared.Kernel;
using MediatR;
namespace Knot.Modules.Admin.Application.Admin.Commands.CreateUser;
public record CreateUserCommand(
string Username,
string Password,
string DisplayName,
string? Email = null,
string? Bio = null
) : ICommand<AdminUserDto>;
internal sealed class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, AdminUserDto>
{
private readonly IUserRepository _userRepository;
private readonly IAuthUnitOfWork _unitOfWork;
public CreateUserCommandHandler(IUserRepository userRepository, IAuthUnitOfWork unitOfWork)
{
_userRepository = userRepository;
_unitOfWork = unitOfWork;
}
public async Task<Result<AdminUserDto>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
// Проверка уникальности username
if (!await _userRepository.IsUsernameUniqueAsync(request.Username, cancellationToken))
{
return Result.Failure<AdminUserDto>(new Error("Admin.CreateUser.UsernameNotUnique", "Username is already taken"));
}
// Хеширование пароля
string passwordHash = BCrypt.Net.BCrypt.HashPassword(request.Password);
// Создание контракта пользователя
var userContract = new UserContract
{
Id = Guid.NewGuid(),
Username = request.Username,
PasswordHash = passwordHash,
DisplayName = request.DisplayName,
Email = request.Email,
Bio = request.Bio,
CreatedAt = DateTime.UtcNow,
IsBanned = false,
IsOnline = false
};
_unitOfWork.Add(userContract);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success(new AdminUserDto(
userContract.Id,
userContract.Username,
userContract.DisplayName,
userContract.Email,
userContract.Avatar,
userContract.CreatedAt,
userContract.IsOnline,
userContract.LastSeen ?? DateTime.UtcNow,
userContract.IsBanned));
}
}

View File

@@ -18,7 +18,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="BCrypt.Net-Next" Version="4.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,9 @@
using System.Text.Json.Serialization;
using Knot.Contracts.Conversations.Abstractions;
using Knot.Contracts.Settings.Application.Abstractions;
using Knot.Contracts.Settings.Application.DTOs;
using Knot.Modules.Admin.Application.Admin.Commands;
using Knot.Modules.Admin.Application.Admin.Commands.CreateUser;
using Knot.Modules.Admin.Application.Admin.Commands.TestKlipy;
using Knot.Modules.Admin.Application.Admin.Queries;
using MediatR;
@@ -56,6 +58,12 @@ public static class AdminEndpoints
return Results.Ok(result.Value);
});
group.MapPost("users", async ([FromBody] CreateUserCommand command, ISender sender, CancellationToken ct) =>
{
var result = await sender.Send(command, ct);
return result.IsSuccess ? Results.Created($"/api/admin/users/{result.Value.Id}", result.Value) : Results.BadRequest(new { error = result.Error.Description });
});
group.MapPost("users/{userId:guid}/reset-password", async ([FromRoute] Guid userId, [FromBody] ResetPasswordRequest dto, ISender sender, CancellationToken ct) =>
{
var result = await sender.Send(new ResetUserPasswordCommand(userId, dto.NewPassword), ct);
@@ -106,6 +114,12 @@ public static class AdminEndpoints
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound("User not found");
});
group.MapDelete("users/{userId:guid}", async ([FromRoute] Guid userId, IUserDeleterService userDeleter, CancellationToken ct) =>
{
var result = await userDeleter.DeleteUserAsync(userId, ct);
return result.IsSuccess ? Results.Ok() : Results.BadRequest(new { error = result.Error.Description });
});
group.MapGet("clean/dry-run", async (ISender sender, CancellationToken ct) =>
{
var result = await sender.Send(new CleanDryRunQuery(), ct);