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:
parent
f7be17d1c5
commit
2b72197f0a
1
.gitignore
vendored
1
.gitignore
vendored
@ -200,3 +200,4 @@ FakesAssemblies/
|
||||
project.lock.json
|
||||
*.jfm
|
||||
mail_dist/
|
||||
*.refactorlog
|
@ -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")]
|
||||
|
@ -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}")]
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user