mirror of
https://github.com/bitwarden/server.git
synced 2025-02-17 02:01:53 +01:00
apis for org vault listing
This commit is contained in:
parent
5b76c43fb0
commit
0e5799f7c8
@ -85,6 +85,25 @@ namespace Bit.Api.Controllers
|
|||||||
return new ListResponseModel<CipherDetailsResponseModel>(responses);
|
return new ListResponseModel<CipherDetailsResponseModel>(responses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("organization-details")]
|
||||||
|
public async Task<ListResponseModel<CipherMiniDetailsResponseModel>> GetOrganizationSubvaults(string organizationId)
|
||||||
|
{
|
||||||
|
var userId = _userService.GetProperUserId(User).Value;
|
||||||
|
var orgIdGuid = new Guid(organizationId);
|
||||||
|
if(!_currentContext.OrganizationAdmin(orgIdGuid))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var ciphers = await _cipherRepository.GetManyByOrganizationIdAsync(orgIdGuid);
|
||||||
|
|
||||||
|
var subvaultCiphers = await _subvaultCipherRepository.GetManyByOrganizationIdAsync(orgIdGuid);
|
||||||
|
var subvaultCiphersGroupDict = subvaultCiphers.GroupBy(s => s.CipherId).ToDictionary(s => s.Key);
|
||||||
|
|
||||||
|
var responses = ciphers.Select(c => new CipherMiniDetailsResponseModel(c, subvaultCiphersGroupDict));
|
||||||
|
return new ListResponseModel<CipherMiniDetailsResponseModel>(responses);
|
||||||
|
}
|
||||||
|
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
[HttpGet("history")]
|
[HttpGet("history")]
|
||||||
public Task<CipherHistoryResponseModel> Get(DateTime since)
|
public Task<CipherHistoryResponseModel> Get(DateTime since)
|
||||||
@ -116,7 +135,7 @@ namespace Bit.Api.Controllers
|
|||||||
{
|
{
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _cipherService.UpdatePartialAsync(new Guid(id), userId, cipher.FolderId, !cipher.Favorite);
|
await _cipherService.UpdatePartialAsync(new Guid(id), userId, cipher.FolderId, !cipher.Favorite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Bit.Core.Models.Api
|
namespace Bit.Core.Models.Api
|
||||||
{
|
{
|
||||||
public class CipherResponseModel : ResponseModel
|
public class CipherMiniResponseModel : ResponseModel
|
||||||
{
|
{
|
||||||
public CipherResponseModel(CipherDetails cipher, string obj = "cipher")
|
public CipherMiniResponseModel(Cipher cipher, string obj = "cipherMini")
|
||||||
: base(obj)
|
: base(obj)
|
||||||
{
|
{
|
||||||
if(cipher == null)
|
if(cipher == null)
|
||||||
@ -20,8 +20,6 @@ namespace Bit.Core.Models.Api
|
|||||||
Type = cipher.Type;
|
Type = cipher.Type;
|
||||||
RevisionDate = cipher.RevisionDate;
|
RevisionDate = cipher.RevisionDate;
|
||||||
OrganizationId = cipher.OrganizationId?.ToString();
|
OrganizationId = cipher.OrganizationId?.ToString();
|
||||||
FolderId = cipher.FolderId?.ToString();
|
|
||||||
Favorite = cipher.Favorite;
|
|
||||||
|
|
||||||
switch(cipher.Type)
|
switch(cipher.Type)
|
||||||
{
|
{
|
||||||
@ -35,13 +33,24 @@ namespace Bit.Core.Models.Api
|
|||||||
|
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public string OrganizationId { get; set; }
|
public string OrganizationId { get; set; }
|
||||||
public string FolderId { get; set; }
|
|
||||||
public Enums.CipherType Type { get; set; }
|
public Enums.CipherType Type { get; set; }
|
||||||
public bool Favorite { get; set; }
|
|
||||||
public dynamic Data { get; set; }
|
public dynamic Data { get; set; }
|
||||||
public DateTime RevisionDate { get; set; }
|
public DateTime RevisionDate { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CipherResponseModel : CipherMiniResponseModel
|
||||||
|
{
|
||||||
|
public CipherResponseModel(CipherDetails cipher, string obj = "cipher")
|
||||||
|
: base(cipher, obj)
|
||||||
|
{
|
||||||
|
FolderId = cipher.FolderId?.ToString();
|
||||||
|
Favorite = cipher.Favorite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FolderId { get; set; }
|
||||||
|
public bool Favorite { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class CipherDetailsResponseModel : CipherResponseModel
|
public class CipherDetailsResponseModel : CipherResponseModel
|
||||||
{
|
{
|
||||||
public CipherDetailsResponseModel(CipherDetails cipher,
|
public CipherDetailsResponseModel(CipherDetails cipher,
|
||||||
@ -68,6 +77,25 @@ namespace Bit.Core.Models.Api
|
|||||||
public IEnumerable<Guid> SubvaultIds { get; set; }
|
public IEnumerable<Guid> SubvaultIds { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CipherMiniDetailsResponseModel : CipherMiniResponseModel
|
||||||
|
{
|
||||||
|
public CipherMiniDetailsResponseModel(Cipher cipher,
|
||||||
|
IDictionary<Guid, IGrouping<Guid, SubvaultCipher>> subvaultCiphers, string obj = "cipherMiniDetails")
|
||||||
|
: base(cipher, obj)
|
||||||
|
{
|
||||||
|
if(subvaultCiphers.ContainsKey(cipher.Id))
|
||||||
|
{
|
||||||
|
SubvaultIds = subvaultCiphers[cipher.Id].Select(s => s.SubvaultId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SubvaultIds = new Guid[] { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Guid> SubvaultIds { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class CipherFullDetailsResponseModel : CipherDetailsResponseModel
|
public class CipherFullDetailsResponseModel : CipherDetailsResponseModel
|
||||||
{
|
{
|
||||||
public CipherFullDetailsResponseModel(CipherFullDetails cipher, IEnumerable<SubvaultCipher> subvaultCiphers)
|
public CipherFullDetailsResponseModel(CipherFullDetails cipher, IEnumerable<SubvaultCipher> subvaultCiphers)
|
||||||
|
@ -12,6 +12,7 @@ namespace Bit.Core.Repositories
|
|||||||
Task<CipherFullDetails> GetFullDetailsByIdAsync(Guid id, Guid userId);
|
Task<CipherFullDetails> GetFullDetailsByIdAsync(Guid id, Guid userId);
|
||||||
Task<ICollection<CipherDetails>> GetManyByUserIdAsync(Guid userId);
|
Task<ICollection<CipherDetails>> GetManyByUserIdAsync(Guid userId);
|
||||||
Task<ICollection<CipherDetails>> GetManyByUserIdHasSubvaultsAsync(Guid userId);
|
Task<ICollection<CipherDetails>> GetManyByUserIdHasSubvaultsAsync(Guid userId);
|
||||||
|
Task<ICollection<Cipher>> GetManyByOrganizationIdAsync(Guid organizationId);
|
||||||
Task<ICollection<CipherDetails>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId);
|
Task<ICollection<CipherDetails>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId);
|
||||||
Task CreateAsync(CipherDetails cipher);
|
Task CreateAsync(CipherDetails cipher);
|
||||||
Task ReplaceAsync(CipherDetails cipher);
|
Task ReplaceAsync(CipherDetails cipher);
|
||||||
|
@ -8,6 +8,7 @@ namespace Bit.Core.Repositories
|
|||||||
public interface ISubvaultCipherRepository
|
public interface ISubvaultCipherRepository
|
||||||
{
|
{
|
||||||
Task<ICollection<SubvaultCipher>> GetManyByUserIdAsync(Guid userId);
|
Task<ICollection<SubvaultCipher>> GetManyByUserIdAsync(Guid userId);
|
||||||
|
Task<ICollection<SubvaultCipher>> GetManyByOrganizationIdAsync(Guid organizationId);
|
||||||
Task<ICollection<SubvaultCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId);
|
Task<ICollection<SubvaultCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId);
|
||||||
Task UpdateSubvaultsAsync(Guid cipherId, Guid userId, IEnumerable<Guid> subvaultIds);
|
Task UpdateSubvaultsAsync(Guid cipherId, Guid userId, IEnumerable<Guid> subvaultIds);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,19 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ICollection<Cipher>> GetManyByOrganizationIdAsync(Guid organizationId)
|
||||||
|
{
|
||||||
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
var results = await connection.QueryAsync<Cipher>(
|
||||||
|
$"[{Schema}].[Cipher_ReadByOrganizationId]",
|
||||||
|
new { OrganizationId = organizationId },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return results.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ICollection<CipherDetails>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId)
|
public async Task<ICollection<CipherDetails>> GetManyByTypeAndUserIdAsync(Enums.CipherType type, Guid userId)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
@ -33,6 +33,19 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ICollection<SubvaultCipher>> GetManyByOrganizationIdAsync(Guid organizationId)
|
||||||
|
{
|
||||||
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
var results = await connection.QueryAsync<SubvaultCipher>(
|
||||||
|
"[dbo].[SubvaultCipher_ReadByOrganizationId]",
|
||||||
|
new { OrganizationId = organizationId },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return results.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ICollection<SubvaultCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId)
|
public async Task<ICollection<SubvaultCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
@ -174,5 +174,7 @@
|
|||||||
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadById.sql" />
|
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadById.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadByOrganizationId.sql" />
|
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadByOrganizationId.sql" />
|
||||||
<Build Include="dbo\User Defined Types\GuidIdArray.sql" />
|
<Build Include="dbo\User Defined Types\GuidIdArray.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\Cipher_ReadByOrganizationId.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\SubvaultCipher_ReadByOrganizationId.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -0,0 +1,13 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[Cipher_ReadByOrganizationId]
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
[dbo].[CipherView]
|
||||||
|
WHERE
|
||||||
|
[OrganizationId] = @OrganizationId
|
||||||
|
END
|
@ -0,0 +1,15 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[SubvaultCipher_ReadByOrganizationId]
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
SC.*
|
||||||
|
FROM
|
||||||
|
[dbo].[SubvaultCipher] SC
|
||||||
|
INNER JOIN
|
||||||
|
[dbo].[Subvault] S ON S.[Id] = SC.[SubvaultId]
|
||||||
|
WHERE
|
||||||
|
S.[OrganizationId] = @OrganizationId
|
||||||
|
END
|
@ -18,6 +18,12 @@ CREATE NONCLUSTERED INDEX [IX_Cipher_UserId_Type]
|
|||||||
ON [dbo].[Cipher]([UserId] ASC, [Type] ASC);
|
ON [dbo].[Cipher]([UserId] ASC, [Type] ASC);
|
||||||
|
|
||||||
|
|
||||||
|
GO
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_Cipher_OrganizationId_Type]
|
||||||
|
ON [dbo].[Cipher]([OrganizationId] ASC, [Type] ASC)
|
||||||
|
WHERE [OrganizationId] IS NOT NULL;
|
||||||
|
|
||||||
|
|
||||||
GO
|
GO
|
||||||
CREATE TRIGGER [dbo].[Cipher_Inserted]
|
CREATE TRIGGER [dbo].[Cipher_Inserted]
|
||||||
ON [dbo].[Cipher] AFTER INSERT
|
ON [dbo].[Cipher] AFTER INSERT
|
||||||
|
Loading…
Reference in New Issue
Block a user