Правка чатов, опциональная регистрация
This commit is contained in:
@@ -3,6 +3,9 @@ using Knot.Shared.Kernel.Configuration;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Knot.Modules.Chats.Infrastructure.Persistence;
|
||||
using MediatR;
|
||||
using Knot.Modules.Identity.Application.Users.Register;
|
||||
using Knot.Modules.Identity.Application.Abstractions;
|
||||
|
||||
namespace Host.Controllers;
|
||||
|
||||
@@ -14,17 +17,23 @@ public class AdminController : ControllerBase
|
||||
private readonly Knot.Shared.Kernel.Services.IStatisticsService _statisticsService;
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly ChatsDbContext _chatsDbContext;
|
||||
private readonly ISender _sender;
|
||||
private readonly IIdentityUnitOfWork _identityUnitOfWork;
|
||||
|
||||
public AdminController(
|
||||
ISettingsService settingsService,
|
||||
Knot.Shared.Kernel.Services.IStatisticsService statisticsService,
|
||||
IUserRepository userRepository,
|
||||
ChatsDbContext chatsDbContext)
|
||||
ChatsDbContext chatsDbContext,
|
||||
ISender sender,
|
||||
IIdentityUnitOfWork identityUnitOfWork)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_statisticsService = statisticsService;
|
||||
_userRepository = userRepository;
|
||||
_chatsDbContext = chatsDbContext;
|
||||
_sender = sender;
|
||||
_identityUnitOfWork = identityUnitOfWork;
|
||||
}
|
||||
|
||||
[HttpGet("settings")]
|
||||
@@ -47,6 +56,40 @@ public class AdminController : ControllerBase
|
||||
var stats = await _statisticsService.GetDashboardStatsAsync(ct);
|
||||
return Ok(stats);
|
||||
}
|
||||
|
||||
[HttpPost("users")]
|
||||
public async Task<IActionResult> CreateUser([FromBody] RegisterUserCommand command)
|
||||
{
|
||||
var result = await _sender.Send(command);
|
||||
if (result.IsFailure)
|
||||
{
|
||||
return BadRequest(new { error = result.Error.Description });
|
||||
}
|
||||
|
||||
var user = await _userRepository.GetByIdAsync(result.Value, default);
|
||||
return Ok(new {
|
||||
user.Id,
|
||||
user.Username,
|
||||
user.DisplayName,
|
||||
user.Email,
|
||||
user.CreatedAt
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("users/{userId:guid}/reset-password")]
|
||||
public async Task<IActionResult> ResetUserPassword(Guid userId, [FromBody] ResetPasswordDto dto, CancellationToken ct)
|
||||
{
|
||||
var user = await _userRepository.GetByIdAsync(userId, ct);
|
||||
if (user == null) return NotFound(new { error = "User not found" });
|
||||
|
||||
if (string.IsNullOrWhiteSpace(dto.NewPassword)) return BadRequest(new { error = "Password cannot be empty" });
|
||||
|
||||
var hash = BCrypt.Net.BCrypt.HashPassword(dto.NewPassword);
|
||||
user.ChangePassword(hash);
|
||||
|
||||
await _identityUnitOfWork.SaveChangesAsync(ct);
|
||||
return Ok(new { success = true });
|
||||
}
|
||||
|
||||
[HttpGet("users")]
|
||||
public async Task<IActionResult> SearchUsers([FromQuery] string query = "", CancellationToken ct = default)
|
||||
@@ -115,3 +158,8 @@ public class AdminController : ControllerBase
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class ResetPasswordDto
|
||||
{
|
||||
public string NewPassword { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ using Knot.Modules.Identity.Application.Users.Register;
|
||||
using Knot.Modules.Identity.Application.Users.Login;
|
||||
using Knot.Modules.Identity.Application.Abstractions;
|
||||
using Knot.Modules.Identity.Domain;
|
||||
using Knot.Modules.Identity.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Shared.Kernel.Configuration;
|
||||
|
||||
namespace Host.Controllers;
|
||||
|
||||
@@ -16,17 +18,23 @@ public sealed class AuthController : ControllerBase
|
||||
private readonly ISender _sender;
|
||||
private readonly IJwtTokenProvider _tokenProvider;
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly ISettingsService _settings;
|
||||
|
||||
public AuthController(ISender sender, IJwtTokenProvider tokenProvider, IUserRepository userRepository)
|
||||
public AuthController(ISender sender, IJwtTokenProvider tokenProvider, IUserRepository userRepository, ISettingsService settings)
|
||||
{
|
||||
_sender = sender;
|
||||
_tokenProvider = tokenProvider;
|
||||
_userRepository = userRepository;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
[HttpPost("register")]
|
||||
public async Task<IActionResult> Register([FromBody] RegisterUserCommand command)
|
||||
{
|
||||
if (!_settings.Current.EnableRegistration)
|
||||
{
|
||||
return BadRequest(new { error = "Registration is disabled by the administrator." });
|
||||
}
|
||||
Result<Guid> result = await _sender.Send(command);
|
||||
|
||||
if (result.IsFailure)
|
||||
|
||||
@@ -17,6 +17,7 @@ public class ConfigController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult GetPublicConfig()
|
||||
{
|
||||
var conf = _settings.Current;
|
||||
@@ -26,7 +27,8 @@ public class ConfigController : ControllerBase
|
||||
conf.EnableKlipy,
|
||||
conf.MaxFileSizeMb,
|
||||
conf.MaxGroupMembers,
|
||||
conf.EnableConfederation
|
||||
conf.EnableConfederation,
|
||||
conf.EnableRegistration
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class Story : Entity<Guid>
|
||||
public IReadOnlyCollection<StoryReaction> Reactions => _reactions.AsReadOnly();
|
||||
public IReadOnlyCollection<StoryReply> Replies => _replies.AsReadOnly();
|
||||
|
||||
protected Story() : base(Guid.NewGuid()) { }
|
||||
protected Story() : base(Guid.NewGuid()) { Type = string.Empty; }
|
||||
|
||||
internal Story(Guid id, Guid userId, string type, string? mediaUrl, string? content, string? bgColor) : base(id)
|
||||
{
|
||||
|
||||
@@ -52,4 +52,9 @@ public sealed class User : AggregateRoot<Guid>
|
||||
{
|
||||
HideStoryViews = hideStoryViews;
|
||||
}
|
||||
|
||||
public void ChangePassword(string newPasswordHash)
|
||||
{
|
||||
PasswordHash = newPasswordHash;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -58,7 +58,7 @@ public sealed class IdentityDbContext : DbContext, IIdentityUnitOfWork
|
||||
builder.Property(s => s.Content)
|
||||
.HasConversion(
|
||||
v => v == null ? null : _encryptionService.EncryptMessage(v),
|
||||
v => v == null ? null : _encryptionService.DecryptMessage(v)
|
||||
v => v == null ? null : _encryptionService.DecryptMessage(v)!
|
||||
);
|
||||
|
||||
// Configure backing fields for collections
|
||||
@@ -106,8 +106,8 @@ public sealed class IdentityDbContext : DbContext, IIdentityUnitOfWork
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasConversion(
|
||||
v => v == null ? null : _encryptionService.EncryptMessage(v),
|
||||
v => v == null ? null : _encryptionService.DecryptMessage(v)
|
||||
v => _encryptionService.EncryptMessage(v) ?? string.Empty,
|
||||
v => _encryptionService.DecryptMessage(v) ?? string.Empty
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -22,4 +22,7 @@ public class SystemSettingsDto
|
||||
// Confederation
|
||||
public bool EnableConfederation { get; set; } = false;
|
||||
public List<string> AllowedDomains { get; set; } = new();
|
||||
|
||||
// Auth
|
||||
public bool EnableRegistration { get; set; } = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user