mirror of
https://github.com/bitwarden/server.git
synced 2026-02-02 07:03:11 +08:00
* Adding auto confirm endpoint and initial command work. * Adding validator * Finished command implementation. * Enabled the feature renomved used method. Enabled the policy in the tests. * Added extension functions to allow for railroad programming. * Removed guid from route template. Added xml docs * Added validation for command. * Added default collection creation to command. * formatting. * Added additional error types and mapped to appropriate results. * Added tests for auto confirm validator * Adding tests * fixing file name * Cleaned up OrgUserController. Added integration tests. * Consolidated CommandResult and validation result stuff into a v2 directory. * changing result to match handle method. * Moves validation thenasync method. * Added brackets. * Updated XML comment * Adding idempotency comment. * Fixed up merge problems. Fixed return types for handle. * Renamed to ValidationRequest * I added some methods for CommandResult to cover some future use cases. Added ApplyAsync method to execute multiple functions against CommandResult without an error stopping the workflow for side-effects. * Fixed up logic around should create default colleciton. Added more methods for chaining ValidationResult together. Added logic for user type. * Clearing nullable enable. * Fixed up validator tests. * Tests for auto confirm command * Fixed up command result and AutoConfirmCommand. * Removed some unused methods. * Moved autoconfirm tests to their own class. * Moved some stuff around. Need to clean up creation of accepted org user yet. * Moved some more code around. Folded Key into accepted constructor. removed unneeded tests since key and accepted are now a part of AcceptedOrgUser Creation. * Clean up clean up everybody everywhere. Clean up clean up everybody do your share. * Another quick one * Removed aggregate Errors.cs * Cleaned up validator and fixed up tests. * Fixed auto confirm repo * Cleaned up command tests. * Unused method. * Restoring Bulk command back to what it was. deleted handle method for bulk. * Remove unused method. * removed unnecssary lines and comments * fixed layout. * Fixed test. * fixed spelling mistake. removed unused import. * Update test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUsers/AutomaticallyConfirmUsersCommandTests.cs Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com> * Ensuring collection is created before full sync. Cleaning up tests and added a few more. Added check that the policy is enabled. * Added org cleanup * Lowering to 5 to see if that helps the runner. * 🤷 * Trying this * Maybe this time will be different. * seeing if awaiting and checking independently will work in ci * I figured it out. Locally, it would be fast enough to all return NoContent, however in CI, its slow enough for it to return 400 due to the user already being confirmed via validation. * Updated tests and validator * Fixed name --------- Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
238 lines
10 KiB
C#
238 lines
10 KiB
C#
// FIXME: Update this file to be null safe and then delete the line below
|
|
#nullable disable
|
|
|
|
using AutoMapper;
|
|
using Bit.Core.AdminConsole.Enums;
|
|
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
|
using Bit.Core.AdminConsole.Repositories;
|
|
using Bit.Core.Enums;
|
|
using Bit.Infrastructure.EntityFramework.AdminConsole.Models;
|
|
using Bit.Infrastructure.EntityFramework.AdminConsole.Repositories.Queries;
|
|
using Bit.Infrastructure.EntityFramework.Repositories;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using AdminConsoleEntities = Bit.Core.AdminConsole.Entities;
|
|
|
|
namespace Bit.Infrastructure.EntityFramework.AdminConsole.Repositories;
|
|
|
|
public class PolicyRepository : Repository<AdminConsoleEntities.Policy, Policy, Guid>, IPolicyRepository
|
|
{
|
|
public PolicyRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
|
|
: base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Policies)
|
|
{ }
|
|
|
|
public async Task<AdminConsoleEntities.Policy> GetByOrganizationIdTypeAsync(Guid organizationId, PolicyType type)
|
|
{
|
|
using (var scope = ServiceScopeFactory.CreateScope())
|
|
{
|
|
var dbContext = GetDatabaseContext(scope);
|
|
var results = await dbContext.Policies
|
|
.FirstOrDefaultAsync(p => p.OrganizationId == organizationId && p.Type == type);
|
|
return Mapper.Map<AdminConsoleEntities.Policy>(results);
|
|
}
|
|
}
|
|
|
|
public async Task<ICollection<AdminConsoleEntities.Policy>> GetManyByOrganizationIdAsync(Guid organizationId)
|
|
{
|
|
using (var scope = ServiceScopeFactory.CreateScope())
|
|
{
|
|
var dbContext = GetDatabaseContext(scope);
|
|
var results = await dbContext.Policies
|
|
.Where(p => p.OrganizationId == organizationId)
|
|
.ToListAsync();
|
|
return Mapper.Map<List<AdminConsoleEntities.Policy>>(results);
|
|
}
|
|
}
|
|
|
|
public async Task<ICollection<AdminConsoleEntities.Policy>> GetManyByUserIdAsync(Guid userId)
|
|
{
|
|
using (var scope = ServiceScopeFactory.CreateScope())
|
|
{
|
|
var dbContext = GetDatabaseContext(scope);
|
|
|
|
var query = new PolicyReadByUserIdQuery(userId);
|
|
var results = await query.Run(dbContext).ToListAsync();
|
|
return Mapper.Map<List<AdminConsoleEntities.Policy>>(results);
|
|
}
|
|
}
|
|
|
|
public async Task<IEnumerable<OrganizationPolicyDetails>> GetPolicyDetailsByOrganizationIdAsync(Guid organizationId, PolicyType policyType)
|
|
{
|
|
using var scope = ServiceScopeFactory.CreateScope();
|
|
var dbContext = GetDatabaseContext(scope);
|
|
|
|
var givenOrgUsers =
|
|
from ou in dbContext.OrganizationUsers
|
|
where ou.OrganizationId == organizationId
|
|
from u in dbContext.Users
|
|
where
|
|
(u.Email == ou.Email && ou.Email != null)
|
|
|| (ou.UserId == u.Id && ou.UserId != null)
|
|
|
|
select new
|
|
{
|
|
ou.Id,
|
|
ou.OrganizationId,
|
|
UserId = u.Id,
|
|
u.Email
|
|
};
|
|
|
|
var orgUsersLinkedByUserId =
|
|
from ou in dbContext.OrganizationUsers
|
|
join gou in givenOrgUsers
|
|
on ou.UserId equals gou.UserId
|
|
select new
|
|
{
|
|
ou.Id,
|
|
ou.OrganizationId,
|
|
gou.UserId,
|
|
ou.Type,
|
|
ou.Status,
|
|
ou.Permissions
|
|
};
|
|
|
|
var orgUsersLinkedByEmail =
|
|
from ou in dbContext.OrganizationUsers
|
|
join gou in givenOrgUsers
|
|
on ou.Email equals gou.Email
|
|
select new
|
|
{
|
|
ou.Id,
|
|
ou.OrganizationId,
|
|
gou.UserId,
|
|
ou.Type,
|
|
ou.Status,
|
|
ou.Permissions
|
|
};
|
|
|
|
var allAffectedOrgUsers = orgUsersLinkedByEmail.Union(orgUsersLinkedByUserId);
|
|
|
|
var providerOrganizations = from pu in dbContext.ProviderUsers
|
|
join po in dbContext.ProviderOrganizations
|
|
on pu.ProviderId equals po.ProviderId
|
|
join ou in allAffectedOrgUsers
|
|
on pu.UserId equals ou.UserId
|
|
where pu.UserId == ou.UserId
|
|
select new
|
|
{
|
|
pu.UserId,
|
|
po.OrganizationId
|
|
};
|
|
|
|
var policyWithAffectedUsers =
|
|
from p in dbContext.Policies
|
|
join o in dbContext.Organizations
|
|
on p.OrganizationId equals o.Id
|
|
join ou in allAffectedOrgUsers
|
|
on o.Id equals ou.OrganizationId
|
|
where p.Enabled
|
|
&& o.Enabled
|
|
&& o.UsePolicies
|
|
&& p.Type == policyType
|
|
select new OrganizationPolicyDetails
|
|
{
|
|
UserId = ou.UserId,
|
|
OrganizationUserId = ou.Id,
|
|
OrganizationId = p.OrganizationId,
|
|
PolicyType = p.Type,
|
|
PolicyData = p.Data,
|
|
OrganizationUserType = ou.Type,
|
|
OrganizationUserStatus = ou.Status,
|
|
OrganizationUserPermissionsData = ou.Permissions,
|
|
IsProvider = providerOrganizations.Any(po => po.OrganizationId == p.OrganizationId)
|
|
};
|
|
|
|
return await policyWithAffectedUsers.ToListAsync();
|
|
}
|
|
|
|
public async Task<IEnumerable<OrganizationPolicyDetails>> GetPolicyDetailsByUserIdsAndPolicyType(
|
|
IEnumerable<Guid> userIds, PolicyType policyType)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(userIds);
|
|
|
|
var userIdsList = userIds.Where(id => id != Guid.Empty).ToList();
|
|
|
|
if (userIdsList.Count == 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
using var scope = ServiceScopeFactory.CreateScope();
|
|
await using var dbContext = GetDatabaseContext(scope);
|
|
|
|
// Get provider relationships
|
|
var providerLookup = await (from pu in dbContext.ProviderUsers
|
|
join po in dbContext.ProviderOrganizations on pu.ProviderId equals po.ProviderId
|
|
where pu.UserId != null && userIdsList.Contains(pu.UserId.Value)
|
|
select new { pu.UserId, po.OrganizationId })
|
|
.ToListAsync();
|
|
|
|
// Hashset for lookup
|
|
var providerSet = new HashSet<(Guid UserId, Guid OrganizationId)>(
|
|
providerLookup.Select(p => (p.UserId!.Value, p.OrganizationId)));
|
|
|
|
// Branch 1: Accepted users
|
|
var acceptedUsers = await (from p in dbContext.Policies
|
|
join ou in dbContext.OrganizationUsers on p.OrganizationId equals ou.OrganizationId
|
|
join o in dbContext.Organizations on p.OrganizationId equals o.Id
|
|
where p.Enabled
|
|
&& p.Type == policyType
|
|
&& o.Enabled
|
|
&& o.UsePolicies
|
|
&& ou.Status != OrganizationUserStatusType.Invited
|
|
&& ou.UserId != null
|
|
&& userIdsList.Contains(ou.UserId.Value)
|
|
select new
|
|
{
|
|
OrganizationUserId = ou.Id,
|
|
OrganizationId = p.OrganizationId,
|
|
PolicyType = p.Type,
|
|
PolicyData = p.Data,
|
|
OrganizationUserType = ou.Type,
|
|
OrganizationUserStatus = ou.Status,
|
|
OrganizationUserPermissionsData = ou.Permissions,
|
|
UserId = ou.UserId.Value
|
|
}).ToListAsync();
|
|
|
|
// Branch 2: Invited users
|
|
var invitedUsers = await (from p in dbContext.Policies
|
|
join ou in dbContext.OrganizationUsers on p.OrganizationId equals ou.OrganizationId
|
|
join o in dbContext.Organizations on p.OrganizationId equals o.Id
|
|
join u in dbContext.Users on ou.Email equals u.Email
|
|
where p.Enabled
|
|
&& o.Enabled
|
|
&& o.UsePolicies
|
|
&& ou.Status == OrganizationUserStatusType.Invited
|
|
&& userIdsList.Contains(u.Id)
|
|
&& p.Type == policyType
|
|
select new
|
|
{
|
|
OrganizationUserId = ou.Id,
|
|
OrganizationId = p.OrganizationId,
|
|
PolicyType = p.Type,
|
|
PolicyData = p.Data,
|
|
OrganizationUserType = ou.Type,
|
|
OrganizationUserStatus = ou.Status,
|
|
OrganizationUserPermissionsData = ou.Permissions,
|
|
UserId = u.Id
|
|
}).ToListAsync();
|
|
|
|
// Combine results with the provider lookup
|
|
var allResults = acceptedUsers.Concat(invitedUsers)
|
|
.Select(item => new OrganizationPolicyDetails
|
|
{
|
|
OrganizationUserId = item.OrganizationUserId,
|
|
OrganizationId = item.OrganizationId,
|
|
PolicyType = item.PolicyType,
|
|
PolicyData = item.PolicyData,
|
|
OrganizationUserType = item.OrganizationUserType,
|
|
OrganizationUserStatus = item.OrganizationUserStatus,
|
|
OrganizationUserPermissionsData = item.OrganizationUserPermissionsData,
|
|
UserId = item.UserId,
|
|
IsProvider = providerSet.Contains((item.UserId, item.OrganizationId))
|
|
});
|
|
|
|
return allResults.ToList();
|
|
}
|
|
}
|