/// <summary> /// Update the specified user in keycloak and PIMS, only add and roles. /// </summary> /// <param name="user"></param> /// <exception type="KeyNotFoundException">User does not exist in keycloak or PIMS.</exception> /// <returns></returns> public async Task <Entity.PimsUser> AppendToUserAsync(Entity.PimsUser update) { var kuser = await _keycloakService.GetUserAsync(update.GuidIdentifierValue.Value) ?? throw new KeyNotFoundException("User does not exist in Keycloak"); var euser = _pimsRepository.User.GetTracking(update.Id); IEnumerable <long> addRoleIds = update.PimsUserRoles.Except(euser.PimsUserRoles, new UserRoleRoleIdComparer()).Select(r => r.RoleId).ToArray(); var roleIds = update.PimsUserRoles.Select(r => r.RoleId); foreach (var roleId in roleIds) { var role = _pimsRepository.Role.Find(roleId) ?? throw new KeyNotFoundException("Cannot assign a role to a user, when the role does not exist."); if (role.KeycloakGroupId == null) { throw new KeyNotFoundException("PIMS has not been synced with Keycloak."); } _logger.LogInformation($"Adding keycloak group '{role.Name}' to user '{euser.BusinessIdentifierValue}'."); await _keycloakService.AddGroupToUserAsync(update.GuidIdentifierValue.Value, role.KeycloakGroupId.Value); } addRoleIds.ForEach(r => { var role = _pimsRepository.Role.Find(r) ?? throw new KeyNotFoundException("Cannot assign a role to a user, when the role does not exist."); if (role.KeycloakGroupId == null) { throw new KeyNotFoundException("PIMS has not been synced with Keycloak."); } euser.PimsUserRoles.Add(new Entity.PimsUserRole(euser, role)); }); return(await SaveUserChanges(update, euser, kuser)); }
/// <summary> /// Create a new instance of an AccessRequest for a default user. /// </summary> /// <param name="id"></param> /// <param name="keycloakUserId"></param> /// <param name="username"></param> /// <param name="firstName"></param> /// <param name="lastName"></param> /// <param name="person"></param> /// <param name="role"></param> /// <param name="organization"></param> /// <returns></returns> public static Entity.PimsUser CreateUser(long id, Guid keycloakUserId, string username, string firstName = "given name", string lastName = "surname", Entity.PimsRole role = null, Entity.PimsOrganization organization = null, Entity.PimsAddress address = null) { organization ??= EntityHelper.CreateOrganization(id, "Organization 1"); role ??= EntityHelper.CreateRole("Real Estate Manager"); var person = new Entity.PimsPerson(lastName, firstName, address); person.PimsContactMethods = new List <Entity.PimsContactMethod>(); var user = new Entity.PimsUser(keycloakUserId, username, person) { Id = id, IssueDate = DateTime.UtcNow, ConcurrencyControlNumber = 1 }; user.PimsUserRoles.Add(new Entity.PimsUserRole() { Role = role, RoleId = role.Id, User = user, UserId = user.Id }); user.PimsUserOrganizations.Add(new Entity.PimsUserOrganization() { Organization = organization, OrganizationId = organization.Id, User = user, UserId = user.Id }); return(user); }
public void GetMyUsers_Success() { // Arrange var helper = new TestHelper(); var controller = helper.CreateController <UserController>(Permissions.AdminUsers); var mapper = helper.GetService <IMapper>(); var service = helper.GetService <Mock <IPimsRepository> >(); var users = new Entity.PimsUser[] { EntityHelper.CreateUser("user1"), EntityHelper.CreateUser("user2") }; var paged = new Entity.Models.Paged <Entity.PimsUser>(users); var filter = new Entity.Models.UserFilter(1, 1, "organization", "username", "lastname", "firstname", "email", false, "role", null, "position"); service.Setup(m => m.User.Get(It.IsAny <Entity.Models.UserFilter>())).Returns(paged); // Act var result = controller.GetMyUsers(filter); // Assert var actionResult = Assert.IsType <JsonResult>(result); Assert.Null(actionResult.StatusCode); var actualResult = Assert.IsType <Pims.Api.Models.PageModel <Model.UserModel> >(actionResult.Value); Assert.Equal(mapper.Map <Model.UserModel[]>(users), actualResult.Items, new DeepPropertyCompare()); service.Verify(m => m.User.Get(It.IsAny <Entity.Models.UserFilter>()), Times.Once()); }
/// <summary> /// Update the specified user in keycloak and PIMS. /// </summary> /// <param name="user"></param> /// <exception type="KeyNotFoundException">User does not exist in keycloak or PIMS.</exception> /// <returns></returns> public async Task <Entity.PimsUser> UpdateUserAsync(Entity.PimsUser user) { var kuser = await _keycloakService.GetUserAsync(user.GuidIdentifierValue.Value) ?? throw new KeyNotFoundException("User does not exist in Keycloak"); var euser = _pimsRepository.User.GetTracking(user.Id); IEnumerable <long> addRoleIds; IEnumerable <long> removeRoleIds; addRoleIds = user.PimsUserRoles.Except(euser.PimsUserRoles, new UserRoleRoleIdComparer()).Select(r => r.RoleId).ToArray(); removeRoleIds = euser.PimsUserRoles.Except(user.PimsUserRoles, new UserRoleRoleIdComparer()).Select(r => r.RoleId).ToArray(); // Update Roles. removeRoleIds.ForEach(r => { var role = _pimsRepository.Role.Find(r) ?? throw new KeyNotFoundException("Cannot remove a role from a user, when the role does not exist."); if (role.KeycloakGroupId == null) { throw new KeyNotFoundException("PIMS has not been synced with Keycloak."); } euser = _pimsRepository.User.RemoveRole(euser, role.RoleId); }); addRoleIds.ForEach(r => { var role = _pimsRepository.Role.Find(r) ?? throw new KeyNotFoundException("Cannot assign a role to a user, when the role does not exist."); if (role.KeycloakGroupId == null) { throw new KeyNotFoundException("PIMS has not been synced with Keycloak."); } euser.PimsUserRoles.Add(new Entity.PimsUserRole(euser, role)); }); return(await SaveUserChanges(user, euser, kuser, true)); }
/// <summary> /// Save the updated user in keycloak and database. /// </summary> /// <param name="update"></param> /// <param name="euser"></param> /// <param name="kuser"></param> /// <returns></returns> private async Task <Entity.PimsUser> SaveUserChanges(Entity.PimsUser update, Entity.PimsUser euser, KModel.UserModel kuser, bool resetRoles = false) { // Update PIMS euser.BusinessIdentifierValue = kuser.Username; // PIMS must use whatever username is set in keycloak. euser.Person.FirstName = update.Person.FirstName; euser.Person.MiddleNames = update.Person.MiddleNames; euser.Person.Surname = update.Person.Surname; euser.Position = update.Position; euser.Note = update.Note; euser.IsDisabled = update.IsDisabled; euser.ConcurrencyControlNumber = update.ConcurrencyControlNumber; //TODO: currently the PIMS contact method screen does not support the concept of multiple contact methods, so for now simply overwrite any work email addresses. euser.Person.PimsContactMethods.RemoveAll(c => c.ContactMethodTypeCode == ContactMethodTypes.WorkEmail); update.Person.PimsContactMethods.ForEach(c => { euser.Person.PimsContactMethods.Add(new PimsContactMethod(c.Person, c.Organization, c.ContactMethodTypeCode, c.ContactMethodValue)); }); euser = _pimsRepository.User.UpdateOnly(euser); // Now update keycloak var kmodel = _mapper.Map <KModel.UserModel>(update); if (resetRoles) { // Remove all keycloak groups from user. // TODO: Only add/remove the ones that should be removed. var userGroups = await _keycloakService.GetUserGroupsAsync(euser.GuidIdentifierValue.Value); foreach (var group in userGroups) { await _keycloakService.RemoveGroupFromUserAsync(update.GuidIdentifierValue.Value, group.Id); } } var roleIds = update.PimsUserRoles.Select(r => r.RoleId); foreach (var roleId in roleIds) { var role = _pimsRepository.Role.Find(roleId) ?? throw new KeyNotFoundException("Cannot assign a role to a user, when the role does not exist."); if (role.KeycloakGroupId == null) { throw new KeyNotFoundException("PIMS has not been synced with Keycloak."); } _logger.LogInformation($"Adding keycloak group '{role.Name}' to user '{euser.BusinessIdentifierValue}'."); await _keycloakService.AddGroupToUserAsync(update.GuidIdentifierValue.Value, role.KeycloakGroupId.Value); } kmodel.Attributes = new Dictionary <string, string[]> { ["displayName"] = new[] { update.BusinessIdentifierValue } }; _logger.LogInformation($"Updating keycloak user '{euser.BusinessIdentifierValue}'."); await _keycloakService.UpdateUserAsync(kmodel); return(_pimsRepository.User.Get(euser.Id)); }
/// <summary> /// Create a new instance of a UserOrganization class. /// </summary> /// <param name="user"></param> /// <param name="organization"></param> /// <param name="role"></param> public PimsUserOrganization(PimsUser user, PimsOrganization organization, PimsRole role) { this.User = user ?? throw new ArgumentNullException(nameof(user)); this.UserId = user.Id; this.Organization = organization ?? throw new ArgumentNullException(nameof(organization)); this.OrganizationId = organization.Id; this.Role = role ?? throw new ArgumentNullException(nameof(role)); this.RoleId = role.RoleId; }
/// <summary> /// Create a new instance of a AccessRequest class. /// </summary> /// <param name="user"></param> /// <param name="role"></param> /// <param name="status"></param> public PimsAccessRequest(PimsUser user, PimsRole role, PimsAccessRequestStatusType status) : this() { this.User = user ?? throw new ArgumentNullException(nameof(user)); this.UserId = user.Id; this.Role = role ?? throw new ArgumentNullException(nameof(role)); this.RoleId = role.RoleId; this.AccessRequestStatusTypeCodeNavigation = status ?? throw new ArgumentNullException(nameof(status)); this.AccessRequestStatusTypeCode = status.Id; }
/// <summary> /// Create a new instance of a UserRole class. /// </summary> /// <param name="user"></param> /// <param name="role"></param> public PimsUserRole(PimsUser user, PimsRole role) { this.User = user; this.UserId = user?.Id ?? throw new ArgumentNullException(nameof(user)); this.Role = role; this.RoleId = role?.RoleId ?? throw new ArgumentNullException(nameof(role)); }
private static void UpdateUser(Model.UserModel model, Entity.PimsUser entity) { entity.PimsUserOrganizations.Where(a => a != null).ForEach(a => { a.UserId = entity.Id; a.RoleId = model.Roles.FirstOrDefault()?.Id ?? 0; }); entity.PimsUserRoles.Where(r => r?.RoleId != null).ForEach(r => r.UserId = entity.Id); if (model?.Email?.Length > 0) { entity.Person.PimsContactMethods.Add(new PimsContactMethod(entity.Person, null, ContactMethodTypes.WorkEmail, model.Email)); } }
/// <summary> /// Create a new instance of an AccessRequest for the specified user. /// </summary> /// <param name="id"></param> /// <param name="user"></param> /// <param name="role"></param> /// <param name="organization"></param> /// <returns></returns> public static Entity.PimsAccessRequest CreateAccessRequest(long id, Entity.PimsUser user, Entity.PimsRole role, Entity.PimsOrganization organization) { user ??= EntityHelper.CreateUser("test"); role ??= EntityHelper.CreateRole("Real Estate Manager"); var accessRequest = new Entity.PimsAccessRequest() { AccessRequestId = id, UserId = user.Id, User = user, RoleId = role.Id, Role = role }; organization ??= EntityHelper.CreateOrganization(id, "test", EntityHelper.CreateOrganizationType("Type 1"), EntityHelper.CreateOrganizationIdentifierType("Identifier 1"), EntityHelper.CreateAddress(id)); accessRequest.PimsAccessRequestOrganizations.Add(new Entity.PimsAccessRequestOrganization() { AccessRequestId = id, AccessRequest = accessRequest, OrganizationId = organization.Id, Organization = organization }); return(accessRequest); }
/// <summary> /// Creates a new instance of a UserModel object, initializes it with specified arguments. /// </summary> /// <param name="user"></param> public UserModel(Entity.PimsUser user) { this.Id = user.Id; this.Key = user.GuidIdentifierValue.Value; }