1
0
mirror of https://github.com/bitwarden/server synced 2025-12-24 20:23:21 +00:00

[PM-21612] [Unified] Fix unhandled error when editing an invited member (#5817)

* Check for UserId instead of passing potentially default value to
  bump account revision date method.

* Pass explicit UserId into CipherRepository.CreateAsync method
  used for imports.
This commit is contained in:
Thomas Rittson
2025-05-23 11:45:41 +10:00
committed by GitHub
parent 83478f9c69
commit 198d96e155
16 changed files with 169 additions and 23 deletions

View File

@@ -1,4 +1,5 @@
using AutoMapper;
using System.Diagnostics;
using AutoMapper;
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Models;
using Bit.Core.Enums;
@@ -7,11 +8,12 @@ using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Repositories;
using Bit.Infrastructure.EntityFramework.Models;
using Bit.Infrastructure.EntityFramework.Repositories;
using Bit.Infrastructure.EntityFramework.Repositories.Queries;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Bit.Infrastructure.EntityFramework.Repositories;
namespace Bit.Infrastructure.EntityFramework.AdminConsole.Repositories;
public class OrganizationUserRepository : Repository<Core.Entities.OrganizationUser, OrganizationUser, Guid>, IOrganizationUserRepository
{
@@ -440,15 +442,23 @@ public class OrganizationUserRepository : Repository<Core.Entities.OrganizationU
}
}
public async override Task ReplaceAsync(Core.Entities.OrganizationUser organizationUser)
public override async Task ReplaceAsync(Core.Entities.OrganizationUser organizationUser)
{
await base.ReplaceAsync(organizationUser);
using (var scope = ServiceScopeFactory.CreateScope())
// Only bump account revision dates for confirmed OrgUsers,
// as this is the only status that receives sync data from the organization
if (organizationUser.Status is not OrganizationUserStatusType.Confirmed)
{
var dbContext = GetDatabaseContext(scope);
await dbContext.UserBumpAccountRevisionDateAsync(organizationUser.UserId.GetValueOrDefault());
await dbContext.SaveChangesAsync();
return;
}
Debug.Assert(organizationUser.UserId is not null, "OrganizationUser is confirmed but does not have a UserId.");
using var scope = ServiceScopeFactory.CreateScope();
var dbContext = GetDatabaseContext(scope);
await dbContext.UserBumpAccountRevisionDateAsync(organizationUser.UserId.Value);
await dbContext.SaveChangesAsync();
}
public async Task ReplaceAsync(Core.Entities.OrganizationUser obj, IEnumerable<CollectionAccessSelection> requestedCollections)

View File

@@ -1,4 +1,6 @@
using System.Diagnostics;
#nullable enable
using System.Diagnostics;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Auth.Enums;
using Bit.Core.Enums;
@@ -11,8 +13,18 @@ namespace Bit.Infrastructure.EntityFramework.Repositories;
public static class DatabaseContextExtensions
{
/// <summary>
/// Bump the account revision date for the user.
/// The caller is responsible for providing a valid UserId (not a null or default Guid) for a user that exists
/// in the database.
/// </summary>
public static async Task UserBumpAccountRevisionDateAsync(this DatabaseContext context, Guid userId)
{
if (userId == Guid.Empty)
{
throw new ArgumentException("Invalid UserId.");
}
var user = await context.Users.FindAsync(userId);
Debug.Assert(user is not null, "The user id is expected to be validated as a true-in database user before making this call.");
user.AccountRevisionDate = DateTime.UtcNow;

View File

@@ -142,8 +142,10 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
}
}
public async Task CreateAsync(IEnumerable<Core.Vault.Entities.Cipher> ciphers, IEnumerable<Core.Vault.Entities.Folder> folders)
public async Task CreateAsync(Guid userId, IEnumerable<Core.Vault.Entities.Cipher> ciphers,
IEnumerable<Core.Vault.Entities.Folder> folders)
{
ciphers = ciphers.ToList();
if (!ciphers.Any())
{
return;
@@ -156,7 +158,8 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, folderEntities);
var cipherEntities = Mapper.Map<List<Cipher>>(ciphers);
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, cipherEntities);
await dbContext.UserBumpAccountRevisionDateAsync(ciphers.First().UserId.GetValueOrDefault());
await dbContext.UserBumpAccountRevisionDateAsync(userId);
await dbContext.SaveChangesAsync();
}
}