mirror of
https://github.com/bitwarden/server.git
synced 2025-04-21 13:05:11 -05:00
return share information with cipher API response
This commit is contained in:
parent
8051995cc7
commit
900e71d4dd
@ -31,27 +31,28 @@ namespace Bit.Api.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<CipherResponseModel> Get(string id)
|
public async Task<CipherShareResponseModel> Get(string id)
|
||||||
{
|
{
|
||||||
var userId = _userService.GetProperUserId(User).Value;
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
var cipher = await _cipherRepository.GetByIdAsync(new Guid(id), userId);
|
var cipher = await _cipherRepository.GetShareByIdAsync(new Guid(id), userId);
|
||||||
if(cipher == null)
|
if(cipher == null)
|
||||||
{
|
{
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CipherResponseModel(cipher, userId);
|
return new CipherShareResponseModel(cipher, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
public async Task<ListResponseModel<CipherResponseModel>> Get()
|
public async Task<ListResponseModel<CipherShareResponseModel>> Get()
|
||||||
{
|
{
|
||||||
var userId = _userService.GetProperUserId(User).Value;
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
var ciphers = await _cipherRepository.GetManyByUserIdAsync(userId);
|
var ciphers = await _cipherRepository.GetManyShareByUserIdAsync(userId);
|
||||||
var responses = ciphers.Select(c => new CipherResponseModel(c, userId));
|
var responses = ciphers.Select(c => new CipherShareResponseModel(c, userId));
|
||||||
return new ListResponseModel<CipherResponseModel>(responses);
|
return new ListResponseModel<CipherShareResponseModel>(responses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
[HttpGet("history")]
|
[HttpGet("history")]
|
||||||
public async Task<CipherHistoryResponseModel> Get(DateTime since)
|
public async Task<CipherHistoryResponseModel> Get(DateTime since)
|
||||||
{
|
{
|
||||||
|
@ -118,13 +118,16 @@ namespace Bit.Api.IdentityServer
|
|||||||
claims.Add(new Claim("device", device.Identifier));
|
claims.Add(new Claim("device", device.Identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var customResponse = new Dictionary<string, object>();
|
||||||
|
if(!string.IsNullOrWhiteSpace(user.PrivateKey))
|
||||||
|
{
|
||||||
|
customResponse.Add("EncryptedPrivateKey", user.PrivateKey);
|
||||||
|
}
|
||||||
|
|
||||||
context.Result = new GrantValidationResult(user.Id.ToString(), "Application",
|
context.Result = new GrantValidationResult(user.Id.ToString(), "Application",
|
||||||
identityProvider: "bitwarden",
|
identityProvider: "bitwarden",
|
||||||
claims: claims.Count > 0 ? claims : null,
|
claims: claims.Count > 0 ? claims : null,
|
||||||
customResponse: new Dictionary<string, object>
|
customResponse: customResponse);
|
||||||
{
|
|
||||||
{ "EncryptedPrivateKey", user.PrivateKey }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildTwoFactorResult(User user, ResourceOwnerPasswordValidationContext context)
|
private void BuildTwoFactorResult(User user, ResourceOwnerPasswordValidationContext context)
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using Bit.Core.Domains;
|
using Bit.Core.Domains;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Bit.Api.Models
|
namespace Bit.Api.Models
|
||||||
{
|
{
|
||||||
public class CipherResponseModel : ResponseModel
|
public class CipherResponseModel : ResponseModel
|
||||||
{
|
{
|
||||||
public CipherResponseModel(Cipher cipher, Guid userId)
|
public CipherResponseModel(Cipher cipher, Guid userId, string obj = "cipher")
|
||||||
: base("cipher")
|
: base(obj)
|
||||||
{
|
{
|
||||||
if(cipher == null)
|
if(cipher == null)
|
||||||
{
|
{
|
||||||
@ -40,7 +40,22 @@ namespace Bit.Api.Models
|
|||||||
public Core.Enums.CipherType Type { get; set; }
|
public Core.Enums.CipherType Type { get; set; }
|
||||||
public bool Favorite { get; set; }
|
public bool Favorite { get; set; }
|
||||||
public dynamic Data { get; set; }
|
public dynamic Data { get; set; }
|
||||||
public string Key { get; set; }
|
|
||||||
public DateTime RevisionDate { get; set; }
|
public DateTime RevisionDate { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CipherShareResponseModel : CipherResponseModel
|
||||||
|
{
|
||||||
|
public CipherShareResponseModel(CipherShare cipherShare, Guid userId)
|
||||||
|
: base(cipherShare, userId, "cipherShare")
|
||||||
|
{
|
||||||
|
Key = cipherShare.Key;
|
||||||
|
Permissions = cipherShare.Permissions == null ? null :
|
||||||
|
JsonConvert.DeserializeObject<IEnumerable<Core.Enums.SharePermissionType>>(cipherShare.Permissions);
|
||||||
|
Status = cipherShare.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Key { get; set; }
|
||||||
|
public IEnumerable<Core.Enums.SharePermissionType> Permissions { get; set; }
|
||||||
|
public Core.Enums.ShareStatusType? Status { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
src/Core/Enums/SharePermissionType.cs
Normal file
8
src/Core/Enums/SharePermissionType.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Bit.Core.Enums
|
||||||
|
{
|
||||||
|
public enum SharePermissionType : byte
|
||||||
|
{
|
||||||
|
Reshare = 0,
|
||||||
|
Edit = 1
|
||||||
|
}
|
||||||
|
}
|
11
src/Core/Models/Data/CipherShare.cs
Normal file
11
src/Core/Models/Data/CipherShare.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Bit.Core.Domains;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Data
|
||||||
|
{
|
||||||
|
public class CipherShare : Cipher
|
||||||
|
{
|
||||||
|
public string Key { get; internal set; }
|
||||||
|
public string Permissions { get; internal set; }
|
||||||
|
public Enums.ShareStatusType? Status { get; internal set; }
|
||||||
|
}
|
||||||
|
}
|
@ -2,13 +2,16 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.Core.Domains;
|
using Bit.Core.Domains;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
|
||||||
namespace Bit.Core.Repositories
|
namespace Bit.Core.Repositories
|
||||||
{
|
{
|
||||||
public interface ICipherRepository : IRepository<Cipher, Guid>
|
public interface ICipherRepository : IRepository<Cipher, Guid>
|
||||||
{
|
{
|
||||||
Task<Cipher> GetByIdAsync(Guid id, Guid userId);
|
Task<Cipher> GetByIdAsync(Guid id, Guid userId);
|
||||||
|
Task<CipherShare> GetShareByIdAsync(Guid id, Guid userId);
|
||||||
Task<ICollection<Cipher>> GetManyByUserIdAsync(Guid userId);
|
Task<ICollection<Cipher>> GetManyByUserIdAsync(Guid userId);
|
||||||
|
Task<ICollection<CipherShare>> GetManyShareByUserIdAsync(Guid userId);
|
||||||
Task<ICollection<Cipher>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId);
|
Task<ICollection<Cipher>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId);
|
||||||
Task<Tuple<ICollection<Cipher>, ICollection<Guid>>>
|
Task<Tuple<ICollection<Cipher>, ICollection<Guid>>>
|
||||||
GetManySinceRevisionDateAndUserIdWithDeleteHistoryAsync(DateTime sinceRevisionDate, Guid userId);
|
GetManySinceRevisionDateAndUserIdWithDeleteHistoryAsync(DateTime sinceRevisionDate, Guid userId);
|
||||||
|
@ -7,6 +7,7 @@ using DataTableProxy;
|
|||||||
using Bit.Core.Domains;
|
using Bit.Core.Domains;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
|
||||||
namespace Bit.Core.Repositories.SqlServer
|
namespace Bit.Core.Repositories.SqlServer
|
||||||
{
|
{
|
||||||
@ -31,6 +32,19 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
return cipher;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<CipherShare> GetShareByIdAsync(Guid id, Guid userId)
|
||||||
|
{
|
||||||
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
var results = await connection.QueryAsync<CipherShare>(
|
||||||
|
$"[{Schema}].[CipherShare_ReadById]",
|
||||||
|
new { UserId = userId },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return results.FirstOrDefault(c => c.UserId == userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Cipher>> GetManyByUserIdAsync(Guid userId)
|
public async Task<ICollection<Cipher>> GetManyByUserIdAsync(Guid userId)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
@ -44,6 +58,19 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ICollection<CipherShare>> GetManyShareByUserIdAsync(Guid userId)
|
||||||
|
{
|
||||||
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
var results = await connection.QueryAsync<CipherShare>(
|
||||||
|
$"[{Schema}].[CipherShare_ReadByUserId]",
|
||||||
|
new { UserId = userId },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return results.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Cipher>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId)
|
public async Task<ICollection<Cipher>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
@ -109,5 +109,8 @@
|
|||||||
<Build Include="dbo\Stored Procedures\Grant_ReadBySubjectId.sql" />
|
<Build Include="dbo\Stored Procedures\Grant_ReadBySubjectId.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\Grant_Save.sql" />
|
<Build Include="dbo\Stored Procedures\Grant_Save.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\User_ReadAccountRevisionDateById.sql" />
|
<Build Include="dbo\Stored Procedures\User_ReadAccountRevisionDateById.sql" />
|
||||||
|
<Build Include="dbo\Views\CipherShareView.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\CipherShare_ReadByUserId.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\CipherShare_ReadById.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
13
src/Sql/dbo/Stored Procedures/CipherShare_ReadById.sql
Normal file
13
src/Sql/dbo/Stored Procedures/CipherShare_ReadById.sql
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[CipherShare_ReadById]
|
||||||
|
@Id UNIQUEIDENTIFIER
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
[dbo].[CipherShareView]
|
||||||
|
WHERE
|
||||||
|
[Id] = @Id
|
||||||
|
END
|
13
src/Sql/dbo/Stored Procedures/CipherShare_ReadByUserId.sql
Normal file
13
src/Sql/dbo/Stored Procedures/CipherShare_ReadByUserId.sql
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[CipherShare_ReadByUserId]
|
||||||
|
@UserId UNIQUEIDENTIFIER
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
[dbo].[CipherShareView]
|
||||||
|
WHERE
|
||||||
|
[UserId] = @UserId
|
||||||
|
END
|
11
src/Sql/dbo/Views/CipherShareView.sql
Normal file
11
src/Sql/dbo/Views/CipherShareView.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
CREATE VIEW [dbo].[CipherShareView]
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
C.*,
|
||||||
|
S.[Key],
|
||||||
|
S.[Permissions],
|
||||||
|
S.[Status]
|
||||||
|
FROM
|
||||||
|
[dbo].[Cipher] C
|
||||||
|
LEFT JOIN
|
||||||
|
[dbo].[Share] S ON C.[Id] = S.[CipherId]
|
Loading…
x
Reference in New Issue
Block a user