1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-21 12:05:42 +01:00

cipher share data and key response

This commit is contained in:
Kyle Spearrin 2017-02-18 01:17:09 -05:00
parent f7be17d1c5
commit 2b72197f0a
13 changed files with 105 additions and 34 deletions

1
.gitignore vendored
View File

@ -200,3 +200,4 @@ FakesAssemblies/
project.lock.json
*.jfm
mail_dist/
*.refactorlog

View File

@ -33,29 +33,32 @@ namespace Bit.Api.Controllers
[HttpGet("{id}")]
public async Task<CipherResponseModel> Get(string id)
{
var cipher = await _cipherRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
var userId = _userService.GetProperUserId(User).Value;
var cipher = await _cipherRepository.GetByIdAsync(new Guid(id), userId);
if(cipher == null)
{
throw new NotFoundException();
}
return new CipherResponseModel(cipher);
return new CipherResponseModel(cipher, userId);
}
[HttpGet("")]
public async Task<ListResponseModel<CipherResponseModel>> Get()
{
var ciphers = await _cipherRepository.GetManyByUserIdAsync(_userService.GetProperUserId(User).Value);
var responses = ciphers.Select(c => new CipherResponseModel(c));
var userId = _userService.GetProperUserId(User).Value;
var ciphers = await _cipherRepository.GetManyByUserIdAsync(userId);
var responses = ciphers.Select(c => new CipherResponseModel(c, userId));
return new ListResponseModel<CipherResponseModel>(responses);
}
[HttpGet("history")]
public async Task<CipherHistoryResponseModel> Get(DateTime since)
{
var userId = _userService.GetProperUserId(User).Value;
var history = await _cipherRepository.GetManySinceRevisionDateAndUserIdWithDeleteHistoryAsync(
since, _userService.GetProperUserId(User).Value);
return new CipherHistoryResponseModel(history.Item1, history.Item2);
since, userId);
return new CipherHistoryResponseModel(history.Item1, history.Item2, userId);
}
[HttpPost("import")]

View File

@ -34,44 +34,48 @@ namespace Bit.Api.Controllers
[HttpGet("{id}")]
public async Task<FolderResponseModel> Get(string id)
{
var userId = _userService.GetProperUserId(User).Value;
var folder = await _cipherRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
if(folder == null || folder.Type != Core.Enums.CipherType.Folder)
{
throw new NotFoundException();
}
return new FolderResponseModel(folder);
return new FolderResponseModel(folder, userId);
}
[HttpGet("")]
public async Task<ListResponseModel<FolderResponseModel>> Get()
{
ICollection<Cipher> folders = await _cipherRepository.GetManyByTypeAndUserIdAsync(Core.Enums.CipherType.Folder,
_userService.GetProperUserId(User).Value);
var responses = folders.Select(f => new FolderResponseModel(f));
var userId = _userService.GetProperUserId(User).Value;
ICollection<Cipher> folders = await _cipherRepository.GetManyByTypeAndUserIdAsync(Core.Enums.CipherType.Folder,
userId);
var responses = folders.Select(f => new FolderResponseModel(f, userId));
return new ListResponseModel<FolderResponseModel>(responses);
}
[HttpPost("")]
public async Task<FolderResponseModel> 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);
return new FolderResponseModel(folder, userId);
}
[HttpPut("{id}")]
[HttpPost("{id}")]
public async Task<FolderResponseModel> Put(string id, [FromBody]FolderRequestModel model)
{
var folder = await _cipherRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
var userId = _userService.GetProperUserId(User).Value;
var folder = await _cipherRepository.GetByIdAsync(new Guid(id), userId);
if(folder == null || folder.Type != Core.Enums.CipherType.Folder)
{
throw new NotFoundException();
}
await _cipherService.SaveAsync(model.ToCipher(folder));
return new FolderResponseModel(folder);
return new FolderResponseModel(folder, userId);
}
[HttpDelete("{id}")]

View File

@ -36,35 +36,38 @@ namespace Bit.Api.Controllers
[HttpGet("{id}")]
public async Task<LoginResponseModel> Get(string id, string[] expand = null)
{
var login = await _cipherRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
var userId = _userService.GetProperUserId(User).Value;
var login = await _cipherRepository.GetByIdAsync(new Guid(id), userId);
if(login == null || login.Type != Core.Enums.CipherType.Login)
{
throw new NotFoundException();
}
var response = new LoginResponseModel(login);
await ExpandAsync(login, response, expand, null);
var response = new LoginResponseModel(login, userId);
await ExpandAsync(login, response, expand, null, userId);
return response;
}
[HttpGet("")]
public async Task<ListResponseModel<LoginResponseModel>> Get(string[] expand = null)
{
var userId = _userService.GetProperUserId(User).Value;
ICollection<Cipher> logins = await _cipherRepository.GetManyByTypeAndUserIdAsync(Core.Enums.CipherType.Login,
_userService.GetProperUserId(User).Value);
var responses = logins.Select(s => new LoginResponseModel(s)).ToList();
await ExpandManyAsync(logins, responses, expand, null);
userId);
var responses = logins.Select(s => new LoginResponseModel(s, userId)).ToList();
await ExpandManyAsync(logins, responses, expand, null, userId);
return new ListResponseModel<LoginResponseModel>(responses);
}
[HttpPost("")]
public async Task<LoginResponseModel> Post([FromBody]LoginRequestModel model, string[] expand = null)
{
var login = model.ToCipher(_userService.GetProperUserId(User).Value);
var userId = _userService.GetProperUserId(User).Value;
var login = model.ToCipher(userId);
await _cipherService.SaveAsync(login);
var response = new LoginResponseModel(login);
await ExpandAsync(login, response, expand, null);
var response = new LoginResponseModel(login, userId);
await ExpandAsync(login, response, expand, null, userId);
return response;
}
@ -72,6 +75,7 @@ namespace Bit.Api.Controllers
[HttpPost("{id}")]
public async Task<LoginResponseModel> Put(string id, [FromBody]LoginRequestModel model, string[] expand = null)
{
var userId = _userService.GetProperUserId(User).Value;
var login = await _cipherRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
if(login == null || login.Type != Core.Enums.CipherType.Login)
{
@ -80,8 +84,8 @@ namespace Bit.Api.Controllers
await _cipherService.SaveAsync(model.ToCipher(login));
var response = new LoginResponseModel(login);
await ExpandAsync(login, response, expand, null);
var response = new LoginResponseModel(login, userId);
await ExpandAsync(login, response, expand, null, userId);
return response;
}
@ -98,7 +102,7 @@ namespace Bit.Api.Controllers
await _cipherService.DeleteAsync(login);
}
private async Task ExpandAsync(Cipher login, LoginResponseModel response, string[] expand, Cipher folder)
private async Task ExpandAsync(Cipher login, LoginResponseModel response, string[] expand, Cipher folder, Guid userId)
{
if(expand == null || expand.Count() == 0)
{
@ -112,12 +116,12 @@ namespace Bit.Api.Controllers
folder = await _cipherRepository.GetByIdAsync(login.FolderId.Value);
}
response.Folder = new FolderResponseModel(folder);
response.Folder = new FolderResponseModel(folder, userId);
}
}
private async Task ExpandManyAsync(IEnumerable<Cipher> logins, ICollection<LoginResponseModel> responses,
string[] expand, IEnumerable<Cipher> folders)
string[] expand, IEnumerable<Cipher> folders, Guid userId)
{
if(expand == null || expand.Count() == 0)
{
@ -148,7 +152,7 @@ namespace Bit.Api.Controllers
continue;
}
response.Folder = new FolderResponseModel(folder);
response.Folder = new FolderResponseModel(folder, userId);
}
}
}

View File

@ -7,7 +7,7 @@ namespace Bit.Api.Models
{
public class CipherHistoryResponseModel : ResponseModel
{
public CipherHistoryResponseModel(IEnumerable<Cipher> revisedCiphers, IEnumerable<Guid> deletedIds)
public CipherHistoryResponseModel(IEnumerable<Cipher> revisedCiphers, IEnumerable<Guid> deletedIds, Guid userId)
: base("cipherHistory")
{
if(revisedCiphers == null)
@ -20,7 +20,7 @@ namespace Bit.Api.Models
throw new ArgumentNullException(nameof(deletedIds));
}
Revised = revisedCiphers.Select(c => new CipherResponseModel(c));
Revised = revisedCiphers.Select(c => new CipherResponseModel(c, userId));
Deleted = deletedIds.Select(id => id.ToString());
}

View File

@ -1,11 +1,14 @@
using System;
using Bit.Core.Domains;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Linq;
namespace Bit.Api.Models
{
public class CipherResponseModel : ResponseModel
{
public CipherResponseModel(Cipher cipher)
public CipherResponseModel(Cipher cipher, Guid userId)
: base("cipher")
{
if(cipher == null)
@ -30,6 +33,16 @@ namespace Bit.Api.Models
default:
throw new ArgumentException("Unsupported " + nameof(Type) + ".");
}
if(!string.IsNullOrWhiteSpace(cipher.Shares))
{
var shares = JsonConvert.DeserializeObject<IEnumerable<Cipher.Share>>(cipher.Shares);
var userShare = shares.FirstOrDefault(s => s.UserId == userId);
if(userShare != null)
{
Key = userShare.Key;
}
}
}
public string Id { get; set; }
@ -37,6 +50,7 @@ namespace Bit.Api.Models
public Core.Enums.CipherType Type { get; set; }
public bool Favorite { get; set; }
public dynamic Data { get; set; }
public string Key { get; set; }
public DateTime RevisionDate { get; set; }
}
}

View File

@ -1,11 +1,14 @@
using System;
using Bit.Core.Domains;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
namespace Bit.Api.Models
{
public class FolderResponseModel : ResponseModel
{
public FolderResponseModel(Cipher cipher)
public FolderResponseModel(Cipher cipher, Guid userId)
: base("folder")
{
if(cipher == null)
@ -23,10 +26,21 @@ namespace Bit.Api.Models
Id = cipher.Id.ToString();
Name = data.Name;
RevisionDate = cipher.RevisionDate;
if(!string.IsNullOrWhiteSpace(cipher.Shares))
{
var shares = JsonConvert.DeserializeObject<IEnumerable<Cipher.Share>>(cipher.Shares);
var userShare = shares.FirstOrDefault(s => s.UserId == userId);
if(userShare != null)
{
Key = userShare.Key;
}
}
}
public string Id { get; set; }
public string Name { get; set; }
public string Key { get; set; }
public DateTime RevisionDate { get; set; }
}
}

View File

@ -1,11 +1,14 @@
using System;
using Bit.Core.Domains;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
namespace Bit.Api.Models
{
public class LoginResponseModel : ResponseModel
{
public LoginResponseModel(Cipher cipher)
public LoginResponseModel(Cipher cipher, Guid userId)
: base("login")
{
if(cipher == null)
@ -29,6 +32,16 @@ namespace Bit.Api.Models
Password = data.Password;
Notes = data.Notes;
RevisionDate = cipher.RevisionDate;
if(!string.IsNullOrWhiteSpace(cipher.Shares))
{
var shares = JsonConvert.DeserializeObject<IEnumerable<Cipher.Share>>(cipher.Shares);
var userShare = shares.FirstOrDefault(s => s.UserId == userId);
if(userShare != null)
{
Key = userShare.Key;
}
}
}
public string Id { get; set; }
@ -39,6 +52,7 @@ namespace Bit.Api.Models
public string Username { get; set; }
public string Password { get; set; }
public string Notes { get; set; }
public string Key { get; set; }
public DateTime RevisionDate { get; set; }
// Expandables

View File

@ -11,6 +11,7 @@ namespace Bit.Core.Domains
public Enums.CipherType Type { get; set; }
public bool Favorite { get; set; }
public string Data { get; set; }
public string Shares { get; set; }
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
@ -18,5 +19,12 @@ namespace Bit.Core.Domains
{
Id = CoreHelpers.GenerateComb();
}
public class Share
{
public Guid UserId { get; set; }
public string Key { get; set; }
// TODO: permission flags?
}
}
}

View File

@ -104,4 +104,7 @@
<Build Include="dbo\Stored Procedures\Grant_Save.sql" />
<Build Include="dbo\Stored Procedures\User_ReadAccountRevisionDateById.sql" />
</ItemGroup>
<ItemGroup>
<RefactorLog Include="Sql.refactorlog" />
</ItemGroup>
</Project>

View File

@ -5,6 +5,7 @@
@Type TINYINT,
@Favorite BIT,
@Data NVARCHAR(MAX),
@Shares NVARCHAR(MAX),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7)
AS
@ -19,6 +20,7 @@ BEGIN
[Type],
[Favorite],
[Data],
[Shares],
[CreationDate],
[RevisionDate]
)
@ -30,6 +32,7 @@ BEGIN
@Type,
@Favorite,
@Data,
@Shares,
@CreationDate,
@RevisionDate
)

View File

@ -5,6 +5,7 @@
@Type TINYINT,
@Favorite BIT,
@Data NVARCHAR(MAX),
@Shares NVARCHAR(MAX),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7)
AS
@ -19,6 +20,7 @@ BEGIN
[Type] = @Type,
[Favorite] = @Favorite,
[Data] = @Data,
[Shares] = @Shares,
[CreationDate] = @CreationDate,
[RevisionDate] = @RevisionDate
WHERE

View File

@ -5,6 +5,7 @@
[Type] TINYINT NOT NULL,
[Favorite] BIT NOT NULL,
[Data] NVARCHAR (MAX) NOT NULL,
[Shares] NVARCHAR (MAX) NULL,
[CreationDate] DATETIME2 (7) NOT NULL,
[RevisionDate] DATETIME2 (7) NOT NULL,
CONSTRAINT [PK_Cipher] PRIMARY KEY CLUSTERED ([Id] ASC),