From 20d3b4b4e8159e456f8f8938fe68958f7c06a76b Mon Sep 17 00:00:00 2001 From: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> Date: Wed, 26 Apr 2023 13:09:25 -0500 Subject: [PATCH] [SM-670] Add permission context to project lists. (#2822) * Attach permission context to project lists. * restrict service-account actions * Fix project permission details * Add getters and setters * dotnet format * Fix admin create unassigned secret (#2872) --- .../CreateAccessPoliciesCommand.cs | 2 +- .../DeleteAccessPolicyCommand.cs | 2 +- .../UpdateAccessPolicyCommand.cs | 2 +- .../Commands/Projects/DeleteProjectCommand.cs | 12 +- .../Commands/Projects/UpdateProjectCommand.cs | 10 +- .../Commands/Secrets/CreateSecretCommand.cs | 2 +- .../Commands/Secrets/DeleteSecretCommand.cs | 10 +- .../Commands/Secrets/UpdateSecretCommand.cs | 6 +- .../Repositories/ProjectRepository.cs | 131 ++++++++---------- .../CreateAccessPoliciesCommandTests.cs | 4 +- .../DeleteAccessPolicyCommandTests.cs | 5 +- .../UpdateAccessPolicyCommandTests.cs | 5 +- .../Projects/DeleteProjectCommandTests.cs | 10 +- .../Projects/UpdateProjectCommandTests.cs | 9 +- .../Secrets/CreateSecretCommandTests.cs | 9 +- .../Secrets/DeleteSecretCommandTests.cs | 4 +- .../Secrets/UpdateSecretCommandTests.cs | 5 +- .../Controllers/AccessPoliciesController.cs | 10 +- .../Controllers/ProjectsController.cs | 12 +- .../SecretsManagerPortingController.cs | 2 +- .../ProjectPermissionDetailsResponseModel.cs | 22 --- .../Models/Response/ProjectResponseModel.cs | 26 +++- .../Models/Data/ProjectPermissionDetails.cs | 3 +- .../Models/Data/SecretPermissionDetails.cs | 2 +- .../Repositories/IProjectRepository.cs | 7 +- .../Controllers/ProjectsControllerTests.cs | 2 +- .../Controllers/SecretsControllerTests.cs | 4 +- .../AccessPoliciesControllerTests.cs | 20 +-- .../Controllers/ProjectsControllerTests.cs | 11 +- .../Controllers/SecretsControllerTests.cs | 17 ++- 30 files changed, 183 insertions(+), 183 deletions(-) delete mode 100644 src/Api/SecretsManager/Models/Response/ProjectPermissionDetailsResponseModel.cs diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs index ec9ce3f35..aab7c75c2 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs @@ -118,7 +118,7 @@ public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand case AccessClientType.User: if (projectIdToCheck.HasValue) { - hasAccess = await _projectRepository.UserHasWriteAccessToProject(projectIdToCheck.Value, userId); + hasAccess = (await _projectRepository.AccessToProjectAsync(projectIdToCheck.Value, userId, accessClient)).Write; } else if (serviceAccountIdToCheck.HasValue) { diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs index ad5b3da14..53955c170 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs @@ -83,7 +83,7 @@ public class DeleteAccessPolicyCommand : IDeleteAccessPolicyCommand case AccessClientType.User: if (projectIdToCheck.HasValue) { - hasAccess = await _projectRepository.UserHasWriteAccessToProject(projectIdToCheck.Value, userId); + hasAccess = (await _projectRepository.AccessToProjectAsync(projectIdToCheck.Value, userId, accessClient)).Write; } else if (serviceAccountIdToCheck.HasValue) { diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs index bf83b735c..b911d52e9 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs @@ -87,7 +87,7 @@ public class UpdateAccessPolicyCommand : IUpdateAccessPolicyCommand case AccessClientType.User: if (projectIdToCheck.HasValue) { - hasAccess = await _projectRepository.UserHasWriteAccessToProject(projectIdToCheck.Value, userId); + hasAccess = (await _projectRepository.AccessToProjectAsync(projectIdToCheck.Value, userId, accessClient)).Write; } else if (serviceAccountIdToCheck.HasValue) { diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/DeleteProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/DeleteProjectCommand.cs index 06e282c28..35cd19910 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/DeleteProjectCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/DeleteProjectCommand.cs @@ -49,19 +49,13 @@ public class DeleteProjectCommand : IDeleteProjectCommand var orgAdmin = await _currentContext.OrganizationAdmin(organizationId); var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); - var results = new List>(projects.Count); + var results = new List>(projects.Count); var deleteIds = new List(); foreach (var project in projects) { - var hasAccess = accessClient switch - { - AccessClientType.NoAccessCheck => true, - AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(project.Id, userId), - _ => false, - }; - - if (!hasAccess) + var access = await _projectRepository.AccessToProjectAsync(project.Id, userId, accessClient); + if (!access.Write || accessClient == AccessClientType.ServiceAccount) { results.Add(new Tuple(project, "access denied")); } diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/UpdateProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/UpdateProjectCommand.cs index 06ed949c0..d03dcf954 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/UpdateProjectCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/UpdateProjectCommand.cs @@ -34,14 +34,8 @@ public class UpdateProjectCommand : IUpdateProjectCommand var orgAdmin = await _currentContext.OrganizationAdmin(project.OrganizationId); var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); - var hasAccess = accessClient switch - { - AccessClientType.NoAccessCheck => true, - AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(updatedProject.Id, userId), - _ => false, - }; - - if (!hasAccess) + var access = await _projectRepository.AccessToProjectAsync(updatedProject.Id, userId, accessClient); + if (!access.Write || accessClient == AccessClientType.ServiceAccount) { throw new NotFoundException(); } diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/CreateSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/CreateSecretCommand.cs index 8f0ce365e..8d5e09082 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/CreateSecretCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/CreateSecretCommand.cs @@ -39,7 +39,7 @@ public class CreateSecretCommand : ICreateSecretCommand var hasAccess = accessClient switch { AccessClientType.NoAccessCheck => true, - AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(project.Id, userId), + AccessClientType.User => (await _projectRepository.AccessToProjectAsync(project.Id, userId, accessClient)).Write, _ => false, }; diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/DeleteSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/DeleteSecretCommand.cs index 2d59cffe3..1b163c7a8 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/DeleteSecretCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/DeleteSecretCommand.cs @@ -54,16 +54,10 @@ public class DeleteSecretCommand : IDeleteSecretCommand if (secret.Projects != null && secret.Projects?.Count > 0) { var projectId = secret.Projects.First().Id; - - hasAccess = accessClient switch - { - AccessClientType.NoAccessCheck => true, - AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(projectId, userId), - _ => false, - }; + hasAccess = (await _projectRepository.AccessToProjectAsync(projectId, userId, accessClient)).Write; } - if (!hasAccess) + if (!hasAccess || accessClient == AccessClientType.ServiceAccount) { results.Add(new Tuple(secret, "access denied")); } diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/UpdateSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/UpdateSecretCommand.cs index 350ad65fd..0b5509efd 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/UpdateSecretCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/UpdateSecretCommand.cs @@ -51,7 +51,7 @@ public class UpdateSecretCommand : IUpdateSecretCommand return secret; } - public async Task HasAccessToOriginalAndUpdatedProject(AccessClientType accessClient, Secret secret, Secret updatedSecret, Guid userId) + private async Task HasAccessToOriginalAndUpdatedProject(AccessClientType accessClient, Secret secret, Secret updatedSecret, Guid userId) { switch (accessClient) { @@ -60,8 +60,8 @@ public class UpdateSecretCommand : IUpdateSecretCommand case AccessClientType.User: var oldProject = secret.Projects?.FirstOrDefault(); var newProject = updatedSecret.Projects?.FirstOrDefault(); - var accessToOld = oldProject != null && await _projectRepository.UserHasWriteAccessToProject(oldProject.Id, userId); - var accessToNew = newProject != null && await _projectRepository.UserHasWriteAccessToProject(newProject.Id, userId); + var accessToOld = oldProject != null && (await _projectRepository.AccessToProjectAsync(oldProject.Id, userId, accessClient)).Write; + var accessToNew = newProject != null && (await _projectRepository.AccessToProjectAsync(newProject.Id, userId, accessClient)).Write; return accessToOld && accessToNew; default: return false; diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs index 676b76966..a05140fb0 100644 --- a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs @@ -1,6 +1,7 @@ using System.Linq.Expressions; using AutoMapper; using Bit.Core.Enums; +using Bit.Core.SecretsManager.Models.Data; using Bit.Core.SecretsManager.Repositories; using Bit.Infrastructure.EntityFramework.Repositories; using Bit.Infrastructure.EntityFramework.SecretsManager.Models; @@ -27,22 +28,16 @@ public class ProjectRepository : Repository> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType) + public async Task> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType) { using var scope = ServiceScopeFactory.CreateScope(); var dbContext = GetDatabaseContext(scope); - var query = dbContext.Project.Where(p => p.OrganizationId == organizationId && p.DeletedDate == null); - query = accessType switch - { - AccessClientType.NoAccessCheck => query, - AccessClientType.User => query.Where(UserHasReadAccessToProject(userId)), - AccessClientType.ServiceAccount => query.Where(ServiceAccountHasReadAccessToProject(userId)), - _ => throw new ArgumentOutOfRangeException(nameof(accessType), accessType, null), - }; + var query = dbContext.Project.Where(p => p.OrganizationId == organizationId && p.DeletedDate == null).OrderBy(p => p.RevisionDate); - var projects = await query.OrderBy(p => p.RevisionDate).ToListAsync(); - return Mapper.Map>(projects); + var projects = ProjectToPermissionDetails(query, userId, accessType); + + return await projects.ToListAsync(); } public async Task> GetManyByOrganizationIdWriteAccessAsync( @@ -63,20 +58,6 @@ public class ProjectRepository : Repository>(projects); } - private static Expression> UserHasReadAccessToProject(Guid userId) => p => - p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Read) || - p.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Read)); - - private static Expression> UserHasWriteAccessToProject(Guid userId) => p => - p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Write) || - p.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Write)); - - private static Expression> ServiceAccountHasReadAccessToProject(Guid serviceAccountId) => p => - p.ServiceAccountAccessPolicies.Any(ap => ap.ServiceAccount.Id == serviceAccountId && ap.Read); - - private static Expression> ServiceAccountHasWriteAccessToProject(Guid serviceAccountId) => p => - p.ServiceAccountAccessPolicies.Any(ap => ap.ServiceAccount.Id == serviceAccountId && ap.Write); - public async Task DeleteManyByIdAsync(IEnumerable ids) { using (var scope = ServiceScopeFactory.CreateScope()) @@ -97,57 +78,13 @@ public class ProjectRepository : Repository p.Secrets) - .Where(c => ids.Contains(c.Id) && c.DeletedDate == null) - .ToListAsync(); + .Include(p => p.Secrets) + .Where(c => ids.Contains(c.Id) && c.DeletedDate == null) + .ToListAsync(); return Mapper.Map>(projects); } } - public async Task ServiceAccountHasReadAccessToProject(Guid id, Guid userId) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var query = dbContext.Project - .Where(p => p.Id == id) - .Where(ServiceAccountHasReadAccessToProject(userId)); - - return await query.AnyAsync(); - } - - public async Task ServiceAccountHasWriteAccessToProject(Guid id, Guid userId) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var query = dbContext.Project - .Where(p => p.Id == id) - .Where(ServiceAccountHasWriteAccessToProject(userId)); - - return await query.AnyAsync(); - } - - public async Task UserHasReadAccessToProject(Guid id, Guid userId) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var query = dbContext.Project - .Where(p => p.Id == id) - .Where(UserHasReadAccessToProject(userId)); - - return await query.AnyAsync(); - } - - public async Task UserHasWriteAccessToProject(Guid id, Guid userId) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var query = dbContext.Project - .Where(p => p.Id == id) - .Where(UserHasWriteAccessToProject(userId)); - - return await query.AnyAsync(); - } - public async Task> ImportAsync(IEnumerable projects) { using var scope = ServiceScopeFactory.CreateScope(); @@ -199,4 +136,54 @@ public class ProjectRepository : Repository ProjectToPermissionDetails(IQueryable query, Guid userId, AccessClientType accessType) + { + var projects = accessType switch + { + AccessClientType.NoAccessCheck => query.Select(p => new ProjectPermissionDetails + { + Project = Mapper.Map(p), + Read = true, + Write = true, + }), + AccessClientType.User => query.Where(UserHasReadAccessToProject(userId)).Select(ProjectToPermissionsUser(userId, true)), + AccessClientType.ServiceAccount => query.Where(ServiceAccountHasReadAccessToProject(userId)).Select(ProjectToPermissionsServiceAccount(userId, true)), + _ => throw new ArgumentOutOfRangeException(nameof(accessType), accessType, null), + }; + return projects; + } + + private Expression> ProjectToPermissionsUser(Guid userId, bool read) => + p => new ProjectPermissionDetails + { + Project = Mapper.Map(p), + Read = read, + Write = p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Write) || + p.GroupAccessPolicies.Any(ap => + ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Write)), + }; + + private Expression> ProjectToPermissionsServiceAccount(Guid userId, bool read) => + p => new ProjectPermissionDetails + { + Project = Mapper.Map(p), + Read = read, + Write = p.ServiceAccountAccessPolicies.Any(ap => ap.ServiceAccount.Id == userId && ap.Write), + }; + + private static Expression> UserHasReadAccessToProject(Guid userId) => p => + p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Read) || + p.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Read)); + + private static Expression> UserHasWriteAccessToProject(Guid userId) => p => + p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Write) || + p.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Write)); + + private static Expression> ServiceAccountHasReadAccessToProject(Guid serviceAccountId) => p => + p.ServiceAccountAccessPolicies.Any(ap => ap.ServiceAccount.Id == serviceAccountId && ap.Read); + + private static Expression> ServiceAccountHasWriteAccessToProject(Guid serviceAccountId) => p => + p.ServiceAccountAccessPolicies.Any(ap => ap.ServiceAccount.Id == serviceAccountId && ap.Write); + } diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/CreateAccessPoliciesCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/CreateAccessPoliciesCommandTests.cs index 2c61e5ec8..1105f2a5a 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/CreateAccessPoliciesCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/CreateAccessPoliciesCommandTests.cs @@ -136,8 +136,8 @@ public class CreateAccessPoliciesCommandTests { if (permissionType == PermissionType.RunAsUserWithPermission) { - sutProvider.GetDependency().UserHasWriteAccessToProject(project.Id, userId) - .Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(project.Id, userId, AccessClientType.User) + .Returns((true, true)); } } diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/DeleteAccessPolicyCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/DeleteAccessPolicyCommandTests.cs index c1c5743d7..5c98812ce 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/DeleteAccessPolicyCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/DeleteAccessPolicyCommandTests.cs @@ -2,6 +2,7 @@ using Bit.Commercial.Core.Test.SecretsManager.Enums; using Bit.Core.Context; using Bit.Core.Entities; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; @@ -28,8 +29,8 @@ public class DeleteAccessPolicyCommandTests .Returns(true); break; case PermissionType.RunAsUserWithPermission: - sutProvider.GetDependency().UserHasWriteAccessToProject(grantedProject.Id, userId) - .Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(grantedProject.Id, userId, AccessClientType.User) + .Returns((true, true)); break; default: throw new ArgumentOutOfRangeException(nameof(permissionType), permissionType, null); diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/UpdateAccessPolicyCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/UpdateAccessPolicyCommandTests.cs index a0f69c9f2..b027f47b5 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/UpdateAccessPolicyCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/UpdateAccessPolicyCommandTests.cs @@ -2,6 +2,7 @@ using Bit.Commercial.Core.Test.SecretsManager.Enums; using Bit.Core.Context; using Bit.Core.Entities; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; @@ -28,8 +29,8 @@ public class UpdateAccessPolicyCommandTests .Returns(true); break; case PermissionType.RunAsUserWithPermission: - sutProvider.GetDependency().UserHasWriteAccessToProject(grantedProject.Id, userId) - .Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(grantedProject.Id, userId, AccessClientType.User) + .Returns((true, true)); break; default: throw new ArgumentOutOfRangeException(nameof(permissionType), permissionType, null); diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/DeleteProjectCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/DeleteProjectCommandTests.cs index f85125b19..9361c2a0c 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/DeleteProjectCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/DeleteProjectCommandTests.cs @@ -1,5 +1,6 @@ using Bit.Commercial.Core.SecretsManager.Commands.Projects; using Bit.Core.Context; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.Identity; using Bit.Core.SecretsManager.Entities; @@ -52,7 +53,8 @@ public class DeleteProjectCommandTests sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(true); sutProvider.GetDependency().ClientType = ClientType.User; sutProvider.GetDependency().GetManyWithSecretsByIds(data).Returns(projects); - sutProvider.GetDependency().UserHasWriteAccessToProject(Arg.Any(), userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), userId, AccessClientType.User) + .Returns((true, true)); var results = await sutProvider.Sut.DeleteProjects(data, userId); @@ -74,7 +76,8 @@ public class DeleteProjectCommandTests sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(true); sutProvider.GetDependency().ClientType = ClientType.User; sutProvider.GetDependency().GetManyWithSecretsByIds(data).Returns(projects); - sutProvider.GetDependency().UserHasWriteAccessToProject(userId, userId).Returns(false); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), userId, AccessClientType.User) + .Returns((false, false)); var results = await sutProvider.Sut.DeleteProjects(data, userId); @@ -96,6 +99,9 @@ public class DeleteProjectCommandTests sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(true); sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(true); sutProvider.GetDependency().GetManyWithSecretsByIds(data).Returns(projects); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), userId, AccessClientType.NoAccessCheck) + .Returns((true, true)); + var results = await sutProvider.Sut.DeleteProjects(data, userId); diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/UpdateProjectCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/UpdateProjectCommandTests.cs index 8bacf0fc2..f105f5cbe 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/UpdateProjectCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/UpdateProjectCommandTests.cs @@ -1,5 +1,6 @@ using Bit.Commercial.Core.SecretsManager.Commands.Projects; using Bit.Core.Context; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; @@ -35,6 +36,8 @@ public class UpdateProjectCommandTests sutProvider.GetDependency().GetByIdAsync(project.Id).Returns(project); sutProvider.GetDependency().AccessSecretsManager(project.OrganizationId).Returns(true); sutProvider.GetDependency().OrganizationAdmin(project.OrganizationId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(project.Id, userId, AccessClientType.NoAccessCheck) + .Returns((true, true)); var project2 = new Project { Id = project.Id, Name = "newName" }; var result = await sutProvider.Sut.UpdateAsync(project2, userId); @@ -51,7 +54,8 @@ public class UpdateProjectCommandTests public async Task UpdateAsync_User_NoAccess(Project project, Guid userId, SutProvider sutProvider) { sutProvider.GetDependency().GetByIdAsync(project.Id).Returns(project); - sutProvider.GetDependency().UserHasWriteAccessToProject(project.Id, userId).Returns(false); + sutProvider.GetDependency().AccessToProjectAsync(project.Id, userId, AccessClientType.User) + .Returns((false, false)); sutProvider.GetDependency().AccessSecretsManager(project.OrganizationId).Returns(true); await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(project, userId)); @@ -64,7 +68,8 @@ public class UpdateProjectCommandTests public async Task UpdateAsync_User_Success(Project project, Guid userId, SutProvider sutProvider) { sutProvider.GetDependency().GetByIdAsync(project.Id).Returns(project); - sutProvider.GetDependency().UserHasWriteAccessToProject(project.Id, userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(project.Id, userId, AccessClientType.User) + .Returns((true, true)); sutProvider.GetDependency().AccessSecretsManager(project.OrganizationId).Returns(true); var project2 = new Project { Id = project.Id, Name = "newName" }; diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/CreateSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/CreateSecretCommandTests.cs index 9ae71ee8d..6cec64337 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/CreateSecretCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/CreateSecretCommandTests.cs @@ -1,6 +1,7 @@ using Bit.Commercial.Core.SecretsManager.Commands.Secrets; using Bit.Commercial.Core.Test.SecretsManager.Enums; using Bit.Core.Context; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; @@ -30,11 +31,14 @@ public class CreateSecretCommandTests if (permissionType == PermissionType.RunAsAdmin) { sutProvider.GetDependency().OrganizationAdmin(data.OrganizationId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync((Guid)data.Projects?.First().Id, userId, AccessClientType.NoAccessCheck) + .Returns((true, true)); } else { sutProvider.GetDependency().OrganizationAdmin(data.OrganizationId).Returns(false); - sutProvider.GetDependency().UserHasWriteAccessToProject((Guid)(data.Projects?.First().Id), userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync((Guid)data.Projects?.First().Id, userId, AccessClientType.User) + .Returns((true, true)); } await sutProvider.Sut.CreateAsync(data, userId); @@ -52,7 +56,8 @@ public class CreateSecretCommandTests data.Projects = new List() { mockProject }; sutProvider.GetDependency().OrganizationAdmin(data.OrganizationId).Returns(false); - sutProvider.GetDependency().UserHasWriteAccessToProject((Guid)(data.Projects?.First().Id), userId).Returns(false); + sutProvider.GetDependency().AccessToProjectAsync((Guid)data.Projects?.First().Id, userId, AccessClientType.User) + .Returns((false, false)); await Assert.ThrowsAsync(() => sutProvider.Sut.CreateAsync(data, userId)); diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/DeleteSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/DeleteSecretCommandTests.cs index 8026fcd8e..4ff4793a2 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/DeleteSecretCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/DeleteSecretCommandTests.cs @@ -1,6 +1,7 @@ using Bit.Commercial.Core.SecretsManager.Commands.Secrets; using Bit.Commercial.Core.Test.SecretsManager.Enums; using Bit.Core.Context; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; @@ -60,7 +61,8 @@ public class DeleteSecretCommandTests else { sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().UserHasWriteAccessToProject(mockProject.Id, userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(mockProject.Id, userId, AccessClientType.User) + .Returns((true, true)); projects = new List() { mockProject }; } diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/UpdateSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/UpdateSecretCommandTests.cs index c348acf13..b90814513 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/UpdateSecretCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/UpdateSecretCommandTests.cs @@ -1,6 +1,7 @@ using Bit.Commercial.Core.SecretsManager.Commands.Secrets; using Bit.Commercial.Core.Test.SecretsManager.Enums; using Bit.Core.Context; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; @@ -46,7 +47,9 @@ public class UpdateSecretCommandTests else { sutProvider.GetDependency().OrganizationAdmin(data.OrganizationId).Returns(false); - sutProvider.GetDependency().UserHasWriteAccessToProject((Guid)(data.Projects?.First().Id), userId).Returns(true); + sutProvider.GetDependency() + .AccessToProjectAsync((Guid)data.Projects?.First().Id, userId, AccessClientType.User) + .Returns((true, true)); } sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); diff --git a/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs b/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs index 789cfb7e0..dd4db2bfa 100644 --- a/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs +++ b/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs @@ -249,14 +249,8 @@ public class AccessPoliciesController : Controller } var (accessClient, userId) = await GetAccessClientTypeAsync(project.OrganizationId); - var hasAccess = accessClient switch - { - AccessClientType.NoAccessCheck => true, - AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(project.Id, userId), - _ => false, - }; - - if (!hasAccess) + var access = await _projectRepository.AccessToProjectAsync(project.Id, userId, accessClient); + if (!access.Write || accessClient == AccessClientType.ServiceAccount) { throw new NotFoundException(); } diff --git a/src/Api/SecretsManager/Controllers/ProjectsController.cs b/src/Api/SecretsManager/Controllers/ProjectsController.cs index b3b52cd07..b4f9983bd 100644 --- a/src/Api/SecretsManager/Controllers/ProjectsController.cs +++ b/src/Api/SecretsManager/Controllers/ProjectsController.cs @@ -67,7 +67,9 @@ public class ProjectsController : Controller var userId = _userService.GetProperUserId(User).Value; var result = await _createProjectCommand.CreateAsync(createRequest.ToProject(organizationId), userId); - return new ProjectResponseModel(result); + + // Creating a project means you have read & write permission. + return new ProjectResponseModel(result, true, true); } [HttpPut("projects/{id}")] @@ -76,11 +78,13 @@ public class ProjectsController : Controller var userId = _userService.GetProperUserId(User).Value; var result = await _updateProjectCommand.UpdateAsync(updateRequest.ToProject(id), userId); - return new ProjectResponseModel(result); + + // Updating a project means you have read & write permission. + return new ProjectResponseModel(result, true, true); } [HttpGet("projects/{id}")] - public async Task GetAsync([FromRoute] Guid id) + public async Task GetAsync([FromRoute] Guid id) { var project = await _projectRepository.GetByIdAsync(id); if (project == null) @@ -104,7 +108,7 @@ public class ProjectsController : Controller throw new NotFoundException(); } - return new ProjectPermissionDetailsResponseModel(project, access.Read, access.Write); + return new ProjectResponseModel(project, access.Read, access.Write); } [HttpPost("projects/delete")] diff --git a/src/Api/SecretsManager/Controllers/SecretsManagerPortingController.cs b/src/Api/SecretsManager/Controllers/SecretsManagerPortingController.cs index a74c2fa48..172a1b5c6 100644 --- a/src/Api/SecretsManager/Controllers/SecretsManagerPortingController.cs +++ b/src/Api/SecretsManager/Controllers/SecretsManagerPortingController.cs @@ -47,7 +47,7 @@ public class SecretsManagerPortingController : Controller throw new NotFoundException(); } - return new SMExportResponseModel(projects, secrets.Select(s => s.Secret)); + return new SMExportResponseModel(projects.Select(p => p.Project), secrets.Select(s => s.Secret)); } [HttpPost("sm/{organizationId}/import")] diff --git a/src/Api/SecretsManager/Models/Response/ProjectPermissionDetailsResponseModel.cs b/src/Api/SecretsManager/Models/Response/ProjectPermissionDetailsResponseModel.cs deleted file mode 100644 index 162ce2205..000000000 --- a/src/Api/SecretsManager/Models/Response/ProjectPermissionDetailsResponseModel.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Bit.Core.SecretsManager.Entities; - -namespace Bit.Api.SecretsManager.Models.Response; - -public class ProjectPermissionDetailsResponseModel : ProjectResponseModel -{ - private const string _objectName = "projectPermissionDetails"; - - public ProjectPermissionDetailsResponseModel(Project project, bool read, bool write, string obj = _objectName) : base(project, obj) - { - Read = read; - Write = write; - } - - public ProjectPermissionDetailsResponseModel() - { - } - - public bool Read { get; set; } - - public bool Write { get; set; } -} diff --git a/src/Api/SecretsManager/Models/Response/ProjectResponseModel.cs b/src/Api/SecretsManager/Models/Response/ProjectResponseModel.cs index bf7507915..b740c6646 100644 --- a/src/Api/SecretsManager/Models/Response/ProjectResponseModel.cs +++ b/src/Api/SecretsManager/Models/Response/ProjectResponseModel.cs @@ -1,5 +1,6 @@ using Bit.Core.Models.Api; using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Models.Data; namespace Bit.Api.SecretsManager.Models.Response; @@ -7,7 +8,7 @@ public class ProjectResponseModel : ResponseModel { private const string _objectName = "project"; - public ProjectResponseModel(Project project, string obj = _objectName) + public ProjectResponseModel(Project project, bool read, bool write, string obj = _objectName) : base(obj) { if (project == null) @@ -20,6 +21,25 @@ public class ProjectResponseModel : ResponseModel Name = project.Name; CreationDate = project.CreationDate; RevisionDate = project.RevisionDate; + Read = read; + Write = write; + } + + public ProjectResponseModel(ProjectPermissionDetails projectDetails, string obj = _objectName) + : base(obj) + { + if (projectDetails == null) + { + throw new ArgumentNullException(nameof(projectDetails)); + } + + Id = projectDetails.Project.Id.ToString(); + OrganizationId = projectDetails.Project.OrganizationId.ToString(); + Name = projectDetails.Project.Name; + CreationDate = projectDetails.Project.CreationDate; + RevisionDate = projectDetails.Project.RevisionDate; + Read = projectDetails.Read; + Write = projectDetails.Write; } public ProjectResponseModel() : base(_objectName) @@ -36,5 +56,7 @@ public class ProjectResponseModel : ResponseModel public DateTime RevisionDate { get; set; } - public IEnumerable Secrets { get; set; } + public bool Read { get; set; } + + public bool Write { get; set; } } diff --git a/src/Core/SecretsManager/Models/Data/ProjectPermissionDetails.cs b/src/Core/SecretsManager/Models/Data/ProjectPermissionDetails.cs index 435b95985..23c01a1fd 100644 --- a/src/Core/SecretsManager/Models/Data/ProjectPermissionDetails.cs +++ b/src/Core/SecretsManager/Models/Data/ProjectPermissionDetails.cs @@ -2,8 +2,9 @@ namespace Bit.Core.SecretsManager.Models.Data; -public class ProjectPermissionDetails : Project +public class ProjectPermissionDetails { + public Project Project { get; set; } public bool Read { get; set; } public bool Write { get; set; } } diff --git a/src/Core/SecretsManager/Models/Data/SecretPermissionDetails.cs b/src/Core/SecretsManager/Models/Data/SecretPermissionDetails.cs index 3a3c8d29c..c5e15e25a 100644 --- a/src/Core/SecretsManager/Models/Data/SecretPermissionDetails.cs +++ b/src/Core/SecretsManager/Models/Data/SecretPermissionDetails.cs @@ -4,7 +4,7 @@ namespace Bit.Core.SecretsManager.Models.Data; public class SecretPermissionDetails { - public Secret Secret; + public Secret Secret { get; set; } public bool Read { get; set; } public bool Write { get; set; } } diff --git a/src/Core/SecretsManager/Repositories/IProjectRepository.cs b/src/Core/SecretsManager/Repositories/IProjectRepository.cs index 7ad76077f..e425df6f4 100644 --- a/src/Core/SecretsManager/Repositories/IProjectRepository.cs +++ b/src/Core/SecretsManager/Repositories/IProjectRepository.cs @@ -1,11 +1,12 @@ using Bit.Core.Enums; using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Models.Data; namespace Bit.Core.SecretsManager.Repositories; public interface IProjectRepository { - Task> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType); + Task> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType); Task> GetManyByOrganizationIdWriteAccessAsync(Guid organizationId, Guid userId, AccessClientType accessType); Task> GetManyWithSecretsByIds(IEnumerable ids); Task GetByIdAsync(Guid id); @@ -13,10 +14,6 @@ public interface IProjectRepository Task ReplaceAsync(Project project); Task DeleteManyByIdAsync(IEnumerable ids); Task> ImportAsync(IEnumerable projects); - Task UserHasReadAccessToProject(Guid id, Guid userId); - Task UserHasWriteAccessToProject(Guid id, Guid userId); - Task ServiceAccountHasWriteAccessToProject(Guid id, Guid userId); - Task ServiceAccountHasReadAccessToProject(Guid id, Guid userId); Task<(bool Read, bool Write)> AccessToProjectAsync(Guid id, Guid userId, AccessClientType accessType); Task ProjectsAreInOrganization(List projectIds, Guid organizationId); } diff --git a/test/Api.IntegrationTest/SecretsManager/Controllers/ProjectsControllerTests.cs b/test/Api.IntegrationTest/SecretsManager/Controllers/ProjectsControllerTests.cs index 1b0d97626..2dd790397 100644 --- a/test/Api.IntegrationTest/SecretsManager/Controllers/ProjectsControllerTests.cs +++ b/test/Api.IntegrationTest/SecretsManager/Controllers/ProjectsControllerTests.cs @@ -304,7 +304,7 @@ public class ProjectsControllerTests : IClassFixture, IAs var response = await _client.GetAsync($"/projects/{project.Id}"); response.EnsureSuccessStatusCode(); - var result = await response.Content.ReadFromJsonAsync(); + var result = await response.Content.ReadFromJsonAsync(); Assert.Equal(project.Name, result!.Name); Assert.Equal(project.RevisionDate, result.RevisionDate); Assert.Equal(project.CreationDate, result.CreationDate); diff --git a/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs b/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs index 6a8b4f829..9b19ff0f1 100644 --- a/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs +++ b/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs @@ -255,7 +255,7 @@ public class SecretsControllerTests : IClassFixture, IAsy Name = _mockEncryptedString }); - var orgUserId = (Guid)orgAdminUser.UserId; + var orgUserId = (Guid)orgAdminUser.UserId!; if (permissionType == PermissionType.RunAsUserWithPermission) { @@ -270,7 +270,7 @@ public class SecretsControllerTests : IClassFixture, IAsy GrantedProjectId = project.Id, OrganizationUserId = orgUser.Id , Read = true, Write = true, }, }; - orgUserId = (Guid)orgUser.UserId; + orgUserId = (Guid)orgUser.UserId!; await _accessPolicyRepository.CreateManyAsync(accessPolicies); } diff --git a/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs b/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs index b1855d569..ddf503774 100644 --- a/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs +++ b/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs @@ -102,11 +102,13 @@ public class AccessPoliciesControllerTests { case PermissionType.RunAsAdmin: SetupAdmin(sutProvider, data.OrganizationId); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.NoAccessCheck) + .Returns((true, true)); break; case PermissionType.RunAsUserWithPermission: SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) - .ReturnsForAnyArgs(true); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) + .Returns((true, true)); break; } @@ -129,8 +131,8 @@ public class AccessPoliciesControllerTests { SetupUserWithoutPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) - .ReturnsForAnyArgs(false); + sutProvider.GetDependency().AccessToProjectAsync(default, default, default) + .Returns((false, false)); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectAccessPoliciesAsync(id)); @@ -153,11 +155,13 @@ public class AccessPoliciesControllerTests { case PermissionType.RunAsAdmin: SetupAdmin(sutProvider, data.OrganizationId); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.NoAccessCheck) + .Returns((true, true)); break; case PermissionType.RunAsUserWithPermission: SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) - .ReturnsForAnyArgs(true); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) + .Returns((true, true)); break; } @@ -184,8 +188,8 @@ public class AccessPoliciesControllerTests { SetupUserWithoutPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) - .ReturnsForAnyArgs(false); + sutProvider.GetDependency().AccessToProjectAsync(default, default, default) + .Returns((false, false)); sutProvider.GetDependency().GetManyByGrantedProjectIdAsync(default, default) .ReturnsForAnyArgs(new List { resultAccessPolicy }); diff --git a/test/Api.Test/SecretsManager/Controllers/ProjectsControllerTests.cs b/test/Api.Test/SecretsManager/Controllers/ProjectsControllerTests.cs index 42ae51f95..ab2643f3f 100644 --- a/test/Api.Test/SecretsManager/Controllers/ProjectsControllerTests.cs +++ b/test/Api.Test/SecretsManager/Controllers/ProjectsControllerTests.cs @@ -6,6 +6,7 @@ using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Commands.Projects.Interfaces; using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Models.Data; using Bit.Core.SecretsManager.Repositories; using Bit.Core.Services; using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; @@ -88,7 +89,7 @@ public class ProjectsControllerTests } sutProvider.GetDependency().GetManyByOrganizationIdAsync(default, default, default) - .ReturnsForAnyArgs(new List { mockProject }); + .ReturnsForAnyArgs(new List { new() { Project = mockProject, Read = true, Write = true } }); var result = await sutProvider.Sut.ListByOrganizationAsync(data); @@ -193,8 +194,8 @@ public class ProjectsControllerTests break; case PermissionType.RunAsUserWithPermission: SetupUserWithPermission(sutProvider, orgId); - sutProvider.GetDependency() - .UserHasReadAccessToProject(Arg.Is(data), Arg.Any()).ReturnsForAnyArgs(true); + sutProvider.GetDependency().AccessToProjectAsync(default, default, default) + .Returns((true, true)); break; } @@ -216,8 +217,8 @@ public class ProjectsControllerTests Guid data) { SetupUserWithPermission(sutProvider, orgId); - sutProvider.GetDependency().UserHasReadAccessToProject(Arg.Is(data), Arg.Any()) - .ReturnsForAnyArgs(false); + sutProvider.GetDependency().AccessToProjectAsync(default, default, default) + .Returns((false, false)); sutProvider.GetDependency().GetByIdAsync(Arg.Is(data)) .ReturnsForAnyArgs(new Project { Id = data, OrganizationId = orgId }); diff --git a/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs b/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs index 54e7bcf90..8922b392d 100644 --- a/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs +++ b/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs @@ -61,7 +61,8 @@ public class SecretsControllerTests { resultSecret.Projects = new List() { mockProject }; sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().UserHasReadAccessToProject(mockProject.Id, userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(default, default, default) + .Returns((true, true)); } @@ -107,11 +108,14 @@ public class SecretsControllerTests { resultSecret.OrganizationId = organizationId; sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.NoAccessCheck) + .Returns((true, true)); } else { sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().UserHasReadAccessToProject(mockProject.Id, userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) + .Returns((true, true)); } await sutProvider.Sut.GetAsync(resultSecret.Id); @@ -142,7 +146,8 @@ public class SecretsControllerTests { resultSecret.Projects = new List() { mockProject }; sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().UserHasReadAccessToProject(mockProject.Id, userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) + .Returns((true, true)); } sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(true); @@ -174,7 +179,8 @@ public class SecretsControllerTests { data.ProjectIds = new Guid[] { mockProject.Id }; sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().UserHasReadAccessToProject(mockProject.Id, userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(default, default, default) + .Returns((true, true)); } var resultSecret = data.ToSecret(secretId); @@ -200,7 +206,8 @@ public class SecretsControllerTests { data.FirstOrDefault().Projects = new List() { mockProject }; sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().UserHasReadAccessToProject(mockProject.Id, userId).Returns(true); + sutProvider.GetDependency().AccessToProjectAsync(default, default, default) + .Returns((true, true)); }