1
0
mirror of https://github.com/bitwarden/server.git synced 2024-12-25 17:27:45 +01:00

[SM-581] Adding support for warning dialogs (#2762)

* Adding support for warning dialogs

* Swap to repository layer implementation
This commit is contained in:
Thomas Avery 2023-03-06 11:31:56 -06:00 committed by GitHub
parent f8cbd4ef7d
commit de559e80f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 80 additions and 31 deletions

View File

@ -157,7 +157,7 @@ public class AccessPolicyRepository : BaseEntityFrameworkRepository, IAccessPoli
}
}
public async Task<IEnumerable<Core.SecretsManager.Entities.BaseAccessPolicy>> GetManyByGrantedProjectIdAsync(Guid id)
public async Task<IEnumerable<Core.SecretsManager.Entities.BaseAccessPolicy>> GetManyByGrantedProjectIdAsync(Guid id, Guid userId)
{
using var scope = ServiceScopeFactory.CreateScope();
var dbContext = GetDatabaseContext(scope);
@ -169,11 +169,19 @@ public class AccessPolicyRepository : BaseEntityFrameworkRepository, IAccessPoli
.Include(ap => ((UserProjectAccessPolicy)ap).OrganizationUser.User)
.Include(ap => ((GroupProjectAccessPolicy)ap).Group)
.Include(ap => ((ServiceAccountProjectAccessPolicy)ap).ServiceAccount)
.Select(ap => new
{
ap,
CurrentUserInGroup = ap is GroupProjectAccessPolicy &&
((GroupProjectAccessPolicy)ap).Group.GroupUsers.Any(g =>
g.OrganizationUser.User.Id == userId),
})
.ToListAsync();
return entities.Select(MapToCore);
return entities.Select(e => MapToCore(e.ap, e.CurrentUserInGroup));
}
public async Task<IEnumerable<Core.SecretsManager.Entities.BaseAccessPolicy>> GetManyByGrantedServiceAccountIdAsync(Guid id)
public async Task<IEnumerable<Core.SecretsManager.Entities.BaseAccessPolicy>> GetManyByGrantedServiceAccountIdAsync(Guid id, Guid userId)
{
using var scope = ServiceScopeFactory.CreateScope();
var dbContext = GetDatabaseContext(scope);
@ -183,9 +191,16 @@ public class AccessPolicyRepository : BaseEntityFrameworkRepository, IAccessPoli
((GroupServiceAccountAccessPolicy)ap).GrantedServiceAccountId == id)
.Include(ap => ((UserServiceAccountAccessPolicy)ap).OrganizationUser.User)
.Include(ap => ((GroupServiceAccountAccessPolicy)ap).Group)
.Select(ap => new
{
ap,
CurrentUserInGroup = ap is GroupServiceAccountAccessPolicy &&
((GroupServiceAccountAccessPolicy)ap).Group.GroupUsers.Any(g =>
g.OrganizationUser.User.Id == userId),
})
.ToListAsync();
return entities.Select(MapToCore);
return entities.Select(e => MapToCore(e.ap, e.CurrentUserInGroup));
}
public async Task DeleteAsync(Guid id)
@ -237,4 +252,26 @@ public class AccessPolicyRepository : BaseEntityFrameworkRepository, IAccessPoli
.Map<Core.SecretsManager.Entities.GroupServiceAccountAccessPolicy>(ap),
_ => throw new ArgumentException("Unsupported access policy type"),
};
private Core.SecretsManager.Entities.BaseAccessPolicy MapToCore(
BaseAccessPolicy baseAccessPolicyEntity, bool currentUserInGroup)
{
switch (baseAccessPolicyEntity)
{
case GroupProjectAccessPolicy ap:
{
var mapped = Mapper.Map<Core.SecretsManager.Entities.GroupProjectAccessPolicy>(ap);
mapped.CurrentUserInGroup = currentUserInGroup;
return mapped;
}
case GroupServiceAccountAccessPolicy ap:
{
var mapped = Mapper.Map<Core.SecretsManager.Entities.GroupServiceAccountAccessPolicy>(ap);
mapped.CurrentUserInGroup = currentUserInGroup;
return mapped;
}
default:
return MapToCore(baseAccessPolicyEntity);
}
}
}

View File

@ -73,7 +73,7 @@ public class AccessPoliciesController : Controller
var (accessClient, userId) = await GetAccessClientTypeAsync(project.OrganizationId);
var policies = request.ToBaseAccessPoliciesForProject(id);
await _createAccessPoliciesCommand.CreateManyAsync(policies, userId, accessClient);
var results = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(id);
var results = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(id, userId);
return new ProjectAccessPoliciesResponseModel(results);
}
@ -81,9 +81,8 @@ public class AccessPoliciesController : Controller
public async Task<ProjectAccessPoliciesResponseModel> GetProjectAccessPoliciesAsync([FromRoute] Guid id)
{
var project = await _projectRepository.GetByIdAsync(id);
await CheckUserHasWriteAccessToProjectAsync(project);
var results = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(id);
var (_, userId) = await CheckUserHasWriteAccessToProjectAsync(project);
var results = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(id, userId);
return new ProjectAccessPoliciesResponseModel(results);
}
@ -106,7 +105,7 @@ public class AccessPoliciesController : Controller
var (accessClient, userId) = await GetAccessClientTypeAsync(serviceAccount.OrganizationId);
var policies = request.ToBaseAccessPoliciesForServiceAccount(id);
await _createAccessPoliciesCommand.CreateManyAsync(policies, userId, accessClient);
var results = await _accessPolicyRepository.GetManyByGrantedServiceAccountIdAsync(id);
var results = await _accessPolicyRepository.GetManyByGrantedServiceAccountIdAsync(id, userId);
return new ServiceAccountAccessPoliciesResponseModel(results);
}
@ -115,9 +114,8 @@ public class AccessPoliciesController : Controller
[FromRoute] Guid id)
{
var serviceAccount = await _serviceAccountRepository.GetByIdAsync(id);
await CheckUserHasWriteAccessToServiceAccountAsync(serviceAccount);
var results = await _accessPolicyRepository.GetManyByGrantedServiceAccountIdAsync(id);
var (_, userId) = await CheckUserHasWriteAccessToServiceAccountAsync(serviceAccount);
var results = await _accessPolicyRepository.GetManyByGrantedServiceAccountIdAsync(id, userId);
return new ServiceAccountAccessPoliciesResponseModel(results);
}
@ -244,7 +242,7 @@ public class AccessPoliciesController : Controller
return new ListResponseModel<PotentialGranteeResponseModel>(projectResponses);
}
private async Task CheckUserHasWriteAccessToProjectAsync(Project project)
private async Task<(AccessClientType AccessClientType, Guid UserId)> CheckUserHasWriteAccessToProjectAsync(Project project)
{
if (project == null)
{
@ -263,9 +261,10 @@ public class AccessPoliciesController : Controller
{
throw new NotFoundException();
}
return (accessClient, userId);
}
private async Task CheckUserHasWriteAccessToServiceAccountAsync(ServiceAccount serviceAccount)
private async Task<(AccessClientType AccessClientType, Guid UserId)> CheckUserHasWriteAccessToServiceAccountAsync(ServiceAccount serviceAccount)
{
if (serviceAccount == null)
{
@ -285,6 +284,7 @@ public class AccessPoliciesController : Controller
{
throw new NotFoundException();
}
return (accessClient, userId);
}
private async Task<(AccessClientType AccessClientType, Guid UserId)> GetAccessClientTypeAsync(Guid organizationId)

View File

@ -37,6 +37,7 @@ public class UserProjectAccessPolicyResponseModel : BaseAccessPolicyResponseMode
OrganizationUserId = accessPolicy.OrganizationUserId;
GrantedProjectId = accessPolicy.GrantedProjectId;
OrganizationUserName = GetUserDisplayName(accessPolicy.User);
UserId = accessPolicy.User?.Id;
}
public UserProjectAccessPolicyResponseModel() : base(new UserProjectAccessPolicy(), _objectName)
@ -45,6 +46,7 @@ public class UserProjectAccessPolicyResponseModel : BaseAccessPolicyResponseMode
public Guid? OrganizationUserId { get; set; }
public string? OrganizationUserName { get; set; }
public Guid? UserId { get; set; }
public Guid? GrantedProjectId { get; set; }
}
@ -58,6 +60,7 @@ public class UserServiceAccountAccessPolicyResponseModel : BaseAccessPolicyRespo
OrganizationUserId = accessPolicy.OrganizationUserId;
GrantedServiceAccountId = accessPolicy.GrantedServiceAccountId;
OrganizationUserName = GetUserDisplayName(accessPolicy.User);
UserId = accessPolicy.User?.Id;
}
public UserServiceAccountAccessPolicyResponseModel() : base(new UserServiceAccountAccessPolicy(), _objectName)
@ -66,6 +69,7 @@ public class UserServiceAccountAccessPolicyResponseModel : BaseAccessPolicyRespo
public Guid? OrganizationUserId { get; set; }
public string? OrganizationUserName { get; set; }
public Guid? UserId { get; set; }
public Guid? GrantedServiceAccountId { get; set; }
}
@ -79,6 +83,7 @@ public class GroupProjectAccessPolicyResponseModel : BaseAccessPolicyResponseMod
GroupId = accessPolicy.GroupId;
GrantedProjectId = accessPolicy.GrantedProjectId;
GroupName = accessPolicy.Group?.Name;
CurrentUserInGroup = accessPolicy.CurrentUserInGroup;
}
public GroupProjectAccessPolicyResponseModel() : base(new GroupProjectAccessPolicy(), _objectName)
@ -87,6 +92,7 @@ public class GroupProjectAccessPolicyResponseModel : BaseAccessPolicyResponseMod
public Guid? GroupId { get; set; }
public string? GroupName { get; set; }
public bool? CurrentUserInGroup { get; set; }
public Guid? GrantedProjectId { get; set; }
}
@ -100,6 +106,7 @@ public class GroupServiceAccountAccessPolicyResponseModel : BaseAccessPolicyResp
GroupId = accessPolicy.GroupId;
GroupName = accessPolicy.Group?.Name;
GrantedServiceAccountId = accessPolicy.GrantedServiceAccountId;
CurrentUserInGroup = accessPolicy.CurrentUserInGroup;
}
public GroupServiceAccountAccessPolicyResponseModel() : base(new GroupServiceAccountAccessPolicy(), _objectName)
@ -109,6 +116,7 @@ public class GroupServiceAccountAccessPolicyResponseModel : BaseAccessPolicyResp
public Guid? GroupId { get; set; }
public string? GroupName { get; set; }
public Guid? GrantedServiceAccountId { get; set; }
public bool? CurrentUserInGroup { get; set; }
}
public class ServiceAccountProjectAccessPolicyResponseModel : BaseAccessPolicyResponseModel

View File

@ -41,6 +41,7 @@ public class GroupProjectAccessPolicy : BaseAccessPolicy
{
public Guid? GroupId { get; set; }
public Group? Group { get; set; }
public bool? CurrentUserInGroup { get; set; }
public Guid? GrantedProjectId { get; set; }
public Project? GrantedProject { get; set; }
}
@ -49,6 +50,7 @@ public class GroupServiceAccountAccessPolicy : BaseAccessPolicy
{
public Guid? GroupId { get; set; }
public Group? Group { get; set; }
public bool? CurrentUserInGroup { get; set; }
public Guid? GrantedServiceAccountId { get; set; }
public ServiceAccount? GrantedServiceAccount { get; set; }
}

View File

@ -9,8 +9,8 @@ public interface IAccessPolicyRepository
Task<List<BaseAccessPolicy>> CreateManyAsync(List<BaseAccessPolicy> baseAccessPolicies);
Task<bool> AccessPolicyExists(BaseAccessPolicy baseAccessPolicy);
Task<BaseAccessPolicy?> GetByIdAsync(Guid id);
Task<IEnumerable<BaseAccessPolicy>> GetManyByGrantedProjectIdAsync(Guid id);
Task<IEnumerable<BaseAccessPolicy>> GetManyByGrantedServiceAccountIdAsync(Guid id);
Task<IEnumerable<BaseAccessPolicy>> GetManyByGrantedProjectIdAsync(Guid id, Guid userId);
Task<IEnumerable<BaseAccessPolicy>> GetManyByGrantedServiceAccountIdAsync(Guid id, Guid userId);
Task<IEnumerable<BaseAccessPolicy>> GetManyByServiceAccountIdAsync(Guid id, Guid userId,
AccessClientType accessType);
Task ReplaceAsync(BaseAccessPolicy baseAccessPolicy);

View File

@ -123,12 +123,14 @@ public class ProjectsControllerTest : IClassFixture<ApiApplicationFactory>, IAsy
var (org, adminOrgUser) = await _organizationHelper.Initialize(true, true);
await LoginAsync(_email);
var orgUserId = adminOrgUser.Id;
var currentUserId = adminOrgUser.UserId!.Value;
if (permissionType == PermissionType.RunAsUserWithPermission)
{
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
orgUserId = orgUser.Id;
currentUserId = orgUser.UserId!.Value;
}
var request = new ProjectCreateRequestModel { Name = _mockEncryptedString };
@ -150,7 +152,7 @@ public class ProjectsControllerTest : IClassFixture<ApiApplicationFactory>, IAsy
Assert.Null(createdProject.DeletedDate);
// Check permissions have been bootstrapped.
var accessPolicies = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(createdProject.Id);
var accessPolicies = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(createdProject.Id, currentUserId);
Assert.NotNull(accessPolicies);
var ap = (UserProjectAccessPolicy)accessPolicies.First();
Assert.Equal(createdProject.Id, ap.GrantedProjectId);

View File

@ -138,7 +138,7 @@ public class ServiceAccountsControllerTest : IClassFixture<ApiApplicationFactory
[Fact]
public async Task Create_Admin_Success()
{
var (org, _) = await _organizationHelper.Initialize(true, true);
var (org, orgUser) = await _organizationHelper.Initialize(true, true);
await LoginAsync(_email);
var request = new ServiceAccountCreateRequestModel { Name = _mockEncryptedString };
@ -159,7 +159,7 @@ public class ServiceAccountsControllerTest : IClassFixture<ApiApplicationFactory
AssertHelper.AssertRecent(createdServiceAccount.CreationDate);
// Check permissions have been bootstrapped.
var accessPolicies = await _accessPolicyRepository.GetManyByGrantedServiceAccountIdAsync(createdServiceAccount.Id);
var accessPolicies = await _accessPolicyRepository.GetManyByGrantedServiceAccountIdAsync(createdServiceAccount.Id, orgUser.UserId!.Value);
Assert.NotNull(accessPolicies);
var ap = accessPolicies!.First();
Assert.True(ap.Read);

View File

@ -113,7 +113,7 @@ public class AccessPoliciesControllerTests
var result = await sutProvider.Sut.GetProjectAccessPoliciesAsync(id);
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
.GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
.GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any<Guid>());
Assert.Empty(result.GroupAccessPolicies);
Assert.Empty(result.UserAccessPolicies);
@ -135,7 +135,7 @@ public class AccessPoliciesControllerTests
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetProjectAccessPoliciesAsync(id));
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
.GetManyByGrantedProjectIdAsync(Arg.Any<Guid>());
.GetManyByGrantedProjectIdAsync(Arg.Any<Guid>(), Arg.Any<Guid>());
}
[Theory]
@ -161,13 +161,13 @@ public class AccessPoliciesControllerTests
break;
}
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedProjectIdAsync(default)
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedProjectIdAsync(default, default)
.ReturnsForAnyArgs(new List<BaseAccessPolicy> { resultAccessPolicy });
var result = await sutProvider.Sut.GetProjectAccessPoliciesAsync(id);
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
.GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
.GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any<Guid>());
Assert.Empty(result.GroupAccessPolicies);
Assert.NotEmpty(result.UserAccessPolicies);
@ -187,13 +187,13 @@ public class AccessPoliciesControllerTests
sutProvider.GetDependency<IProjectRepository>().UserHasWriteAccessToProject(default, default)
.ReturnsForAnyArgs(false);
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedProjectIdAsync(default)
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedProjectIdAsync(default, default)
.ReturnsForAnyArgs(new List<BaseAccessPolicy> { resultAccessPolicy });
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetProjectAccessPoliciesAsync(id));
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
.GetManyByGrantedProjectIdAsync(Arg.Any<Guid>());
.GetManyByGrantedProjectIdAsync(Arg.Any<Guid>(), Arg.Any<Guid>());
}
[Theory]
@ -222,7 +222,7 @@ public class AccessPoliciesControllerTests
var result = await sutProvider.Sut.GetServiceAccountAccessPoliciesAsync(id);
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
.GetManyByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
.GetManyByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any<Guid>());
Assert.Empty(result.UserAccessPolicies);
Assert.Empty(result.GroupAccessPolicies);
@ -243,7 +243,7 @@ public class AccessPoliciesControllerTests
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetServiceAccountAccessPoliciesAsync(id));
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
.GetManyByGrantedServiceAccountIdAsync(Arg.Any<Guid>());
.GetManyByGrantedServiceAccountIdAsync(Arg.Any<Guid>(), Arg.Any<Guid>());
}
[Theory]
@ -270,13 +270,13 @@ public class AccessPoliciesControllerTests
break;
}
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedServiceAccountIdAsync(default)
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedServiceAccountIdAsync(default, default)
.ReturnsForAnyArgs(new List<BaseAccessPolicy> { resultAccessPolicy });
var result = await sutProvider.Sut.GetServiceAccountAccessPoliciesAsync(id);
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
.GetManyByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
.GetManyByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any<Guid>());
Assert.Empty(result.GroupAccessPolicies);
Assert.NotEmpty(result.UserAccessPolicies);
@ -295,13 +295,13 @@ public class AccessPoliciesControllerTests
sutProvider.GetDependency<IServiceAccountRepository>().UserHasWriteAccessToServiceAccount(default, default)
.ReturnsForAnyArgs(false);
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedServiceAccountIdAsync(default)
sutProvider.GetDependency<IAccessPolicyRepository>().GetManyByGrantedServiceAccountIdAsync(default, default)
.ReturnsForAnyArgs(new List<BaseAccessPolicy> { resultAccessPolicy });
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetServiceAccountAccessPoliciesAsync(id));
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
.GetManyByGrantedServiceAccountIdAsync(Arg.Any<Guid>());
.GetManyByGrantedServiceAccountIdAsync(Arg.Any<Guid>(), Arg.Any<Guid>());
}
[Theory]