diff --git a/src/Api/Controllers/CiphersController.cs b/src/Api/Controllers/CiphersController.cs index dc5638a394..e7702834c6 100644 --- a/src/Api/Controllers/CiphersController.cs +++ b/src/Api/Controllers/CiphersController.cs @@ -119,12 +119,12 @@ namespace Bit.Api.Controllers { var userId = _userService.GetProperUserId(User).Value; var cipher = await _cipherRepository.GetByIdAsync(new Guid(id), userId); - if(cipher == null) + if(cipher == null || cipher.OrganizationId.HasValue || cipher.UserId != userId) { throw new NotFoundException(); } - await _cipherService.MoveSubvaultAsync(model.Cipher.ToCipher(cipher), + await _cipherService.MoveSubvaultAsync(model.Cipher.ToCipher(cipher), new Guid(model.Cipher.OrganizationId), model.SubvaultIds.Select(s => new Guid(s)), userId); } diff --git a/src/Api/IdentityServer/ResourceOwnerPasswordValidator.cs b/src/Api/IdentityServer/ResourceOwnerPasswordValidator.cs index 93d71fd0a9..26c97a2a6e 100644 --- a/src/Api/IdentityServer/ResourceOwnerPasswordValidator.cs +++ b/src/Api/IdentityServer/ResourceOwnerPasswordValidator.cs @@ -121,7 +121,7 @@ namespace Bit.Api.IdentityServer var customResponse = new Dictionary(); if(!string.IsNullOrWhiteSpace(user.PrivateKey)) { - customResponse.Add("EncryptedPrivateKey", user.PrivateKey); + customResponse.Add("PrivateKey", user.PrivateKey); } context.Result = new GrantValidationResult(user.Id.ToString(), "Application", diff --git a/src/Core/Services/ICipherService.cs b/src/Core/Services/ICipherService.cs index 14332fecc1..ed2dc3fdaa 100644 --- a/src/Core/Services/ICipherService.cs +++ b/src/Core/Services/ICipherService.cs @@ -13,7 +13,7 @@ namespace Bit.Core.Services Task DeleteAsync(CipherDetails cipher, Guid deletingUserId); Task SaveFolderAsync(Folder folder); Task DeleteFolderAsync(Folder folder); - Task MoveSubvaultAsync(Cipher cipher, IEnumerable subvaultIds, Guid userId); + Task MoveSubvaultAsync(Cipher cipher, Guid organizationId, IEnumerable subvaultIds, Guid userId); Task ImportCiphersAsync(List folders, List ciphers, IEnumerable> folderRelationships); } diff --git a/src/Core/Services/Implementations/CipherService.cs b/src/Core/Services/Implementations/CipherService.cs index 00cfb52c2c..f7560f74fc 100644 --- a/src/Core/Services/Implementations/CipherService.cs +++ b/src/Core/Services/Implementations/CipherService.cs @@ -112,24 +112,38 @@ namespace Bit.Core.Services //await _pushService.PushSyncCipherDeleteAsync(cipher); } - public async Task MoveSubvaultAsync(Cipher cipher, IEnumerable subvaultIds, Guid userId) + public async Task MoveSubvaultAsync(Cipher cipher, Guid organizationId, IEnumerable subvaultIds, Guid movingUserId) { if(cipher.Id == default(Guid)) { throw new BadRequestException(nameof(cipher.Id)); } - if(!cipher.OrganizationId.HasValue) + if(organizationId == default(Guid)) { - throw new BadRequestException(nameof(cipher.OrganizationId)); + throw new BadRequestException(nameof(organizationId)); } - var subvaultUserDetails = await _subvaultUserRepository.GetPermissionsByUserIdAsync(userId, subvaultIds, - cipher.OrganizationId.Value); + if(!cipher.UserId.HasValue || cipher.UserId.Value != movingUserId) + { + throw new NotFoundException(); + } + + // We do not need to check if the user belongs to this organization since this call will return no subvaults + // and therefore be caught by the .Any() check below. + var subvaultUserDetails = await _subvaultUserRepository.GetPermissionsByUserIdAsync(movingUserId, subvaultIds, + organizationId); + + var adminSubvaults = subvaultUserDetails.Where(s => s.Admin).Select(s => s.SubvaultId); + if(!adminSubvaults.Any()) + { + throw new BadRequestException("No subvaults."); + } cipher.UserId = null; + cipher.OrganizationId = organizationId; cipher.RevisionDate = DateTime.UtcNow; - await _cipherRepository.ReplaceAsync(cipher, subvaultUserDetails.Where(s => s.Admin).Select(s => s.SubvaultId)); + await _cipherRepository.ReplaceAsync(cipher, adminSubvaults); // push //await _pushService.PushSyncCipherUpdateAsync(cipher); @@ -173,7 +187,7 @@ namespace Bit.Core.Services } } - private async Task UserCanEditAsync(CipherDetails cipher, Guid userId) + private async Task UserCanEditAsync(Cipher cipher, Guid userId) { if(!cipher.OrganizationId.HasValue && cipher.UserId.HasValue && cipher.UserId.Value == userId) {