-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test a lot more scenarios in UserServiceTest
- Loading branch information
Showing
2 changed files
with
132 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,34 @@ | ||
using LexBoxApi.Auth; | ||
using LexBoxApi.Services; | ||
using LexBoxApi.Services.Email; | ||
using LexCore.Auth; | ||
using LexCore.Entities; | ||
using LexCore.ServiceInterfaces; | ||
using LexData; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.Caching.Memory; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Moq; | ||
using Npgsql; | ||
using Shouldly; | ||
using Testing.Fixtures; | ||
using FluentAssertions; | ||
|
||
namespace Testing.LexCore.Services; | ||
|
||
[Collection(nameof(TestingServicesFixture))] | ||
public class UserServiceTest | ||
public class UserServiceTest : IAsyncLifetime | ||
{ | ||
private readonly UserService _userService; | ||
|
||
private readonly LexBoxDbContext _lexBoxDbContext; | ||
private List<Project> ManagedProjects { get; } = []; | ||
private List<User> ManagedUsers { get; } = []; | ||
|
||
// Users created for this test | ||
private User? Robin { get; set; } | ||
private User? John { get; set; } | ||
private User? Marian { get; set; } | ||
private User? Tuck { get; set; } | ||
private User? Sheriff { get; set; } | ||
// Projects created for this test | ||
private Project? Sherwood { get; set; } | ||
private Project? Nottingham { get; set; } | ||
|
||
public UserServiceTest(TestingServicesFixture testing) | ||
{ | ||
|
@@ -34,38 +41,132 @@ public UserServiceTest(TestingServicesFixture testing) | |
_lexBoxDbContext = serviceProvider.GetRequiredService<LexBoxDbContext>(); | ||
} | ||
|
||
public Task InitializeAsync() | ||
{ | ||
Robin = CreateUser("Robin Hood"); | ||
John = CreateUser("Little John"); | ||
Marian = CreateUser("Maid Marian"); | ||
Tuck = CreateUser("Friar Tuck"); | ||
Sheriff = CreateUser("Sheriff of Nottingham"); | ||
|
||
Nottingham = CreateProject([Sheriff.Id], [Marian.Id]); | ||
Sherwood = CreateConfidentialProject([Robin.Id, Marian.Id], [John.Id]); | ||
|
||
return _lexBoxDbContext.SaveChangesAsync(); | ||
} | ||
|
||
public Task DisposeAsync() | ||
{ | ||
foreach (var project in ManagedProjects) | ||
{ | ||
_lexBoxDbContext.Remove(project); | ||
} | ||
foreach (var user in ManagedUsers) | ||
{ | ||
_lexBoxDbContext.Remove(user); | ||
} | ||
return _lexBoxDbContext.SaveChangesAsync(); | ||
} | ||
|
||
[Fact] | ||
public async Task ManagerCanSeeAllUsersEvenInConfidentialProjects() | ||
{ | ||
var manager = await _lexBoxDbContext.Users.Include(u => u.Organizations).Include(u => u.Projects).FirstOrDefaultAsync(user => user.Email == "[email protected]"); | ||
manager.ShouldNotBeNull(); | ||
await using var privateProject = await TempProjectWithoutRepo.Create(_lexBoxDbContext, true, manager.Id); | ||
privateProject.Project.ShouldNotBeNull(); | ||
var qaAdmin = await _lexBoxDbContext.Users.Include(u => u.Organizations).Include(u => u.Projects).FirstOrDefaultAsync(user => user.Email == "[email protected]"); | ||
qaAdmin.ShouldNotBeNull(); | ||
privateProject.Project.Users.Add(new ProjectUsers() { UserId = qaAdmin.Id, Role = ProjectRole.Editor }); | ||
await _lexBoxDbContext.SaveChangesAsync(); | ||
var authUser = new LexAuthUser(manager); | ||
var authUser = new LexAuthUser(Robin!); | ||
var users = await _userService.UserQueryForTypeahead(authUser).ToArrayAsync(); | ||
users.ShouldNotBeEmpty(); | ||
users.ShouldContain(u => u.Id == qaAdmin.Id); | ||
users.Should().BeEquivalentTo([Robin, Marian, John]); | ||
} | ||
|
||
[Fact] | ||
public async Task NonManagerCanNotSeeUsersInConfidentialProjects() | ||
{ | ||
var manager = await _lexBoxDbContext.Users.Include(u => u.Organizations).Include(u => u.Projects).FirstOrDefaultAsync(user => user.Email == "[email protected]"); | ||
manager.ShouldNotBeNull(); | ||
var editor = await _lexBoxDbContext.Users.Include(u => u.Organizations).Include(u => u.Projects).FirstOrDefaultAsync(user => user.Email == "[email protected]"); | ||
editor.ShouldNotBeNull(); | ||
await using var privateProject = await TempProjectWithoutRepo.Create(_lexBoxDbContext, true, manager.Id); | ||
privateProject.Project.ShouldNotBeNull(); | ||
var qaAdmin = await _lexBoxDbContext.Users.Include(u => u.Organizations).Include(u => u.Projects).FirstOrDefaultAsync(user => user.Email == "[email protected]"); | ||
qaAdmin.ShouldNotBeNull(); | ||
privateProject.Project.Users.Add(new ProjectUsers() { UserId = qaAdmin.Id, Role = ProjectRole.Editor }); | ||
await _lexBoxDbContext.SaveChangesAsync(); | ||
var authUser = new LexAuthUser(editor); | ||
var authUser = new LexAuthUser(John!); | ||
var users = await _userService.UserQueryForTypeahead(authUser).ToArrayAsync(); | ||
users.ShouldNotContain(u => u.Id == qaAdmin.Id); | ||
users.Should().BeEmpty(); | ||
} | ||
|
||
[Fact] | ||
public async Task ManagerOfOneProjectAndMemberOfAnotherPublicProjectCanSeeUsersInBoth() | ||
{ | ||
var authUser = new LexAuthUser(Marian!); | ||
var users = await _userService.UserQueryForTypeahead(authUser).ToArrayAsync(); | ||
users.Should().BeEquivalentTo([Robin, Marian, John, Sheriff]); | ||
} | ||
|
||
[Fact] | ||
public async Task ManagerOfOneProjectAndMemberOfAnotherConfidentialProjectCanNotSeeUsersInConfidentialProject() | ||
{ | ||
try | ||
{ | ||
// Sheriff tries to sneak into Sherwood... | ||
await AddUserToProject(Sherwood!, Sheriff!); | ||
// ... but can still only see the users in Nottingham | ||
var authUser = new LexAuthUser(Sheriff!); | ||
var users = await _userService.UserQueryForTypeahead(authUser).ToArrayAsync(); | ||
users.Should().BeEquivalentTo([Sheriff, Marian]); | ||
} | ||
finally | ||
{ | ||
await RemoveUserFromProject(Sherwood!, Sheriff!); | ||
} | ||
} | ||
|
||
private User CreateUser(string name) | ||
{ | ||
var email = name.ToLowerInvariant().Replace(' ', '_') + "@example.com"; | ||
var user = new User | ||
{ | ||
Name = name, | ||
Email = email, | ||
CanCreateProjects = true, | ||
EmailVerified = true, | ||
IsAdmin = name.Contains("Admin"), | ||
PasswordHash = "", | ||
Salt = "" | ||
}; | ||
_lexBoxDbContext.Add(user); | ||
ManagedUsers.Add(user); | ||
return user; // Caller must call SaveChanges after all users and projects are added | ||
} | ||
|
||
private Project CreateProject(IEnumerable<Guid> managers, IEnumerable<Guid> members, bool isConfidential = false) | ||
{ | ||
var config = Testing.Services.Utils.GetNewProjectConfig(); | ||
var project = new Project | ||
{ | ||
Name = config.Name, | ||
Code = config.Code, | ||
IsConfidential = isConfidential, | ||
LastCommit = null, | ||
Organizations = [], | ||
Users = [], | ||
RetentionPolicy = RetentionPolicy.Test, | ||
Type = ProjectType.FLEx, | ||
Id = config.Id, | ||
}; | ||
project.Users.AddRange(managers.Select(userId => new ProjectUsers { UserId = userId, Role = ProjectRole.Manager })); | ||
project.Users.AddRange(members.Select(userId => new ProjectUsers { UserId = userId, Role = ProjectRole.Editor })); | ||
_lexBoxDbContext.Add(project); | ||
ManagedProjects.Add(project); | ||
return project; // Caller must call SaveChanges after all users and projects are added | ||
} | ||
|
||
private Project CreateConfidentialProject(IEnumerable<Guid> managers, IEnumerable<Guid> members) | ||
{ | ||
return CreateProject(managers, members, true); | ||
} | ||
|
||
private async Task AddUserToProject(Project project, User user, ProjectRole role = ProjectRole.Editor) | ||
{ | ||
var pu = project.Users.FirstOrDefault(pu => pu.UserId == user.Id); | ||
if (pu is null) project.Users.Add(new ProjectUsers { UserId = user.Id, Role = role }); | ||
else pu.Role = role; | ||
await _lexBoxDbContext.SaveChangesAsync(); | ||
} | ||
|
||
private async Task RemoveUserFromProject(Project project, User user) | ||
{ | ||
var pu = project.Users.FirstOrDefault(pu => pu.UserId == user.Id); | ||
if (pu is not null) project.Users.Remove(pu); | ||
await _lexBoxDbContext.SaveChangesAsync(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters