-
Notifications
You must be signed in to change notification settings - Fork 0
/
AuthService.cs
115 lines (94 loc) · 5.09 KB
/
AuthService.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using AMOGUS.Core.Centralization.User;
using AMOGUS.Core.Common.Communication;
using AMOGUS.Core.Common.Exceptions;
using AMOGUS.Core.Common.Interfaces.Database;
using AMOGUS.Core.Common.Interfaces.Repositories;
using AMOGUS.Core.Common.Interfaces.Security;
using AMOGUS.Core.Common.Interfaces.User;
using AMOGUS.Core.DataTransferObjects.User;
using AMOGUS.Core.Domain.Models.Entities;
using AMOGUS.Infrastructure.Identity;
using FluentValidation;
using Microsoft.AspNetCore.Identity;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Claims;
[assembly: InternalsVisibleTo("AMOGUS.UnitTests")]
namespace AMOGUS.Infrastructure.Services.User {
internal class AuthService : IAuthService {
private readonly ITokenFactory _tokenFactory;
private readonly IRoleManager _roleManager;
private readonly IUserManager _userManager;
private readonly IUserStatsRepository _userStatsRepository;
private readonly IValidator<RegisterApiModel> _registerValidator;
public AuthService(IRoleManager _roleManager, IUserManager _userManager, ITokenFactory _tokenFactory, IUserStatsRepository userStatsRepository, IValidator<RegisterApiModel> registerValidator) {
this._roleManager = _roleManager!;
this._userManager = _userManager!;
this._tokenFactory = _tokenFactory!;
_userStatsRepository = userStatsRepository!;
_registerValidator = registerValidator!;
}
public async Task CreateRolesAsync<TRoles>() {
var roles = typeof(TRoles).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(f => f.IsLiteral && !f.IsInitOnly && (f.FieldType == typeof(string) || f.FieldType == typeof(String)) && f.GetRawConstantValue() != null)
.Select(x => (string) (x.GetRawConstantValue() ?? ""))
.ToList();
foreach (string r in roles) {
if (!(await _roleManager.RoleExistsAsync(r))) {
await _roleManager.CreateAsync(new IdentityRole(r));
}
}
}
public async Task<Result<LoginResultApiModel>> LoginUserAsync(LoginApiModel loginModel) {
var user = await _userManager.FindByEmailAsync(loginModel.Email);
if (user == null || !await _userManager.CheckPasswordAsync(user, loginModel.Password)) {
return new AuthFailureException("Invalid Username or Password!");
}
var userRoles = await _userManager.GetRolesAsync(user);
List<Claim> authClaims = _tokenFactory.GetUserAuthClaimsFromRoles(userRoles, user);
JwtSecurityToken token = _tokenFactory.GenerateNewJwtSecurityToken(authClaims);
return new LoginResultApiModel(new JwtSecurityTokenHandler().WriteToken(token), token.ValidTo, user.UserName, user.Email);
}
public async Task<Result<LoginResultApiModel>> RegisterUserAsync(RegisterApiModel registerModel, string role) {
var validRes = _registerValidator.Validate(registerModel);
if (!validRes.IsValid) {
return new ValidationException(validRes.Errors);
}
var userExists = await _userManager.FindByEmailAsync(registerModel.Email);
if (userExists != null) {
return new AuthFailureException("Account already exists!");
}
ApplicationUser user = CreateNewApplicationUserModel(registerModel);
var result = await _userManager.CreateAsync(user, registerModel.Password);
if (!result.Succeeded)
return new AuthFailureException($"Failed to create Account \n{String.Join("\n", result.Errors)}");
if (!await _roleManager.RoleExistsAsync(role)) {
return new AuthFailureException($"Failed to create Account with role {role}");
}
await _userManager.AddToRoleAsync(user, UserRoles.User);
if (!UserRoles.User.Equals(role)) {
await _userManager.AddToRoleAsync(user, role);
}
var res = await CreateNewUserStatsAsync(user);
if (res.IsFaulted)
return new Exception("Did not finish creating the user", res);
return await LoginUserAsync(new LoginApiModel { Email = registerModel.Email, Password = registerModel.Password });
}
private static ApplicationUser CreateNewApplicationUserModel(RegisterApiModel registerModel) {
return new() {
Email = registerModel.Email,
UserName = registerModel.UserName,
SecurityStamp = Guid.NewGuid().ToString()
};
}
private async Task<Result<UserStats>> CreateNewUserStatsAsync(ApplicationUser user) {
var stats = new UserStats {
User = user,
UserId = user.Id
};
var res = await _userStatsRepository.AddUserStatsAsync(stats);
return res > 0 ? stats : new UserOperationException("Could not create stats object");
}
}
}