|
|
|
@@ -0,0 +1,787 @@ |
|
|
|
using AutoMapper; |
|
|
|
using Diligent.WebAPI.Business.MappingProfiles; |
|
|
|
using Diligent.WebAPI.Business.Services; |
|
|
|
using Diligent.WebAPI.Business.Settings; |
|
|
|
using Diligent.WebAPI.Contracts.DTOs; |
|
|
|
using Diligent.WebAPI.Contracts.DTOs.Auth; |
|
|
|
using Diligent.WebAPI.Contracts.Models; |
|
|
|
using Diligent.WebAPI.Data.Entities; |
|
|
|
using Microsoft.AspNetCore.Identity; |
|
|
|
using Microsoft.AspNetCore.WebUtilities; |
|
|
|
using Microsoft.EntityFrameworkCore; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
using Microsoft.Extensions.Options; |
|
|
|
using NSubstitute.ReturnsExtensions; |
|
|
|
using System.Text; |
|
|
|
|
|
|
|
namespace Diligent.WebAPI.Tests.Services |
|
|
|
{ |
|
|
|
public class AuthenticationServiceTests |
|
|
|
{ |
|
|
|
private readonly List<User> _users; |
|
|
|
private readonly List<RefreshToken> _tokens; |
|
|
|
private readonly IUserStore<User> _mockStore; |
|
|
|
private readonly UserManager<User> _mockUserManager; |
|
|
|
private readonly IEmailer _emailer = Substitute.For<IEmailer>(); |
|
|
|
private readonly IMapper _mapper; |
|
|
|
private readonly ILogger<AuthenticationService> _logger = Substitute.For<ILogger<AuthenticationService>>(); |
|
|
|
private readonly IHttpClientService _httpClient = Substitute.For<IHttpClientService>(); |
|
|
|
|
|
|
|
public AuthenticationServiceTests() |
|
|
|
{ |
|
|
|
_mockStore = Substitute.For<IUserStore<User>>(); |
|
|
|
_mockUserManager = Substitute.For<UserManager<User>>(_mockStore, null, null, null, null, null, null, null, null); |
|
|
|
_tokens = new List<RefreshToken> |
|
|
|
{ |
|
|
|
new RefreshToken |
|
|
|
{ |
|
|
|
Id = 1, |
|
|
|
CreationDate = DateTime.UtcNow, |
|
|
|
ExpiryDate = DateTime.UtcNow.AddDays(5), |
|
|
|
UserId = 1, |
|
|
|
Invalidated = false, |
|
|
|
JwtId = "string", |
|
|
|
Used = false, |
|
|
|
Token = "refresh" |
|
|
|
}, |
|
|
|
new RefreshToken |
|
|
|
{ |
|
|
|
Id = 2, |
|
|
|
CreationDate = DateTime.UtcNow, |
|
|
|
ExpiryDate = DateTime.UtcNow.AddDays(5), |
|
|
|
UserId = 2, |
|
|
|
Invalidated = false, |
|
|
|
JwtId = "string", |
|
|
|
Used = false, |
|
|
|
Token = "refresh" |
|
|
|
}, |
|
|
|
new RefreshToken |
|
|
|
{ |
|
|
|
Id = 3, |
|
|
|
CreationDate = DateTime.UtcNow, |
|
|
|
ExpiryDate = DateTime.UtcNow.AddDays(5), |
|
|
|
UserId = 3, |
|
|
|
Invalidated = false, |
|
|
|
JwtId = "string", |
|
|
|
Used = false, |
|
|
|
Token = "refresh" |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
_users = new List<User> |
|
|
|
{ |
|
|
|
new User |
|
|
|
{ |
|
|
|
Id = 1, |
|
|
|
PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==", |
|
|
|
FirstName = "User", |
|
|
|
LastName = "One", |
|
|
|
UserName = "user1", |
|
|
|
NormalizedUserName = "USER1", |
|
|
|
Email = "user1@dilig.net", |
|
|
|
NormalizedEmail = "USER1@DILIG.NET", |
|
|
|
EmailConfirmed = false, |
|
|
|
IsEnabled = true, |
|
|
|
AccessFailedCount = 0, |
|
|
|
SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
}, |
|
|
|
new User |
|
|
|
{ |
|
|
|
Id = 2, |
|
|
|
PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==", |
|
|
|
FirstName = "User", |
|
|
|
LastName = "Two", |
|
|
|
UserName = "user2", |
|
|
|
NormalizedUserName = "USER2", |
|
|
|
Email = "user2@dilig.net", |
|
|
|
NormalizedEmail = "USER2@DILIG.NET", |
|
|
|
EmailConfirmed = false, |
|
|
|
IsEnabled = true, |
|
|
|
AccessFailedCount = 0, |
|
|
|
SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
}, |
|
|
|
new User |
|
|
|
{ |
|
|
|
Id = 3, |
|
|
|
PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==", |
|
|
|
FirstName = "User", |
|
|
|
LastName = "Three", |
|
|
|
UserName = "user3", |
|
|
|
NormalizedUserName = "USER3", |
|
|
|
Email = "user3@dilig.net", |
|
|
|
NormalizedEmail = "USER3@DILIG.NET", |
|
|
|
EmailConfirmed = false, |
|
|
|
IsEnabled = false, |
|
|
|
AccessFailedCount = 0, |
|
|
|
SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
}, |
|
|
|
new User |
|
|
|
{ |
|
|
|
Id = 4, |
|
|
|
PasswordHash = "AQAAAAEAACcQAAAAEJnWVhD/qftzqJq5XOUD0BxEBEwhd7vS46HeDD+9cwEsqO9ev9xEORJVjmFMASUGJg==", |
|
|
|
FirstName = "User", |
|
|
|
LastName = "Four", |
|
|
|
UserName = "user4", |
|
|
|
NormalizedUserName = "USER4", |
|
|
|
Email = "user4@dilig.net", |
|
|
|
NormalizedEmail = "USER4@DILIG.NET", |
|
|
|
EmailConfirmed = false, |
|
|
|
IsEnabled = true, |
|
|
|
AccessFailedCount = 0, |
|
|
|
SecurityStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
ConcurrencyStamp = "2D3XPK2P5MAKO377AWFU3T4ZFFYTSOJX", |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// configure mapper |
|
|
|
var configuration = new MapperConfiguration(cfg => cfg.AddProfiles( |
|
|
|
new List<Profile> |
|
|
|
{ |
|
|
|
new UserMappingProfile() |
|
|
|
})); |
|
|
|
|
|
|
|
_mapper = new Mapper(configuration); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Authenticate_ShouldReturnError_IfInvalidUsername() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByNameAsync(Arg.Any<string>()).ReturnsNull(); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto |
|
|
|
{ |
|
|
|
Username = "Any", |
|
|
|
Password = "Any" |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "Username is not valid" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Authenticate_ShouldCall_CheckPasswordAsync() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto |
|
|
|
{ |
|
|
|
Username = _users[1].Email, |
|
|
|
Password = "Any" |
|
|
|
}); |
|
|
|
|
|
|
|
await _mockUserManager.Received(1).CheckPasswordAsync(_users[1], "Any"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Authenticate_ShouldReturnError_IfUserIsDisabled() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[2]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto |
|
|
|
{ |
|
|
|
Username = _users[2].Email, |
|
|
|
Password = "Any" |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = $"User with email {_users[2].Email} has no permission to log in." |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Authenticate_ShouldReturnError_IfInvalidPassword() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto |
|
|
|
{ |
|
|
|
Username = _users[1].Email, |
|
|
|
Password = "Any" |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = $"Password is not correct" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Authenticate_ShouldReturnError_IfUserIsLockedOut() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[3]); |
|
|
|
_mockUserManager.CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(true); |
|
|
|
_mockUserManager.IsLockedOutAsync(Arg.Any<User>()).Returns(true); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { |
|
|
|
Secret = "S1231251WAS124AS" |
|
|
|
}); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto |
|
|
|
{ |
|
|
|
Username = _users[3].Email, |
|
|
|
Password = "Nekasifra123!" |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "The account is locked out" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Authenticate_ShouldGenerateToken_IfCredsAreValid() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByNameAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new Contracts.DTOs.Auth.AuthenticateRequestDto |
|
|
|
{ |
|
|
|
Username = _users[1].Email, |
|
|
|
Password = "Nekasifra123!" |
|
|
|
}); |
|
|
|
|
|
|
|
Assert.IsType<ServiceResponseDTO<AuthenticateResponseDto>>(result); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task AuthenticateGoogle_ShouldReturnError_IfInvalidApiToken() |
|
|
|
{ |
|
|
|
_httpClient.IsTokenValid(Arg.Any<string>()).Returns(false); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new GoogleApiModel |
|
|
|
{ |
|
|
|
Token = "t", |
|
|
|
User = new GoogleApiTokenInfo |
|
|
|
{ |
|
|
|
email = "something@dilig.net" |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "Invalid Google Api Token" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task AuthenticateGoogle_ShouldReturnError_IfUserDoesntExist() |
|
|
|
{ |
|
|
|
_httpClient.IsTokenValid(Arg.Any<string>()).Returns(true); |
|
|
|
_mockUserManager.FindByNameAsync(Arg.Any<string>()).ReturnsNull(); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new GoogleApiModel |
|
|
|
{ |
|
|
|
Token = "t", |
|
|
|
User = new GoogleApiTokenInfo |
|
|
|
{ |
|
|
|
email = _users[1].Email, |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = $"User with email {_users[1].Email} does not exist in database" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task AuthenticateGoogle_ShouldReturnError_IfUserIsDisabled() |
|
|
|
{ |
|
|
|
_httpClient.IsTokenValid(Arg.Any<string>()).Returns(true); |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[2]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new GoogleApiModel |
|
|
|
{ |
|
|
|
Token = "token", |
|
|
|
User = new GoogleApiTokenInfo |
|
|
|
{ |
|
|
|
email = _users[2].Email, |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = $"User with email {_users[2].Email} has no permission to log in." |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task AuthenticateGoogle_ShouldGenerateToken() |
|
|
|
{ |
|
|
|
_httpClient.IsTokenValid(Arg.Any<string>()).Returns(true); |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings |
|
|
|
{ |
|
|
|
Secret = "S1231251WAS124AS" |
|
|
|
}); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Authenticate(new GoogleApiModel |
|
|
|
{ |
|
|
|
Token = "token", |
|
|
|
User = new GoogleApiTokenInfo |
|
|
|
{ |
|
|
|
email = _users[1].Email |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
Assert.IsType<ServiceResponseDTO<AuthenticateResponseDto>>(result); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Register_ShouldReturnError_IfUserNotFound() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).ReturnsNull(); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.Register(new Contracts.DTOs.User.RegisterDTO |
|
|
|
{ |
|
|
|
Token = "token", |
|
|
|
LinkedIn = "Link", |
|
|
|
Confirm = "Password123!", |
|
|
|
Email = _users[1].Email, |
|
|
|
Password = "Password123!", |
|
|
|
Phone = "123", |
|
|
|
Position = "Senior Dev" |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<AuthenticateResponseDto> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "User not invited." |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Register_ShouldCreateUser_IfUserExists() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
|
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
_mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>()).Returns(IdentityResult.Success); |
|
|
|
|
|
|
|
var result = await service.Register(new Contracts.DTOs.User.RegisterDTO |
|
|
|
{ |
|
|
|
Token = "token", |
|
|
|
LinkedIn = "Link", |
|
|
|
Confirm = "Password123!", |
|
|
|
Email = _users[1].Email, |
|
|
|
Password = "Password123!", |
|
|
|
Phone = "123", |
|
|
|
Position = "Senior Dev" |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<object> |
|
|
|
{ |
|
|
|
Data = true, |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Register_ShouldThrowError_IfUnsuccessfulReset() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
|
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
_mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>()) |
|
|
|
.Returns(IdentityResult.Failed( |
|
|
|
new IdentityError[] { |
|
|
|
new IdentityError { |
|
|
|
Description= "Failed" |
|
|
|
} |
|
|
|
} |
|
|
|
)); |
|
|
|
|
|
|
|
var result = await service.Register(new Contracts.DTOs.User.RegisterDTO |
|
|
|
{ |
|
|
|
Token = "token", |
|
|
|
LinkedIn = "Link", |
|
|
|
Confirm = "Password123!", |
|
|
|
Email = _users[1].Email, |
|
|
|
Password = "Password123!", |
|
|
|
Phone = "123", |
|
|
|
Position = "Senior Dev" |
|
|
|
}); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<object> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "Failed" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task PasswordResetAsync_ShouldReturnError_IfUserNotFound() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).ReturnsNull(); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.PasswordResetAsync( |
|
|
|
email: _users[1].Email, |
|
|
|
code: "code", |
|
|
|
password: "Password123!" |
|
|
|
); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<object> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "Email did not find." |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task PasswordResetAsync_ShouldResetToken_IfUserFound() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
_mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>()) |
|
|
|
.Returns(IdentityResult.Success); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.PasswordResetAsync( |
|
|
|
email: _users[1].Email, |
|
|
|
code: "code", |
|
|
|
password: "Password123!" |
|
|
|
); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<object> |
|
|
|
{ Data = true } |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task PasswordResetAsync_ShouldReturnError_IfUnsuccessfulReset() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
_mockUserManager.ResetPasswordAsync(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<string>()) |
|
|
|
.Returns(IdentityResult.Failed( |
|
|
|
new IdentityError[] { |
|
|
|
new IdentityError { |
|
|
|
Description= "Failed" |
|
|
|
} |
|
|
|
} |
|
|
|
)); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.PasswordResetAsync( |
|
|
|
email: _users[1].Email, |
|
|
|
code: "code", |
|
|
|
password: "Password123!" |
|
|
|
); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<object> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "Failed" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task GetForgotPasswordUrlAsync_ShouldReturnError_IfUserNotFound() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).ReturnsNull(); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.GetForgotPasswordUrlAsync(_users[1].Email); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<object> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "Email did not find." |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task GetForgotPasswordUrlAsync_ShouldReturnSuccess_IfUserIsFound() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
await service.GetForgotPasswordUrlAsync(_users[1].Email); |
|
|
|
|
|
|
|
await _emailer.ReceivedWithAnyArgs(1) |
|
|
|
.SendEmailAndWriteToDbAsync("mail", "reset", "url", true); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task GetForgotPasswordUrlAsync_ShouldCallEmailer_IfUserIsFound() |
|
|
|
{ |
|
|
|
_mockUserManager.FindByEmailAsync(Arg.Any<string>()).Returns(_users[1]); |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContext(_users); |
|
|
|
|
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.GetForgotPasswordUrlAsync(_users[1].Email); |
|
|
|
|
|
|
|
result.Should().BeOfType(typeof(ServiceResponseDTO<object>)); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task UpdateRefreshToken_ShouldUpdate() |
|
|
|
{ |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens); |
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var first = await databaseContext.RefreshTokens.FindAsync(1); |
|
|
|
|
|
|
|
await service.UpdateRefreshToken(first); |
|
|
|
databaseContext.Entry(first).Should().NotBeNull(); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task DeleteRefreshToken_ShouldReturnError_IfTokenDoesNotExist() |
|
|
|
{ |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.DeleteRefreshToken(1000); // not existing token |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<string> |
|
|
|
{ |
|
|
|
IsError = true, |
|
|
|
ErrorMessage = "There is no refresh token for user" |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task DeleteRefreshToken_ShouldSucceed_IfTokenExists() |
|
|
|
{ |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.DeleteRefreshToken(1); // not existing token |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(new ServiceResponseDTO<string> |
|
|
|
{ |
|
|
|
Data = null |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task GetRefreshTokenByUserId_ShouldReturnTokenOrNull() |
|
|
|
{ |
|
|
|
var databaseContext = await Helpers<User>.GetDatabaseContextWithRelation(_users, _tokens); |
|
|
|
|
|
|
|
var authSettings = Options.Create(new AuthorizationSettings { }); |
|
|
|
var frontEndSettings = Options.Create(new FrontEndSettings |
|
|
|
{ |
|
|
|
BaseUrl = "some url" |
|
|
|
}); |
|
|
|
|
|
|
|
var service = new AuthenticationService(authSettings, frontEndSettings, _mockUserManager, databaseContext, _emailer, _logger, _httpClient, _mapper); |
|
|
|
|
|
|
|
var result = await service.GetRefreshTokenByUserId(1); |
|
|
|
|
|
|
|
result.Should().BeEquivalentTo(_tokens[0]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |