Invitation globale work

+ tests
+ new services
+ InvitationDto and IInvitationReqest
This commit is contained in:
Artemy
2025-06-24 21:20:43 +07:00
parent f99ec0b17b
commit 76094af15b
38 changed files with 483 additions and 1640 deletions
@@ -4,6 +4,7 @@ using Govor.Core.Infrastructure.Extensions;
using Govor.Core.Models;
using Govor.Core.Repositories.Users;
using Govor.API.Services;
using Govor.API.Services.AdminsStuff.Interfaces;
using Govor.Core.Repositories.Admins;
using Govor.Core.Repositories.Invaites;
@@ -15,35 +16,27 @@ public class AuthService : IAccountService
private readonly IPasswordHasher _passwordHasher;
private readonly IJwtService _jwtService;
private readonly IUsersRepository _usersRepository;
private readonly IInvitesRepository _invitesRepository;
private readonly IAdminsRepository _adminsRepository;
public AuthService(IUsersRepository usersRepository,
IJwtService jwtService,
IPasswordHasher passwordHasher,
IInvitesRepository invitesRepository,
IAdminsRepository adminsRepository)
IAdminsRepository adminsRepository
)
{
_usersRepository = usersRepository;
_jwtService = jwtService;
_passwordHasher = passwordHasher;
_invitesRepository = invitesRepository;
_adminsRepository = adminsRepository;
}
public async Task<string> RegistrationAsync(string name, string password, string inviteCode)
public async Task<string> RegistrationAsync(string name, string password, Invitation invitation)
{
// 1. Проверка существования имени
if (await _usersRepository.ExistsUsernameAsync(name))
throw new UserAlreadyExistException(name);
// 2. Проверка валидности инвайта
var invite = await _invitesRepository.FindByCodeAsync(inviteCode);
// 3. Генерация пароля
var passwordHash = _passwordHasher.Hash(password);
// 4. Создание пользователя
var user = new User
{
Id = Guid.NewGuid(),
@@ -53,22 +46,13 @@ public class AuthService : IAccountService
CreatedOn = DateOnly.FromDateTime(DateTime.UtcNow),
IconId = Guid.NewGuid(),
WasOnline = DateTime.UtcNow,
InviteId = invite.Id
InviteId = invitation.Id
};
// 5. Добавление пользователя
await _usersRepository.AddAsync(user);
// 6. Назначение роли, если инвайт — админский
if (invite.IsAdmin)
{
await _adminsRepository.AddAsync(new Admin
{
UserId = user.Id
});
}
// 7. Генерация токена
SetRole(user, invitation);
return _jwtService.GenerateJwtToken(user);
}
@@ -85,6 +69,12 @@ public class AuthService : IAccountService
return _jwtService.GenerateJwtToken(user);
}
private async void SetRole(User user, Invitation invitation)
{
if(invitation.IsAdmin)
await _adminsRepository.AddAsync(new Admin() { UserId = user.Id });
}
}
public class LoginUserException : GovorCoreException { }
@@ -4,6 +4,6 @@ namespace Govor.API.Services.Authentication.Interfaces;
public interface IAccountService
{
public Task<string> RegistrationAsync(string name, string password, string inviteCode);
public Task<string> RegistrationAsync(string name, string password, Invitation invitation);
public Task<string> LoginAsync(string name, string password);
}
@@ -0,0 +1,9 @@
using Govor.Core.Models;
namespace Govor.API.Services.Authentication.Interfaces;
public interface IInvitesService
{
public Task<string> GetRole(User user);
public Invitation Validate(string inviteCode);
}
@@ -0,0 +1,52 @@
using Govor.API.Services.Authentication.Interfaces;
using Govor.Core;
using Govor.Core.Models;
using Govor.Core.Repositories.Invaites;
using Govor.Data.Repositories.Exceptions;
namespace Govor.API.Services.Authentication;
public class InvitesService : IInvitesService
{
private readonly IInvitesRepository _invitesRepository;
public InvitesService(IInvitesRepository invitesRepository)
{
_invitesRepository = invitesRepository;
}
public async Task<string> GetRole(User user)
{
try
{
var invitation = await _invitesRepository.FindByIdAsync(user.InviteId);
return invitation.IsAdmin ? "Admin" : "User";
}
catch (NotFoundByKeyException<Guid>)
{
return "User";
}
}
public Invitation Validate(string inviteCode)
{
var invite = _invitesRepository.FindByCodeAsync(inviteCode).Result;
if (invite.EndDate < DateTime.Now ||
invite.MaxParticipants <= invite.Users.Count)
{
invite.IsActive = false;
_invitesRepository.UpdateAsync(invite);
throw new InviteLinkInvalidException(inviteCode);
}
return invite;
}
public string GenerateInvitationLink(Invitation invitation)
{
throw new NotImplementedException();
}
}
public class InviteLinkInvalidException(string inviteCode) : GovorCoreException($"Invite link invalid: {inviteCode}");
@@ -13,21 +13,20 @@ namespace Govor.API.Services.Authentication;
public class JwtService : IJwtService
{
private JwtOption _jwtOption;
private IInvitesRepository _invitesRepository;
private IInvitesService _invitesService;
public JwtService(IOptions<JwtOption> options)
public JwtService(IOptions<JwtOption> options, IInvitesService invitesService)
{
_jwtOption = options.Value;
_invitesService = invitesService;
}
public string GenerateJwtToken(User user)
{
var invite = _invitesRepository.FindByIdAsync(user.InviteId).Result;
var claims = new[]
{
new Claim("userID", user.Id.ToString()),
new Claim(ClaimTypes.Role, invite.IsAdmin ? "Admin" : "User", ClaimValueTypes.String)
new Claim(ClaimTypes.Role, _invitesService.GetRole(user).Result, ClaimValueTypes.String)
};
var singing = new SigningCredentials(