1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-13 05:38:25 -05:00

[PM-14376] Add GET tasks endpoint (#5089)

* 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
This commit is contained in:
SmithThe4th
2024-12-12 14:27:31 -05:00
committed by GitHub
parent 03dde0d008
commit a332a69112
13 changed files with 469 additions and 2 deletions

View File

@ -0,0 +1,90 @@
using Bit.Core.Enums;
using Bit.Core.Vault.Entities;
using Bit.Core.Vault.Enums;
using Bit.Infrastructure.EntityFramework.Repositories;
using Bit.Infrastructure.EntityFramework.Repositories.Queries;
namespace Bit.Infrastructure.EntityFramework.Vault.Repositories.Queries;
public class SecurityTaskReadByUserIdStatusQuery : IQuery<SecurityTask>
{
private readonly Guid _userId;
private readonly SecurityTaskStatus? _status;
public SecurityTaskReadByUserIdStatusQuery(Guid userId, SecurityTaskStatus? status)
{
_userId = userId;
_status = status;
}
public IQueryable<SecurityTask> Run(DatabaseContext dbContext)
{
var query = from st in dbContext.SecurityTasks
join ou in dbContext.OrganizationUsers
on st.OrganizationId equals ou.OrganizationId
join o in dbContext.Organizations
on st.OrganizationId equals o.Id
join c in dbContext.Ciphers
on st.CipherId equals c.Id into c_g
from c in c_g.DefaultIfEmpty()
join cc in dbContext.CollectionCiphers
on c.Id equals cc.CipherId into cc_g
from cc in cc_g.DefaultIfEmpty()
join cu in dbContext.CollectionUsers
on new { cc.CollectionId, OrganizationUserId = ou.Id } equals
new { cu.CollectionId, cu.OrganizationUserId } into cu_g
from cu in cu_g.DefaultIfEmpty()
join gu in dbContext.GroupUsers
on new { CollectionId = (Guid?)cu.CollectionId, OrganizationUserId = ou.Id } equals
new { CollectionId = (Guid?)null, gu.OrganizationUserId } into gu_g
from gu in gu_g.DefaultIfEmpty()
join cg in dbContext.CollectionGroups
on new { cc.CollectionId, gu.GroupId } equals
new { cg.CollectionId, cg.GroupId } into cg_g
from cg in cg_g.DefaultIfEmpty()
where
ou.UserId == _userId &&
ou.Status == OrganizationUserStatusType.Confirmed &&
o.Enabled &&
(
st.CipherId == null ||
(
c != null &&
(
(cu != null && !cu.ReadOnly) || (cg != null && !cg.ReadOnly && cu == null)
)
)
) &&
(_status == null || st.Status == _status)
group st by new
{
st.Id,
st.OrganizationId,
st.CipherId,
st.Type,
st.Status,
st.CreationDate,
st.RevisionDate
} into g
select new SecurityTask
{
Id = g.Key.Id,
OrganizationId = g.Key.OrganizationId,
CipherId = g.Key.CipherId,
Type = g.Key.Type,
Status = g.Key.Status,
CreationDate = g.Key.CreationDate,
RevisionDate = g.Key.RevisionDate
};
return query.OrderByDescending(st => st.CreationDate);
}
}

View File

@ -1,7 +1,10 @@
using AutoMapper;
using Bit.Core.Vault.Enums;
using Bit.Core.Vault.Repositories;
using Bit.Infrastructure.EntityFramework.Repositories;
using Bit.Infrastructure.EntityFramework.Vault.Models;
using Bit.Infrastructure.EntityFramework.Vault.Repositories.Queries;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Bit.Infrastructure.EntityFramework.Vault.Repositories;
@ -11,4 +14,15 @@ public class SecurityTaskRepository : Repository<Core.Vault.Entities.SecurityTas
public SecurityTaskRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
: base(serviceScopeFactory, mapper, (context) => context.SecurityTasks)
{ }
/// <inheritdoc />
public async Task<ICollection<Core.Vault.Entities.SecurityTask>> GetManyByUserIdStatusAsync(Guid userId,
SecurityTaskStatus? status = null)
{
using var scope = ServiceScopeFactory.CreateScope();
var dbContext = GetDatabaseContext(scope);
var query = new SecurityTaskReadByUserIdStatusQuery(userId, status);
var data = await query.Run(dbContext).ToListAsync();
return data;
}
}