mirror of
https://github.com/bitwarden/server.git
synced 2024-11-22 12:15:36 +01:00
handle user delete scenarios when part of org
This commit is contained in:
parent
da03c276aa
commit
628a72b13f
@ -11,6 +11,7 @@ namespace Bit.Core.Repositories
|
||||
{
|
||||
Task<int> GetCountByOrganizationIdAsync(Guid organizationId);
|
||||
Task<int> GetCountByFreeOrganizationAdminUserAsync(Guid userId);
|
||||
Task<int> GetCountByOrganizationOwnerUserAsync(Guid userId);
|
||||
Task<ICollection<OrganizationUser>> GetManyByUserAsync(Guid userId);
|
||||
Task<ICollection<OrganizationUser>> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type);
|
||||
Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, string email);
|
||||
|
@ -47,6 +47,19 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> GetCountByOrganizationOwnerUserAsync(Guid userId)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var results = await connection.ExecuteScalarAsync<int>(
|
||||
"[dbo].[OrganizationUser_ReadCountByOrganizationOwnerUser]",
|
||||
new { UserId = userId },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, string email)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
|
@ -18,6 +18,7 @@ namespace Bit.Core.Services
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly ICipherRepository _cipherRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IMailService _mailService;
|
||||
private readonly IPushService _pushService;
|
||||
private readonly IdentityErrorDescriber _identityErrorDescriber;
|
||||
@ -29,6 +30,7 @@ namespace Bit.Core.Services
|
||||
public UserService(
|
||||
IUserRepository userRepository,
|
||||
ICipherRepository cipherRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IMailService mailService,
|
||||
IPushService pushService,
|
||||
IUserStore<User> store,
|
||||
@ -54,6 +56,7 @@ namespace Bit.Core.Services
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_cipherRepository = cipherRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_mailService = mailService;
|
||||
_pushService = pushService;
|
||||
_identityOptions = optionsAccessor?.Value ?? new IdentityOptions();
|
||||
@ -133,6 +136,22 @@ namespace Bit.Core.Services
|
||||
await _pushService.PushSyncSettingsAsync(user.Id);
|
||||
}
|
||||
|
||||
public override async Task<IdentityResult> DeleteAsync(User user)
|
||||
{
|
||||
// Check if user is the owner of any organizations.
|
||||
var organizationOwnerCount = await _organizationUserRepository.GetCountByOrganizationOwnerUserAsync(user.Id);
|
||||
if(organizationOwnerCount > 0)
|
||||
{
|
||||
return IdentityResult.Failed(new IdentityError
|
||||
{
|
||||
Description = "You must leave or delete any organizations that you are the owner of first."
|
||||
});
|
||||
}
|
||||
|
||||
await _userRepository.DeleteAsync(user);
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
public async Task<IdentityResult> RegisterUserAsync(User user, string masterPassword)
|
||||
{
|
||||
var result = await base.CreateAsync(user, masterPassword);
|
||||
@ -184,7 +203,7 @@ namespace Bit.Core.Services
|
||||
return IdentityResult.Failed(_identityErrorDescriber.PasswordMismatch());
|
||||
}
|
||||
|
||||
if(!await base.VerifyUserTokenAsync(user, _identityOptions.Tokens.ChangeEmailTokenProvider,
|
||||
if(!await base.VerifyUserTokenAsync(user, _identityOptions.Tokens.ChangeEmailTokenProvider,
|
||||
GetChangeEmailTokenPurpose(newEmail), token))
|
||||
{
|
||||
return IdentityResult.Failed(_identityErrorDescriber.InvalidToken());
|
||||
@ -224,7 +243,7 @@ namespace Bit.Core.Services
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<IdentityResult> ChangePasswordAsync(User user, string masterPassword, string newMasterPassword,
|
||||
public async Task<IdentityResult> ChangePasswordAsync(User user, string masterPassword, string newMasterPassword,
|
||||
IEnumerable<Cipher> ciphers, IEnumerable<Folder> folders, string privateKey)
|
||||
{
|
||||
if(user == null)
|
||||
@ -373,7 +392,7 @@ namespace Bit.Core.Services
|
||||
|
||||
if(errors.Count > 0)
|
||||
{
|
||||
Logger.LogWarning("User {userId} password validation failed: {errors}.", await GetUserIdAsync(user),
|
||||
Logger.LogWarning("User {userId} password validation failed: {errors}.", await GetUserIdAsync(user),
|
||||
string.Join(";", errors.Select(e => e.Code)));
|
||||
return IdentityResult.Failed(errors.ToArray());
|
||||
}
|
||||
|
@ -179,5 +179,6 @@
|
||||
<Build Include="dbo\Stored Procedures\OrganizationUserOrganizationDetails_ReadByUserIdStatus.sql" />
|
||||
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadById.sql" />
|
||||
<Build Include="dbo\User Defined Types\GuidIdArray.sql" />
|
||||
<Build Include="dbo\Stored Procedures\OrganizationUser_ReadCountByOrganizationOwnerUser.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,14 @@
|
||||
CREATE PROCEDURE [dbo].[OrganizationUser_ReadCountByOrganizationOwnerUser]
|
||||
@UserId UNIQUEIDENTIFIER
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
[dbo].[OrganizationUser] OU
|
||||
WHERE
|
||||
OU.[UserId] = @UserId
|
||||
AND OU.[Type] = 0
|
||||
END
|
@ -6,6 +6,7 @@ BEGIN
|
||||
SET NOCOUNT ON
|
||||
DECLARE @BatchSize INT = 100
|
||||
|
||||
-- Delete ciphers
|
||||
WHILE @BatchSize > 0
|
||||
BEGIN
|
||||
BEGIN TRANSACTION User_DeleteById_Ciphers
|
||||
@ -23,12 +24,25 @@ BEGIN
|
||||
|
||||
BEGIN TRANSACTION User_DeleteById
|
||||
|
||||
-- Delete collection users
|
||||
DELETE
|
||||
CU
|
||||
FROM
|
||||
[dbo].[CollectionUser] CU
|
||||
INNER JOIN
|
||||
[dbo].[OrganizationUser] OU ON OU.[Id] = CU.[OrganizationUserId]
|
||||
WHERE
|
||||
OU.[UserId] = @Id
|
||||
|
||||
-- Delete organization users
|
||||
DELETE
|
||||
FROM
|
||||
[dbo].[Device]
|
||||
[dbo].[OrganizationUser]
|
||||
WHERE
|
||||
[UserId] = @Id
|
||||
AND [Type] != 0 -- 0 = owner
|
||||
|
||||
-- Finally, delete the user
|
||||
DELETE
|
||||
FROM
|
||||
[dbo].[User]
|
||||
|
Loading…
Reference in New Issue
Block a user