Skip to content

Commit

Permalink
FEAT: Adding new logic to store user attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
fmattioli committed Jul 14, 2024
1 parent a56f5c8 commit e5abcc9
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
"AuthSettings": {
"Realms": [
{
"Name": "",
"Audience": "",
"Issuer": ""
"Name": "smartconsig",
"Audience": "smartconsig-api",
"Issuer": "https://services-keycloak.ul0sru.easypanel.host/realms/smartconsig"
}
],
"ClientId": "",
"Resource": "",
"AuthServerUrl": "",
"ClientSecret": "qSGxtu0CFOmZ6Yzr5ntPK2iXppmKeerS",
"ClientId": "smartconsig-api",
"Resource": "smartconsig-api",
"AuthServerUrl": "https://services-keycloak.ul0sru.easypanel.host",
"PolicyName": "TokenManager",
"Roles": [
"TokenManager"
Expand All @@ -19,6 +20,6 @@
"tokenmanager-write",
"tokenmanager-read"
]
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,29 @@ public class CreateUserCommandHandler(IUserRepository userRepository) : IRequest

public async Task<Result> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
AddTenantToRequest(request);
var accessTokenResult = await _userRepository.GetAccessTokenAsync(request.Tenant);
if (accessTokenResult.IsSuccess)
{
var user = request.AddUserRequest.ToDomain();
var(IsSuccessStatusCode, contentRequest) = await _userRepository.CreateNewUserAsync(user);

var (IsSuccessStatusCode, contentRequest) = await _userRepository.CreateNewUserAsync(request.Tenant, user);
if (IsSuccessStatusCode)
{
await SetUserPasswordAsync(user);
return Result.Success();
}

UserErrors.SetTechnicalMessage(contentRequest);
return Result.Failure(UserErrors.TokenGenerationError);
return Result.Failure(UserErrors.WrongPasswordDefinition);
}

return Result.Failure(UserErrors.InvalidUserNameOrPasswordError);
return Result.Failure(UserErrors.TokenGenerationError);
}

private static void AddTenantToRequest(CreateUserCommand request)
{
request.AddUserRequest.Attributes.Add("tenant", [request.Tenant]);
}

private async Task SetUserPasswordAsync(User user)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class LoginUserCommandHandler(IUserRepository userRepository) : IRequestH

public async Task<Result<TokenResponse>> Handle(LoginUserCommand request, CancellationToken cancellationToken)
{
var user = request.LoginUser.ToDomain(request.Tenant);
var user = request.LoginUser.ToDomain();
var tokenDetailsResult = await _userRepository.LoginAsync(request.Tenant, user);
if (tokenDetailsResult.IsSuccess)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,10 @@ namespace TokenManager.Application.Services.Mappers
public static class UserMapper
{
public static User ToDomain(this AddUserRequest userRequest)
{
var attributes = userRequest.Attributes!.ToDomain();
return new User(userRequest.Username!, userRequest.Password, userRequest.Email!, userRequest.FirstName!, userRequest.LastName!, attributes);
{
return new User(userRequest.Username!, userRequest.Password, userRequest.Email!, userRequest.FirstName!, userRequest.LastName!, userRequest.Attributes);
}

public static Attributes ToDomain(this AttributesRequest attributes)
{
return new Attributes(attributes.Tenant, attributes.UserAttributes);
}

public static User ToDomain(this LoginUserRequest loginUserRequest)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

namespace TokenManager.Application.Services.Requests.User
{
public record AddUserRequest(string Username, string Password, string Email, string FirstName, string LastName, AttributesRequest? Attributes);
public record AddUserRequest(string Username, string Password, string Email, string FirstName, string LastName, Dictionary<string, string[]> Attributes);
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class User
public int NotBefore { get; set; }
public long CreatedTimestamp { get; set; }
public Access? Access { get; set; }
public Attributes? Attributes { get; set; }
public Dictionary<string, string[]>? Attributes { get; set; }

public User()
{
Expand All @@ -32,7 +32,7 @@ public User(string userName, string password)
Password = password;
}

public User(string userName, string password, string email, string firstName, string lastName, Attributes attributes)
public User(string userName, string password, string email, string firstName, string lastName, Dictionary<string, string[]> attributes)
{
Enabled = true;
EmailVerified = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public interface IUserRepository
{
Task<Result<TokenDetails>> GetAccessTokenAsync(string tenant);
Task<Result<TokenDetails>> LoginAsync(string tenant, User user);
Task<(bool result, string content)> CreateNewUserAsync(User user);
Task<(bool result, string content)> CreateNewUserAsync(string tenant, User user);
Task<Result<User>> GetUserAsync(string userName);
Task<Result> ResetPasswordAsync(string userId, string password);
Task<Result> SendEmailVerificationAsync(string userId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Contracts.Common;
using Feijuca.Keycloak.MultiTenancy.Services;
using Flurl;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
Expand Down Expand Up @@ -63,9 +62,9 @@ public async Task<Result<TokenDetails>> GetAccessTokenAsync(string tenant)
return Result<TokenDetails>.Failure(UserErrors.TokenGenerationError);
}

public async Task<(bool result, string content)> CreateNewUserAsync(User user)
public async Task<(bool result, string content)> CreateNewUserAsync(string tenant, User user)
{
SetBaseUrlUserAction(user!.Attributes!.Tenant!);
SetBaseUrlUserAction(tenant);

var json = JsonConvert.SerializeObject(user, Settings);
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public async Task HandleWhenInformAValidUser_ShouldCreateANewUserAndReturnsTrue(
(bool result, string content) createUserResult = (true, "Success message");

_userRepositoryMock
.Setup(x => x.CreateNewUserAsync(It.IsAny<User>()))
.Setup(x => x.CreateNewUserAsync(It.IsAny<string>(), It.IsAny<User>()))
.ReturnsAsync(createUserResult);

var user = _autoFixture.Create<User>();
Expand All @@ -53,26 +53,37 @@ public async Task HandleWhenInformAValidUser_ShouldCreateANewUserAndReturnsTrue(
var resultHandle = await _createUserCommandHandler.Handle(createUserCommand, CancellationToken.None);

//Assert
_userRepositoryMock
.Verify(x => x.GetAccessTokenAsync(It.IsAny<string>()), Times.Once);

resultHandle.IsSuccess
.Should()
.Be(true);

_userRepositoryMock
.Verify(x => x.GetAccessTokenAsync(It.IsAny<string>()), Times.Once);

_userRepositoryMock
.Verify(x => x.CreateNewUserAsync(It.IsAny<string>(), It.IsAny<User>()), Times.Once);

_userRepositoryMock
.Verify(x => x.GetUserAsync(It.IsAny<string>()), Times.Once);

_userRepositoryMock
.Verify(x => x.ResetPasswordAsync(It.IsAny<string>(), It.IsAny<string>()), Times.Once);

_userRepositoryMock.VerifyNoOtherCalls();
}

[Fact]
public async Task HandleWhenInformAInvalidUser_ShouldNotCreateANewUserAndReturnsFalse()
public async Task HandleWhenInformAInvalidConfig_ShouldNotCreateANewUserAndReturnsFalse()
{
// Arrange
var createUserCommand = _autoFixture.Create<CreateUserCommand>();

var errorMessage = _autoFixture.Create<string>();
UserErrors.SetTechnicalMessage(errorMessage);
var result = Result.Failure(UserErrors.TokenGenerationError);
var result = Result<TokenDetails>.Failure(UserErrors.TokenGenerationError);

_userRepositoryMock
.Setup(x => x.GetAccessTokenAsync(It.IsAny<string>()), Times.Once)
.Setup(x => x.GetAccessTokenAsync(It.IsAny<string>()))
.ReturnsAsync(result);

//Act
Expand All @@ -91,5 +102,36 @@ public async Task HandleWhenInformAInvalidUser_ShouldNotCreateANewUserAndReturns
.Should()
.Contain(result.Error.Code);
}

[Fact]
public async Task HandleWhenInformAInvalidUser_ShouldNotCreateANewUserAndReturnsFalse()
{
// Arrange
var createUserCommand = _autoFixture.Create<CreateUserCommand>();

var errorMessage = _autoFixture.Create<string>();
UserErrors.SetTechnicalMessage(errorMessage);
var successResult = Result<TokenDetails>.Success(_autoFixture.Create<TokenDetails>());


_userRepositoryMock
.Setup(x => x.GetAccessTokenAsync(It.IsAny<string>()))
.ReturnsAsync(successResult);

_userRepositoryMock
.Setup(x => x.CreateNewUserAsync(It.IsAny<string>(), It.IsAny<User>()))
.ReturnsAsync((false, "Some error"));
//Act
var resultHandle = await _createUserCommandHandler.Handle(createUserCommand, CancellationToken.None);

//Assert
resultHandle.IsSuccess
.Should()
.Be(false);

resultHandle.Error.Description
.Should()
.Contain(UserErrors.WrongPasswordDefinition.Description);
}
}
}

0 comments on commit e5abcc9

Please sign in to comment.