mirror of
https://github.com/bitwarden/server.git
synced 2025-02-12 01:11:22 +01:00
* Added CQRS pattern * Added the GetManyByUserIdAsync signature to the repositiory * Added sql sproc Created user defined type to hold status Created migration file * Added ef core query * Added absract and concrete implementation for GetManyByUserIdStatusAsync * Added integration tests * Updated params to status * Implemented new query to utilize repository method * Added controller for the security task endpoint * Fixed lint issues * Added documentation * simplified to require single status modified script to check for users with edit rights * Updated ef core query * Added new assertions * simplified to require single status * fixed formatting * Fixed sql script * Removed default null * Added security tasks feature flag
227 lines
8.1 KiB
C#
227 lines
8.1 KiB
C#
using Bit.Core.AdminConsole.Entities;
|
|
using Bit.Core.Billing.Enums;
|
|
using Bit.Core.Entities;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Models.Data;
|
|
using Bit.Core.Repositories;
|
|
using Bit.Core.Vault.Entities;
|
|
using Bit.Core.Vault.Enums;
|
|
using Bit.Core.Vault.Repositories;
|
|
using Bit.Infrastructure.IntegrationTest.Comparers;
|
|
using Xunit;
|
|
|
|
namespace Bit.Infrastructure.IntegrationTest.Vault.Repositories;
|
|
|
|
public class SecurityTaskRepositoryTests
|
|
{
|
|
[DatabaseTheory, DatabaseData]
|
|
public async Task CreateAsync(
|
|
IOrganizationRepository organizationRepository,
|
|
ICipherRepository cipherRepository,
|
|
ISecurityTaskRepository securityTaskRepository)
|
|
{
|
|
var organization = await organizationRepository.CreateAsync(new Organization
|
|
{
|
|
Name = "Test Org",
|
|
PlanType = PlanType.EnterpriseAnnually,
|
|
Plan = "Test Plan",
|
|
BillingEmail = "billing@email.com"
|
|
});
|
|
|
|
var cipher = await cipherRepository.CreateAsync(new Cipher
|
|
{
|
|
Type = CipherType.Login,
|
|
OrganizationId = organization.Id,
|
|
Data = "",
|
|
});
|
|
|
|
var task = await securityTaskRepository.CreateAsync(new SecurityTask
|
|
{
|
|
OrganizationId = organization.Id,
|
|
CipherId = cipher.Id,
|
|
Status = SecurityTaskStatus.Pending,
|
|
Type = SecurityTaskType.UpdateAtRiskCredential,
|
|
});
|
|
|
|
Assert.NotNull(task);
|
|
}
|
|
|
|
[DatabaseTheory, DatabaseData]
|
|
public async Task ReadByIdAsync(
|
|
IOrganizationRepository organizationRepository,
|
|
ICipherRepository cipherRepository,
|
|
ISecurityTaskRepository securityTaskRepository)
|
|
{
|
|
var organization = await organizationRepository.CreateAsync(new Organization
|
|
{
|
|
Name = "Test Org",
|
|
PlanType = PlanType.EnterpriseAnnually,
|
|
Plan = "Test Plan",
|
|
BillingEmail = "billing@email.com"
|
|
});
|
|
|
|
var cipher = await cipherRepository.CreateAsync(new Cipher
|
|
{
|
|
Type = CipherType.Login,
|
|
OrganizationId = organization.Id,
|
|
Data = "",
|
|
});
|
|
|
|
var task = await securityTaskRepository.CreateAsync(new SecurityTask
|
|
{
|
|
OrganizationId = organization.Id,
|
|
CipherId = cipher.Id,
|
|
Status = SecurityTaskStatus.Pending,
|
|
Type = SecurityTaskType.UpdateAtRiskCredential,
|
|
});
|
|
|
|
Assert.NotNull(task);
|
|
|
|
var readTask = await securityTaskRepository.GetByIdAsync(task.Id);
|
|
|
|
Assert.NotNull(readTask);
|
|
Assert.Equal(task.Id, readTask.Id);
|
|
Assert.Equal(task.Status, readTask.Status);
|
|
}
|
|
|
|
[DatabaseTheory, DatabaseData]
|
|
public async Task UpdateAsync(
|
|
IOrganizationRepository organizationRepository,
|
|
ICipherRepository cipherRepository,
|
|
ISecurityTaskRepository securityTaskRepository)
|
|
{
|
|
var organization = await organizationRepository.CreateAsync(new Organization
|
|
{
|
|
Name = "Test Org",
|
|
PlanType = PlanType.EnterpriseAnnually,
|
|
Plan = "Test Plan",
|
|
BillingEmail = "billing@email.com"
|
|
});
|
|
|
|
var cipher = await cipherRepository.CreateAsync(new Cipher
|
|
{
|
|
Type = CipherType.Login,
|
|
OrganizationId = organization.Id,
|
|
Data = "",
|
|
});
|
|
|
|
var task = await securityTaskRepository.CreateAsync(new SecurityTask
|
|
{
|
|
OrganizationId = organization.Id,
|
|
CipherId = cipher.Id,
|
|
Status = SecurityTaskStatus.Pending,
|
|
Type = SecurityTaskType.UpdateAtRiskCredential,
|
|
});
|
|
|
|
Assert.NotNull(task);
|
|
|
|
task.Status = SecurityTaskStatus.Completed;
|
|
await securityTaskRepository.ReplaceAsync(task);
|
|
|
|
var updatedTask = await securityTaskRepository.GetByIdAsync(task.Id);
|
|
|
|
Assert.NotNull(updatedTask);
|
|
Assert.Equal(task.Id, updatedTask.Id);
|
|
Assert.Equal(SecurityTaskStatus.Completed, updatedTask.Status);
|
|
}
|
|
|
|
[DatabaseTheory, DatabaseData]
|
|
public async Task GetManyByUserIdAsync_ReturnsExpectedTasks(
|
|
IUserRepository userRepository,
|
|
IOrganizationRepository organizationRepository,
|
|
ICipherRepository cipherRepository,
|
|
ISecurityTaskRepository securityTaskRepository,
|
|
IOrganizationUserRepository organizationUserRepository,
|
|
ICollectionRepository collectionRepository)
|
|
{
|
|
var user = await userRepository.CreateAsync(new User
|
|
{
|
|
Name = "Test User",
|
|
Email = $"test+{Guid.NewGuid()}@email.com",
|
|
ApiKey = "TEST",
|
|
SecurityStamp = "stamp",
|
|
});
|
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization
|
|
{
|
|
Name = "Test Org",
|
|
PlanType = PlanType.EnterpriseAnnually,
|
|
Plan = "Test Plan",
|
|
BillingEmail = "billing@email.com"
|
|
});
|
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
|
|
{
|
|
OrganizationId = organization.Id,
|
|
UserId = user.Id,
|
|
Status = OrganizationUserStatusType.Confirmed
|
|
});
|
|
|
|
var collection = await collectionRepository.CreateAsync(new Collection
|
|
{
|
|
OrganizationId = organization.Id,
|
|
Name = "Test Collection 1",
|
|
});
|
|
|
|
var collection2 = await collectionRepository.CreateAsync(new Collection
|
|
{
|
|
OrganizationId = organization.Id,
|
|
Name = "Test Collection 2",
|
|
});
|
|
|
|
var cipher1 = new Cipher { Type = CipherType.Login, OrganizationId = organization.Id, Data = "", };
|
|
await cipherRepository.CreateAsync(cipher1, [collection.Id, collection2.Id]);
|
|
|
|
var cipher2 = new Cipher { Type = CipherType.Login, OrganizationId = organization.Id, Data = "", };
|
|
await cipherRepository.CreateAsync(cipher2, [collection.Id]);
|
|
|
|
var task1 = await securityTaskRepository.CreateAsync(new SecurityTask
|
|
{
|
|
OrganizationId = organization.Id,
|
|
CipherId = cipher1.Id,
|
|
Status = SecurityTaskStatus.Pending,
|
|
Type = SecurityTaskType.UpdateAtRiskCredential,
|
|
});
|
|
|
|
var task2 = await securityTaskRepository.CreateAsync(new SecurityTask
|
|
{
|
|
OrganizationId = organization.Id,
|
|
CipherId = cipher2.Id,
|
|
Status = SecurityTaskStatus.Completed,
|
|
Type = SecurityTaskType.UpdateAtRiskCredential,
|
|
});
|
|
|
|
var task3 = await securityTaskRepository.CreateAsync(new SecurityTask
|
|
{
|
|
OrganizationId = organization.Id,
|
|
CipherId = cipher2.Id,
|
|
Status = SecurityTaskStatus.Pending,
|
|
Type = SecurityTaskType.UpdateAtRiskCredential,
|
|
});
|
|
|
|
await collectionRepository.UpdateUsersAsync(collection.Id,
|
|
new List<CollectionAccessSelection>
|
|
{
|
|
new() {Id = orgUser.Id, ReadOnly = false, HidePasswords = false, Manage = true}
|
|
});
|
|
|
|
var allTasks = await securityTaskRepository.GetManyByUserIdStatusAsync(user.Id);
|
|
Assert.Equal(3, allTasks.Count);
|
|
Assert.Contains(task1, allTasks, new SecurityTaskComparer());
|
|
Assert.Contains(task2, allTasks, new SecurityTaskComparer());
|
|
Assert.Contains(task3, allTasks, new SecurityTaskComparer());
|
|
|
|
var pendingTasks = await securityTaskRepository.GetManyByUserIdStatusAsync(user.Id, SecurityTaskStatus.Pending);
|
|
Assert.Equal(2, pendingTasks.Count);
|
|
Assert.Contains(task1, pendingTasks, new SecurityTaskComparer());
|
|
Assert.Contains(task3, pendingTasks, new SecurityTaskComparer());
|
|
Assert.DoesNotContain(task2, pendingTasks, new SecurityTaskComparer());
|
|
|
|
var completedTasks = await securityTaskRepository.GetManyByUserIdStatusAsync(user.Id, SecurityTaskStatus.Completed);
|
|
Assert.Single(completedTasks);
|
|
Assert.Contains(task2, completedTasks, new SecurityTaskComparer());
|
|
Assert.DoesNotContain(task1, completedTasks, new SecurityTaskComparer());
|
|
Assert.DoesNotContain(task3, completedTasks, new SecurityTaskComparer());
|
|
}
|
|
}
|