diff --git a/src/Api/Controllers/CiphersController.cs b/src/Api/Controllers/CiphersController.cs index 624b71e12..c3c23f070 100644 --- a/src/Api/Controllers/CiphersController.cs +++ b/src/Api/Controllers/CiphersController.cs @@ -134,7 +134,7 @@ namespace Bit.Api.Controllers { var userId = _userService.GetProperUserId(User).Value; var cipher = await _cipherRepository.GetByIdAsync(new Guid(id), userId); - if(cipher == null || cipher.OrganizationId.HasValue || cipher.UserId != userId) + if(cipher == null || cipher.UserId != userId) { throw new NotFoundException(); } diff --git a/src/Core/Models/Api/Request/CipherRequestModel.cs b/src/Core/Models/Api/Request/CipherRequestModel.cs index 04c77e0b1..da9fd88fc 100644 --- a/src/Core/Models/Api/Request/CipherRequestModel.cs +++ b/src/Core/Models/Api/Request/CipherRequestModel.cs @@ -5,6 +5,7 @@ using Bit.Core.Models.Table; using Bit.Core.Enums; using Newtonsoft.Json; using System.Collections.Generic; +using System.Linq; namespace Bit.Core.Models.Api { @@ -48,12 +49,11 @@ namespace Bit.Core.Models.Api public Cipher ToCipher(Cipher existingCipher) { - existingCipher.OrganizationId = string.IsNullOrWhiteSpace(OrganizationId) ? null : (Guid?)new Guid(OrganizationId); - switch(existingCipher.Type) { case CipherType.Login: - existingCipher.Data = JsonConvert.SerializeObject(new LoginDataModel(this), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); + existingCipher.Data = JsonConvert.SerializeObject(new LoginDataModel(this), + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); break; default: throw new ArgumentException("Unsupported " + nameof(Type) + "."); @@ -63,10 +63,20 @@ namespace Bit.Core.Models.Api } } - public class CipherMoveRequestModel + public class CipherMoveRequestModel : IValidatableObject { + [Required] public IEnumerable SubvaultIds { get; set; } [Required] public CipherRequestModel Cipher { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if(!SubvaultIds?.Any() ?? false) + { + yield return new ValidationResult("You must select at least one subvault.", + new string[] { nameof(SubvaultIds) }); + } + } } } diff --git a/src/Core/Services/Implementations/CipherService.cs b/src/Core/Services/Implementations/CipherService.cs index f7560f74f..82f8ea0b9 100644 --- a/src/Core/Services/Implementations/CipherService.cs +++ b/src/Core/Services/Implementations/CipherService.cs @@ -119,9 +119,9 @@ namespace Bit.Core.Services throw new BadRequestException(nameof(cipher.Id)); } - if(organizationId == default(Guid)) + if(cipher.OrganizationId.HasValue) { - throw new BadRequestException(nameof(organizationId)); + throw new BadRequestException("Already belongs to an organization."); } if(!cipher.UserId.HasValue || cipher.UserId.Value != movingUserId) @@ -134,8 +134,8 @@ namespace Bit.Core.Services var subvaultUserDetails = await _subvaultUserRepository.GetPermissionsByUserIdAsync(movingUserId, subvaultIds, organizationId); - var adminSubvaults = subvaultUserDetails.Where(s => s.Admin).Select(s => s.SubvaultId); - if(!adminSubvaults.Any()) + var writeableSubvaults = subvaultUserDetails.Where(s => !s.ReadOnly).Select(s => s.SubvaultId); + if(!writeableSubvaults.Any()) { throw new BadRequestException("No subvaults."); } @@ -143,7 +143,7 @@ namespace Bit.Core.Services cipher.UserId = null; cipher.OrganizationId = organizationId; cipher.RevisionDate = DateTime.UtcNow; - await _cipherRepository.ReplaceAsync(cipher, adminSubvaults); + await _cipherRepository.ReplaceAsync(cipher, writeableSubvaults); // push //await _pushService.PushSyncCipherUpdateAsync(cipher); diff --git a/src/Sql/dbo/Functions/UserCanEditCipher.sql b/src/Sql/dbo/Functions/UserCanEditCipher.sql index f84795772..21700c402 100644 --- a/src/Sql/dbo/Functions/UserCanEditCipher.sql +++ b/src/Sql/dbo/Functions/UserCanEditCipher.sql @@ -5,11 +5,7 @@ BEGIN ;WITH [CTE] AS( SELECT - CASE - WHEN OU.[Type] = 2 AND SU.[Admin] = 1 THEN 1 -- 2 = Regular User - WHEN SU.[ReadOnly] = 0 THEN 1 - ELSE 0 - END [CanEdit] + CASE WHEN SU.[ReadOnly] = 0 THEN 1 ELSE 0 END [CanEdit] FROM [dbo].[SubvaultUser] SU INNER JOIN diff --git a/src/Sql/dbo/Stored Procedures/SubvaultUser_ReadPermissionsBySubvaultUserId.sql b/src/Sql/dbo/Stored Procedures/SubvaultUser_ReadPermissionsBySubvaultUserId.sql index 3acb89b26..61259aab8 100644 --- a/src/Sql/dbo/Stored Procedures/SubvaultUser_ReadPermissionsBySubvaultUserId.sql +++ b/src/Sql/dbo/Stored Procedures/SubvaultUser_ReadPermissionsBySubvaultUserId.sql @@ -9,7 +9,7 @@ BEGIN SELECT SU.[SubvaultId], CASE WHEN OU.[Type] = 2 THEN SU.[Admin] ELSE 1 END AS [Admin], -- 2 = Regular User - CASE WHEN OU.[Type] = 2 THEN SU.[ReadOnly] ELSE 0 END AS [ReadOnly] -- 2 = Regular User + SU.[ReadOnly] FROM [dbo].[SubvaultUser] SU INNER JOIN