Skip to content

Commit 97a6747

Browse files
author
TL\anwarahm
committed
Seperate Table created for RefreshToken and RefreshTokenCommandHandlerTest created for unit test and all appSettings updated
1 parent 7e1f5c4 commit 97a6747

16 files changed

+1050
-25
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations.Schema;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace CleanTemplate.Domain.Entities.Users
9+
{
10+
public class RefreshToken : IEntity<int>
11+
{
12+
public int Id { get; set; }
13+
14+
[ForeignKey(name: nameof(User))]
15+
public int UserId { get; set; }
16+
public User User { get; set; }
17+
public string Token { get; set; }
18+
public DateTime Created { get; set; }
19+
public DateTime Updated { get; set; } = DateTime.Now;
20+
public DateTime ExpiryTime { get; set; }
21+
}
22+
}

src/Core/Domain/Entities/Users/User.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ public User()
2121
public bool IsActive { get; set; }
2222

2323
public DateTimeOffset? LastLoginDate { get; set; }
24-
public string? RefreshToken { get; set; }
25-
public DateTime? RefreshTokenExpiryTime { get; set; }
2624
}
2725

2826
public enum GenderType
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using CleanTemplate.Domain.Entities.Users;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace CleanTemplate.Domain.IRepositories
10+
{
11+
public interface IRefreshTokenRepository : IRepository<RefreshToken>
12+
{
13+
Task UpsertRefreshToken(RefreshToken refreshToken, CancellationToken cancellationToken);
14+
Task<bool> ValidateRefreshToken(RefreshToken refreshToken, CancellationToken cancellationToken);
15+
}
16+
}

src/Infrastructure/Persistance/CommandHandlers/Users/LoginCommandHandler.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using CleanTemplate.Common;
33
using CleanTemplate.Common.Exceptions;
44
using CleanTemplate.Domain.Entities.Users;
5+
using CleanTemplate.Domain.IRepositories;
56
using CleanTemplate.Persistance.Jwt;
67
using MediatR;
78
using Microsoft.AspNetCore.Identity;
@@ -15,12 +16,15 @@ public class LoginCommandHandler : IRequestHandler<LoginCommand, LoginResponse>
1516
{
1617
private readonly UserManager<User> _userManager;
1718
private readonly IJwtService _jwtService;
19+
private readonly IRefreshTokenRepository _refreshTokenRepository;
1820

1921
public LoginCommandHandler(UserManager<User> userManager,
20-
IJwtService jwtService)
22+
IJwtService jwtService,
23+
IRefreshTokenRepository refreshTokenRepository)
2124
{
2225
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
2326
_jwtService = jwtService ?? throw new ArgumentNullException(nameof(jwtService));
27+
_refreshTokenRepository = refreshTokenRepository ?? throw new ArgumentNullException(nameof(refreshTokenRepository));
2428
}
2529

2630
public async Task<LoginResponse> Handle(LoginCommand request, CancellationToken cancellationToken)
@@ -37,9 +41,13 @@ public async Task<LoginResponse> Handle(LoginCommand request, CancellationToken
3741
throw new CleanArchAppException("username or password is incorrect");
3842

3943
var jwt = await _jwtService.GenerateAsync(user);
40-
user.RefreshToken = jwt.refresh_token;
41-
user.RefreshTokenExpiryTime = DateTime.Now.AddDays(jwt.refreshToken_expiresIn);
42-
await _userManager.UpdateAsync(user);
44+
var refreshToken = new RefreshToken
45+
{
46+
UserId = user.Id,
47+
ExpiryTime = DateTime.Now.AddDays(jwt.refreshToken_expiresIn),
48+
Token = jwt.refresh_token
49+
};
50+
await _refreshTokenRepository.UpsertRefreshToken(refreshToken: refreshToken, cancellationToken);
4351
return new LoginResponse
4452
{
4553
accessToken = jwt.access_token,

src/Infrastructure/Persistance/CommandHandlers/Users/RefreshTokenCommandHandler.cs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CleanTemplate.Application.Users.Command.RefreshToken;
22
using CleanTemplate.Common;
3+
using CleanTemplate.Common.Exceptions;
34
using CleanTemplate.Domain.Entities.Users;
45
using CleanTemplate.Domain.IRepositories;
56
using CleanTemplate.Persistance.Jwt;
@@ -18,29 +19,43 @@ namespace CleanTemplate.Persistance.CommandHandlers.Users
1819
{
1920
public class RefreshTokenCommandHandler : IRequestHandler<RefreshTokenCommand, RefreshTokenResponse>
2021
{
21-
private readonly IUserRepository _userRepository;
22+
private readonly UserManager<User> _userManager;
2223
private readonly IJwtService _jwtService;
24+
private readonly IRefreshTokenRepository _refreshTokenRepository;
2325

24-
public RefreshTokenCommandHandler(IUserRepository userRepository,
25-
IJwtService jwtService)
26+
public RefreshTokenCommandHandler(UserManager<User> userManager,
27+
IJwtService jwtService,
28+
IRefreshTokenRepository refreshTokenRepository)
2629
{
27-
_userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
30+
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
2831
_jwtService = jwtService ?? throw new ArgumentNullException(nameof(jwtService));
32+
_refreshTokenRepository = refreshTokenRepository ?? throw new ArgumentNullException(nameof(refreshTokenRepository));
2933
}
3034
public async Task<RefreshTokenResponse> Handle(RefreshTokenCommand request, CancellationToken cancellationToken)
3135
{
36+
if (request is null)
37+
throw new InvalidNullInputException(nameof(request));
38+
3239
var userId = _jwtService.ValidateJwtAccessTokenAsync(request.AccessToken);
3340
if (userId == null)
3441
throw new CleanArchAppException("AccessToken is not valid");
3542

36-
var user = await _userRepository.GetByIdAsync(cancellationToken, userId);
37-
if (user.RefreshToken != request.RefreshToken)
38-
throw new CleanArchAppException("RefreshToken is not valid");
43+
var refreshToken = new RefreshToken
44+
{
45+
UserId = userId.Value,
46+
Token = request.RefreshToken
47+
};
48+
await _refreshTokenRepository.ValidateRefreshToken(refreshToken, cancellationToken);
3949

50+
var user = await _userManager.FindByIdAsync(userId.ToString());
4051
var jwt = await _jwtService.GenerateAsync(user);
41-
user.RefreshToken = jwt.refresh_token;
42-
user.RefreshTokenExpiryTime = DateTime.Now.AddDays(jwt.refreshToken_expiresIn);
43-
await _userRepository.UpdateAsync(user, cancellationToken);
52+
var updateRefreshToken = new RefreshToken
53+
{
54+
UserId = user.Id,
55+
ExpiryTime = DateTime.Now.AddDays(jwt.refreshToken_expiresIn),
56+
Token = jwt.refresh_token
57+
};
58+
await _refreshTokenRepository.UpsertRefreshToken(refreshToken: updateRefreshToken, cancellationToken);
4459
return new RefreshTokenResponse
4560
{
4661
AccessToken = jwt.access_token,

0 commit comments

Comments
 (0)