public async void CreateProject_ShouldReturnCorrectAccess() { // Arrange _fakeHttpContextItems.Add(ApplicationIdentityService.CURRENTUSERKEY, _testUser); var newDecryptedProject = CreateTestProject(); AccessIdentifier accessIdentifier1 = new AccessIdentifier(); accessIdentifier1.Role = TeamStore.Keeper.Enums.Role.Editor; accessIdentifier1.Identity = new ApplicationUser() { AzureAdNameIdentifier = "TestAdIdentity1", AzureAdObjectIdentifier = "TestAdObjectId1", TenantId = "1234", Upn = "*****@*****.**" }; AccessIdentifier accessIdentifier2 = new AccessIdentifier(); accessIdentifier2.Role = TeamStore.Keeper.Enums.Role.Owner; accessIdentifier2.Identity = new ApplicationGroup() { DisplayName = "TestGroup1", AzureAdObjectIdentifier = "TestAdObjectId1", TenantId = "1234" }; newDecryptedProject.AccessIdentifiers.Add(accessIdentifier1); newDecryptedProject.AccessIdentifiers.Add(accessIdentifier2); // Act var createdProjectId = await _projectsService.CreateProject(newDecryptedProject); var retrievedProject = await _projectsService.GetProject(createdProjectId); // Assert Assert.True(retrievedProject.Id > 0); Assert.False(retrievedProject.IsArchived); Assert.Equal(3, retrievedProject.AccessIdentifiers.Count); // +1 for the Owner Assert.NotNull(retrievedProject.AccessIdentifiers.First()); Assert.NotNull(retrievedProject.AccessIdentifiers.First().Project); Assert.True(retrievedProject.AccessIdentifiers.First().ProjectForeignKey > 0); Assert.Equal(Role.Editor, retrievedProject.AccessIdentifiers.First().Role); Assert.NotEqual(Role.Reader, retrievedProject.AccessIdentifiers.First().Role); Assert.IsType <ApplicationUser>(retrievedProject.AccessIdentifiers.First().Identity); Assert.Equal("1234", retrievedProject.AccessIdentifiers.First().Identity.TenantId); Assert.Equal("TestAdObjectId1", retrievedProject.AccessIdentifiers.First().Identity.AzureAdObjectIdentifier); Assert.Equal("*****@*****.**", ((ApplicationUser)retrievedProject.AccessIdentifiers.First().Identity).Upn); Assert.Equal("TestAdIdentity1", ((ApplicationUser)retrievedProject.AccessIdentifiers.First().Identity).AzureAdNameIdentifier); // Cleanup await _projectsService.ArchiveProject(retrievedProject, "127.0.1.1"); var archivedProject = await _projectsService.GetProject(createdProjectId); Assert.Null(archivedProject); }
private static AccessIdentifierViewModel BuildAccessIdentityViewModel(AccessIdentifier accessIdentifier) { var newAccessIdentifierViewModel = new AccessIdentifierViewModel(); var appIdentity = (ApplicationUser)accessIdentifier.Identity; newAccessIdentifierViewModel.DisplayName = appIdentity.DisplayName; newAccessIdentifierViewModel.Role = accessIdentifier.Role; newAccessIdentifierViewModel.Upn = appIdentity.Upn; newAccessIdentifierViewModel.LastModified = accessIdentifier.Modified == DateTime.MinValue ? accessIdentifier.Created : accessIdentifier.Modified; return(newAccessIdentifierViewModel); }
/// <summary> /// Grants access to a project /// </summary> /// <param name="projectId">The Id of the project</param> /// <param name="upn">The UPN identifier of the identity for which access will be granted to</param> /// <param name="role">The role/level of access that will be granted</param> /// <param name="remoteIpAddress">The IP address of the incoming request</param> /// <param name="projectsService">An instance of IProjectService to assist with resolving of the project</param> /// <returns>A Task object with an AccessChangeResult representing the result</returns> public async Task <AccessChangeResult> GrantAccessAsync( int projectId, string upn, Role role, string remoteIpAddress, IProjectsService projectsService) { if (string.IsNullOrWhiteSpace(upn)) { throw new ArgumentNullException(nameof(upn)); } if (string.IsNullOrWhiteSpace(remoteIpAddress)) { throw new ArgumentNullException(nameof(remoteIpAddress)); } if (projectId == 0) { throw new ArgumentException("You must provide a valid project id."); } var currentUser = await _applicationIdentityService.GetCurrentUser(); if (currentUser == null) { throw new ArgumentException("The current user could not be retrieved."); } // Get/find the project var project = await projectsService.GetProject(projectId, true); if (project == null) { throw new ArgumentNullException(nameof(project)); } // Refresh the entity to discard changes and avoid saving a decrypted project if (project.IsDecrypted == true) { _dbContext.Entry(project).State = EntityState.Unchanged; // project will be encrypted here } // Verify current user has permissions to grant access, aka Owner if (await CurrentUserHasAccessAsync(projectId, projectsService, Role.Owner) == false) { await _eventService.LogCustomEventAsync(currentUser.Id.ToString(), $"User {currentUser.Upn} attepted to give access to {upn} without having access to project with ID: {projectId}."); throw new Exception("The current user does not have permissions to grant access."); } // Check if the target user already has access if (CheckAccess(project, upn, Role.Owner)) { await _eventService.LogCustomEventAsync(currentUser.Id.ToString(), $"The user {currentUser.Upn} attepted to give access to {upn} who already has access to project with ID: {projectId}."); return(new AccessChangeResult() { Success = false, Message = $"User {upn} already has access." }); // no need to grant } // TODO: grant access to AD group var newAccessIdentifier = new AccessIdentifier(); newAccessIdentifier.Project = project ?? throw new ArgumentNullException(nameof(project)); newAccessIdentifier.Role = role; newAccessIdentifier.Created = DateTime.UtcNow; newAccessIdentifier.CreatedBy = currentUser ?? throw new ArgumentNullException(nameof(currentUser)); newAccessIdentifier.Identity = await _applicationIdentityService.EnsureUserByUpnAsync(upn); project.AccessIdentifiers.Add(newAccessIdentifier); // Validation of the access identifiers before save foreach (var item in project.AccessIdentifiers) { if ((item.Identity == null)) { await _eventService.LogCustomEventAsync(currentUser.Upn, $"Ensure did not return a user for {upn}"); return(new AccessChangeResult() { Success = false, Message = $"The user or group '{upn}' was not found." }); } } // Save Grant event // Issue: LogGrantAccessEventAsync calls SaveChanges. await _eventService.LogGrantAccessEventAsync(projectId, remoteIpAddress, role, newAccessIdentifier.Identity.Id, currentUser.Id, "UPN: " + upn); var modifiedRows = await _dbContext.SaveChangesAsync(); return(new AccessChangeResult() { Success = true }); }