You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

216 lines
7.1 KiB

  1. using Domain.Identity;
  2. using Infrastructure;
  3. using Microsoft.EntityFrameworkCore;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Models.Identity;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Threading.Tasks;
  10. namespace Services.Identity
  11. {
  12. public class AuthService : BaseService<Account>, IAuthService
  13. {
  14. private readonly ITokenIssuer _tokenIssuer;
  15. public AuthService(IServiceProvider serviceProvider) : base(serviceProvider)
  16. {
  17. _tokenIssuer = serviceProvider.GetService<ITokenIssuer>();
  18. }
  19. public async Task<Account> GetByLoginToken(string username, string token)
  20. {
  21. var now = DateTime.Now;
  22. var loginToken = await _db.LoginTokens
  23. .Where(x => !x.Used && x.ExpireationDate > now)
  24. .Where(x => x.Token.ToLower() == token.ToLower())
  25. .Where(x => x.Account.Username.ToLower() == username.ToLower())
  26. .Include(x => x.Account).FirstOrDefaultAsync();
  27. if (loginToken is null) return null;
  28. var account = loginToken.Account;
  29. return account;
  30. }
  31. public async Task<(Account account, RefreshToken refreshToken)> GetByRefreshToken(string token)
  32. {
  33. var refreshToken = await _db.RefreshTokens
  34. .Include(x => x.LoginToken).ThenInclude(x => x.Account)
  35. .FirstOrDefaultAsync(x => x.Token.ToLower().Trim() == token.Trim().ToLower());
  36. if (refreshToken is null) return (null, null);
  37. return (refreshToken.LoginToken.Account, refreshToken);
  38. }
  39. public Account GetByUsername(string username)
  40. {
  41. return GetQueryable().FirstOrDefault(x => x.Username.ToLower().Trim() == username.ToLower().Trim());
  42. }
  43. public async Task<Account> GetByUsernameAndPassword(string username, string password)
  44. {
  45. return GetQueryable().
  46. Where(x => x.Username.Equals(username) && x.Password.Equals(password)).Include(x => x.AccountRoles).FirstOrDefault();
  47. }
  48. public async Task<LoginToken> GenerateLoginToken(Account account)
  49. {
  50. var now = DateTime.Now;
  51. var token = _db.LoginTokens.FirstOrDefault(x => x.AccountId == account.Id && !x.Used && x.ExpireationDate > now);
  52. if (token == null)
  53. {
  54. var code = RandomGenerator.GetRandomString(4);
  55. token = new LoginToken
  56. {
  57. AccountId = account.Id,
  58. ExpireationDate = DateTime.Now.AddMinutes(2),
  59. Token = code
  60. };
  61. await _db.LoginTokens.AddAsync(token);
  62. SaveChanges();
  63. }
  64. return token;
  65. }
  66. public async Task<RefreshToken> GenerateRefreshToken(LoginToken loginToken)
  67. {
  68. if (loginToken.Used) return null;
  69. var refreshToken = loginToken.RefreshToken ?? new RefreshToken();
  70. loginToken.Used = true;
  71. refreshToken.Token = Guid.NewGuid().ToString();
  72. refreshToken.LoginTokenId = loginToken.Id;
  73. if (loginToken.RefreshToken is null)
  74. {
  75. await _db.RefreshTokens.AddAsync(refreshToken);
  76. SaveChanges();
  77. }
  78. else
  79. {
  80. SaveChanges();
  81. }
  82. return refreshToken;
  83. }
  84. public async Task<PlainToken> GeneratePlainToken(Guid id, string loginToken)
  85. {
  86. var account =GetById(id);
  87. if (account is null) return null;
  88. var token = await _db.LoginTokens
  89. .Where(x => x.AccountId == id)
  90. .Include(x => x.Account)
  91. .ThenInclude(x => x.AccountRoles)
  92. .ThenInclude(x => x.Role)
  93. .Include(x => x.RefreshToken)
  94. .FirstOrDefaultAsync(x => x.Token == loginToken);
  95. if (token is null) return null;
  96. var refreshToken = await GenerateRefreshToken(token);
  97. var plainToken = _tokenIssuer.IssuePlainToken(account);
  98. return plainToken;
  99. }
  100. public async Task<PlainToken> GeneratePlainToken(Account account, string loginToken)
  101. {
  102. var token = await _db.LoginTokens
  103. .Where(x => x.AccountId == account.Id)
  104. .Where(x => x.Token == loginToken)
  105. .Include(x => x.Account)
  106. .ThenInclude(x => x.AccountRoles)
  107. .ThenInclude(x => x.Role)
  108. .Include(x => x.RefreshToken)
  109. .FirstOrDefaultAsync();
  110. if (token is null) return null;
  111. var refreshToken = await GenerateRefreshToken(token);
  112. if (refreshToken is null) return null;
  113. var plainToken = _tokenIssuer.IssuePlainToken(account);
  114. return plainToken;
  115. }
  116. public async Task<PlainToken> RefreshToken(string token)
  117. {
  118. var refreshToken = await _db.RefreshTokens
  119. .Where(x => x.Token == token)
  120. .Include(x => x.LoginToken)
  121. .ThenInclude(x => x.Account)
  122. .ThenInclude(x => x.AccountRoles)
  123. .ThenInclude(x => x.Role)
  124. .FirstOrDefaultAsync();
  125. if (refreshToken is null || !refreshToken.LoginToken.Used) return null;
  126. refreshToken.Token = Guid.NewGuid().ToString();
  127. SaveChanges();
  128. var plainToken = _tokenIssuer.IssuePlainToken(refreshToken.LoginToken.Account);
  129. return plainToken;
  130. }
  131. public void SetDeveloperUser()
  132. {
  133. string[] developers = { "09169212241", "09161151186" };
  134. var users = GetQueryable().Where(x => developers.Contains(x.Username)).ToList();
  135. foreach (var user in users)
  136. {
  137. var role = _db.Roles.FirstOrDefault(x => x.Name == Consts.Developer);
  138. if (role != null)
  139. {
  140. var accountRole = _db.AccountRoles.FirstOrDefault(x => x.RoleId == role.Id && x.AccountId == user.Id);
  141. if (accountRole == null)
  142. _db.AccountRoles.Add(new AccountRole
  143. {
  144. AccountId = user.Id,
  145. RoleId = role.Id
  146. });
  147. SaveChanges();
  148. }
  149. }
  150. }
  151. }
  152. public interface IAuthService : IBaseService<Account>
  153. {
  154. Account GetByUsername(string username);
  155. Task<Account> GetByUsernameAndPassword(string username, string password);
  156. Task<Account> GetByLoginToken(string username, string token);
  157. Task<LoginToken> GenerateLoginToken(Account account);
  158. Task<RefreshToken> GenerateRefreshToken(LoginToken loginToken);
  159. Task<(Account account, RefreshToken refreshToken)> GetByRefreshToken(string token);
  160. Task<PlainToken> GeneratePlainToken(Account account, string token);
  161. Task<PlainToken> RefreshToken(string token);
  162. void SetDeveloperUser();
  163. }
  164. }