diff --git a/src/Api/Controllers/FoldersController.cs b/src/Api/Controllers/FoldersController.cs index 0511c7c47..fd762ace7 100644 --- a/src/Api/Controllers/FoldersController.cs +++ b/src/Api/Controllers/FoldersController.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -7,8 +6,6 @@ using Bit.Core.Repositories; using Microsoft.AspNetCore.Authorization; using Bit.Core.Models.Api; using Bit.Core.Exceptions; -using Bit.Core.Models.Table; -using Microsoft.AspNetCore.Identity; using Bit.Core.Services; namespace Bit.Api.Controllers @@ -17,16 +14,16 @@ namespace Bit.Api.Controllers [Authorize("Application")] public class FoldersController : Controller { - private readonly ICipherRepository _cipherRepository; + private readonly IFolderRepository _folderRepository; private readonly ICipherService _cipherService; private readonly IUserService _userService; public FoldersController( - ICipherRepository cipherRepository, + IFolderRepository folderRepository, ICipherService cipherService, IUserService userService) { - _cipherRepository = cipherRepository; + _folderRepository = folderRepository; _cipherService = cipherService; _userService = userService; } @@ -35,22 +32,21 @@ namespace Bit.Api.Controllers public async Task Get(string id) { var userId = _userService.GetProperUserId(User).Value; - var folder = await _cipherRepository.GetByIdAsync(new Guid(id), userId); - if(folder == null || folder.Type != Core.Enums.CipherType.Folder) + var folder = await _folderRepository.GetByIdAsync(new Guid(id), userId); + if(folder == null) { throw new NotFoundException(); } - return new FolderResponseModel(folder, userId); + return new FolderResponseModel(folder); } [HttpGet("")] public async Task> Get() { var userId = _userService.GetProperUserId(User).Value; - ICollection folders = await _cipherRepository.GetManyByTypeAndUserIdAsync(Core.Enums.CipherType.Folder, - userId); - var responses = folders.Select(f => new FolderResponseModel(f, userId)); + var folders = await _folderRepository.GetManyByUserIdAsync(userId); + var responses = folders.Select(f => new FolderResponseModel(f)); return new ListResponseModel(responses); } @@ -58,9 +54,9 @@ namespace Bit.Api.Controllers public async Task Post([FromBody]FolderRequestModel model) { var userId = _userService.GetProperUserId(User).Value; - var folder = model.ToCipher(_userService.GetProperUserId(User).Value); - await _cipherService.SaveAsync(folder); - return new FolderResponseModel(folder, userId); + var folder = model.ToFolder(_userService.GetProperUserId(User).Value); + await _cipherService.SaveFolderAsync(folder); + return new FolderResponseModel(folder); } [HttpPut("{id}")] @@ -68,27 +64,28 @@ namespace Bit.Api.Controllers public async Task Put(string id, [FromBody]FolderRequestModel model) { var userId = _userService.GetProperUserId(User).Value; - var folder = await _cipherRepository.GetByIdAsync(new Guid(id), userId); - if(folder == null || folder.Type != Core.Enums.CipherType.Folder) + var folder = await _folderRepository.GetByIdAsync(new Guid(id), userId); + if(folder == null) { throw new NotFoundException(); } - await _cipherService.SaveAsync(model.ToCipher(folder)); - return new FolderResponseModel(folder, userId); + await _cipherService.SaveFolderAsync(model.ToFolder(folder)); + return new FolderResponseModel(folder); } [HttpDelete("{id}")] [HttpPost("{id}/delete")] public async Task Delete(string id) { - var folder = await _cipherRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value); - if(folder == null || folder.Type != Core.Enums.CipherType.Folder) + var userId = _userService.GetProperUserId(User).Value; + var folder = await _folderRepository.GetByIdAsync(new Guid(id), userId); + if(folder == null) { throw new NotFoundException(); } - await _cipherService.DeleteAsync(folder); + await _cipherService.DeleteFolderAsync(folder); } } } diff --git a/src/Core/Models/Api/FolderDataModel.cs b/src/Core/Models/Api/FolderDataModel.cs deleted file mode 100644 index 9726258a4..000000000 --- a/src/Core/Models/Api/FolderDataModel.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Bit.Core.Models.Table; -using Newtonsoft.Json; - -namespace Bit.Core.Models.Api -{ - public class FolderDataModel - { - public FolderDataModel() { } - - public FolderDataModel(FolderRequestModel folder) - { - Name = folder.Name; - } - - public FolderDataModel(CipherRequestModel cipher) - { - Name = cipher.Name; - } - - public FolderDataModel(Cipher cipher) - { - if(cipher.Type != Core.Enums.CipherType.Folder) - { - throw new ArgumentException("Cipher is not correct type."); - } - - var data = JsonConvert.DeserializeObject(cipher.Data); - - Name = data.Name; - } - - public string Name { get; set; } - } -} diff --git a/src/Core/Models/Api/Request/FolderRequestModel.cs b/src/Core/Models/Api/Request/FolderRequestModel.cs index ab281b309..5ba828999 100644 --- a/src/Core/Models/Api/Request/FolderRequestModel.cs +++ b/src/Core/Models/Api/Request/FolderRequestModel.cs @@ -13,19 +13,17 @@ namespace Bit.Core.Models.Api [StringLength(300)] public string Name { get; set; } - public Cipher ToCipher(Guid userId) + public Folder ToFolder(Guid userId) { - return ToCipher(new Cipher + return ToFolder(new Folder { UserId = userId }); } - public Cipher ToCipher(Cipher existingFolder) + public Folder ToFolder(Folder existingFolder) { - existingFolder.Data = JsonConvert.SerializeObject(new FolderDataModel(this), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); - existingFolder.Type = Core.Enums.CipherType.Folder; - + existingFolder.Name = Name; return existingFolder; } } diff --git a/src/Core/Models/Api/Response/FolderResponseModel.cs b/src/Core/Models/Api/Response/FolderResponseModel.cs index 16a5ec3eb..5767bec31 100644 --- a/src/Core/Models/Api/Response/FolderResponseModel.cs +++ b/src/Core/Models/Api/Response/FolderResponseModel.cs @@ -5,24 +5,17 @@ namespace Bit.Core.Models.Api { public class FolderResponseModel : ResponseModel { - public FolderResponseModel(Cipher cipher, Guid userId) + public FolderResponseModel(Folder folder) : base("folder") { - if(cipher == null) + if(folder == null) { - throw new ArgumentNullException(nameof(cipher)); + throw new ArgumentNullException(nameof(folder)); } - if(cipher.Type != Core.Enums.CipherType.Folder) - { - throw new ArgumentException(nameof(cipher.Type)); - } - - var data = new FolderDataModel(cipher); - - Id = cipher.Id.ToString(); - Name = data.Name; - RevisionDate = cipher.RevisionDate; + Id = folder.Id.ToString(); + Name = folder.Name; + RevisionDate = folder.RevisionDate; } public string Id { get; set; } diff --git a/src/Core/Repositories/IFolderRepository.cs b/src/Core/Repositories/IFolderRepository.cs index 9b48d971b..3056c3121 100644 --- a/src/Core/Repositories/IFolderRepository.cs +++ b/src/Core/Repositories/IFolderRepository.cs @@ -1,9 +1,13 @@ using System; using Bit.Core.Models.Table; +using System.Threading.Tasks; +using System.Collections.Generic; namespace Bit.Core.Repositories { public interface IFolderRepository : IRepository { + Task GetByIdAsync(Guid id, Guid userId); + Task> GetManyByUserIdAsync(Guid userId); } } diff --git a/src/Core/Repositories/SqlServer/FolderRepository.cs b/src/Core/Repositories/SqlServer/FolderRepository.cs index 839c605c6..d3898fe67 100644 --- a/src/Core/Repositories/SqlServer/FolderRepository.cs +++ b/src/Core/Repositories/SqlServer/FolderRepository.cs @@ -1,5 +1,11 @@ using System; using Bit.Core.Models.Table; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using Dapper; +using System.Linq; namespace Bit.Core.Repositories.SqlServer { @@ -12,5 +18,29 @@ namespace Bit.Core.Repositories.SqlServer public FolderRepository(string connectionString) : base(connectionString) { } + + public async Task GetByIdAsync(Guid id, Guid userId) + { + var folder = await GetByIdAsync(id); + if(folder == null || folder.UserId != userId) + { + return null; + } + + return folder; + } + + public async Task> GetManyByUserIdAsync(Guid userId) + { + using(var connection = new SqlConnection(ConnectionString)) + { + var results = await connection.QueryAsync( + $"[{Schema}].[Folder_ReadByUserId]", + new { UserId = userId }, + commandType: CommandType.StoredProcedure); + + return results.ToList(); + } + } } } diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 93c24a0e5..1b990cf0e 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -163,5 +163,7 @@ + + \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Folder_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/Folder_ReadByUserId.sql new file mode 100644 index 000000000..1244383ed --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/Folder_ReadByUserId.sql @@ -0,0 +1,13 @@ +CREATE PROCEDURE [dbo].[Folder_ReadByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[FolderView] + WHERE + [UserId] = @UserId +END \ No newline at end of file diff --git a/src/Sql/dbo/Views/FolderView.sql b/src/Sql/dbo/Views/FolderView.sql new file mode 100644 index 000000000..959248e30 --- /dev/null +++ b/src/Sql/dbo/Views/FolderView.sql @@ -0,0 +1,6 @@ +CREATE VIEW [dbo].[FolderView] +AS +SELECT + * +FROM + [dbo].[Folder] \ No newline at end of file