mirror of
https://github.com/bitwarden/server.git
synced 2025-02-02 23:41:21 +01:00
subvault user apis
This commit is contained in:
parent
0961d86d65
commit
f1fc7832a0
54
src/Api/Controllers/SubvaultUsersController.cs
Normal file
54
src/Api/Controllers/SubvaultUsersController.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
[Route("organizations/{orgId}/subvaultUsers")]
|
||||
[Authorize("Application")]
|
||||
public class SubvaultUsersController : Controller
|
||||
{
|
||||
private readonly ISubvaultRepository _subvaultRepository;
|
||||
private readonly ISubvaultUserRepository _subvaultUserRepository;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public SubvaultUsersController(
|
||||
ISubvaultRepository subvaultRepository,
|
||||
ISubvaultUserRepository subvaultUserRepository,
|
||||
IUserService userService)
|
||||
{
|
||||
_subvaultRepository = subvaultRepository;
|
||||
_subvaultUserRepository = subvaultUserRepository;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
[HttpGet("{subvaultId}")]
|
||||
public async Task<ListResponseModel<SubvaultUserResponseModel>> GetBySubvault(string orgId, string subvaultId)
|
||||
{
|
||||
// TODO: permission check
|
||||
var subvaultUsers = await _subvaultUserRepository.GetManyDetailsBySubvaultIdAsync(new Guid(subvaultId));
|
||||
var responses = subvaultUsers.Select(s => new SubvaultUserResponseModel(s));
|
||||
return new ListResponseModel<SubvaultUserResponseModel>(responses);
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[HttpPost("{id}/delete")]
|
||||
public async Task Delete(string orgId, string id)
|
||||
{
|
||||
var user = await _subvaultUserRepository.GetByIdAsync(new Guid(id));
|
||||
if(user == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
// TODO: permission check
|
||||
await _subvaultUserRepository.DeleteAsync(user);
|
||||
}
|
||||
}
|
||||
}
|
@ -198,6 +198,7 @@ namespace Bit.Api
|
||||
services.AddScoped<IDeviceService, DeviceService>();
|
||||
services.AddScoped<IBlockIpService, AzureQueueBlockIpService>();
|
||||
services.AddScoped<IOrganizationService, OrganizationService>();
|
||||
services.AddScoped<ISubvaultService, SubvaultService>();
|
||||
|
||||
// Cors
|
||||
services.AddCors(config =>
|
||||
|
@ -35,7 +35,7 @@ namespace Bit.Core.Models.Api
|
||||
public class OrganizationUserDetailsResponseModel : OrganizationUserResponseModel
|
||||
{
|
||||
public OrganizationUserDetailsResponseModel(OrganizationUserUserDetails organizationUser,
|
||||
IEnumerable<SubvaultUserDetails> subvaults)
|
||||
IEnumerable<SubvaultUserSubvaultDetails> subvaults)
|
||||
: base(organizationUser, "organizationUserDetails")
|
||||
{
|
||||
Subvaults = new ListResponseModel<OrganizationUserSubvaultResponseModel>(
|
||||
|
@ -5,7 +5,7 @@ namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class OrganizationUserSubvaultResponseModel : ResponseModel
|
||||
{
|
||||
public OrganizationUserSubvaultResponseModel(SubvaultUserDetails details,
|
||||
public OrganizationUserSubvaultResponseModel(SubvaultUserSubvaultDetails details,
|
||||
string obj = "organizationUserSubvault")
|
||||
: base(obj)
|
||||
{
|
||||
|
39
src/Core/Models/Api/Response/SubvaultUserResponseModel.cs
Normal file
39
src/Core/Models/Api/Response/SubvaultUserResponseModel.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class SubvaultUserResponseModel : ResponseModel
|
||||
{
|
||||
public SubvaultUserResponseModel(SubvaultUserUserDetails subvaultUser)
|
||||
: base("subvaultUser")
|
||||
{
|
||||
if(subvaultUser == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(subvaultUser));
|
||||
}
|
||||
|
||||
Id = subvaultUser.Id.ToString();
|
||||
OrganizationUserId = subvaultUser.OrganizationUserId.ToString();
|
||||
SubvaultId = subvaultUser.SubvaultId.ToString();
|
||||
Name = subvaultUser.Name;
|
||||
Email = subvaultUser.Email;
|
||||
Type = subvaultUser.Type;
|
||||
Status = subvaultUser.Status;
|
||||
ReadOnly = subvaultUser.ReadOnly;
|
||||
Admin = subvaultUser.Admin;
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string OrganizationUserId { get; set; }
|
||||
public string SubvaultId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public OrganizationUserType Type { get; set; }
|
||||
public OrganizationUserStatusType Status { get; set; }
|
||||
public bool ReadOnly { get; set; }
|
||||
public bool Admin { get; set; }
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bit.Core.Models.Data
|
||||
{
|
||||
public class SubvaultUserDetails
|
||||
public class SubvaultUserSubvaultDetails
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid OrganizationUserId { get; set; }
|
17
src/Core/Models/Data/SubvaultUserUserDetails.cs
Normal file
17
src/Core/Models/Data/SubvaultUserUserDetails.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace Bit.Core.Models.Data
|
||||
{
|
||||
public class SubvaultUserUserDetails
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid OrganizationUserId { get; set; }
|
||||
public Guid SubvaultId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public Enums.OrganizationUserStatusType Status { get; set; }
|
||||
public Enums.OrganizationUserType Type { get; set; }
|
||||
public bool ReadOnly { get; set; }
|
||||
public bool Admin { get; set; }
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ namespace Bit.Core.Repositories
|
||||
Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, Guid userId);
|
||||
Task<ICollection<OrganizationUser>> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type);
|
||||
Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, string email);
|
||||
Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserDetails>>> GetDetailsByIdAsync(Guid id);
|
||||
Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserSubvaultDetails>>> GetDetailsByIdAsync(Guid id);
|
||||
Task<ICollection<OrganizationUserUserDetails>> GetManyDetailsByOrganizationAsync(Guid organizationId);
|
||||
Task<ICollection<OrganizationUserOrganizationDetails>> GetManyDetailsByUserAsync(Guid userId,
|
||||
OrganizationUserStatusType? status = null);
|
||||
|
@ -9,7 +9,8 @@ namespace Bit.Core.Repositories
|
||||
public interface ISubvaultUserRepository : IRepository<SubvaultUser, Guid>
|
||||
{
|
||||
Task<ICollection<SubvaultUser>> GetManyByOrganizationUserIdAsync(Guid orgUserId);
|
||||
Task<ICollection<SubvaultUserDetails>> GetManyDetailsByUserIdAsync(Guid userId);
|
||||
Task<ICollection<SubvaultUserSubvaultDetails>> GetManyDetailsByUserIdAsync(Guid userId);
|
||||
Task<ICollection<SubvaultUserUserDetails>> GetManyDetailsBySubvaultIdAsync(Guid subvaultId);
|
||||
Task<ICollection<SubvaultUserPermissions>> GetPermissionsByUserIdAsync(Guid userId, IEnumerable<Guid> subvaultIds,
|
||||
Guid organizationId);
|
||||
Task<bool> GetCanEditByUserIdCipherIdAsync(Guid userId, Guid cipherId);
|
||||
|
@ -61,7 +61,7 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserDetails>>> GetDetailsByIdAsync(Guid id)
|
||||
public async Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserSubvaultDetails>>> GetDetailsByIdAsync(Guid id)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
@ -71,8 +71,8 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
var user = (await results.ReadAsync<OrganizationUserUserDetails>()).SingleOrDefault();
|
||||
var subvaults = (await results.ReadAsync<SubvaultUserDetails>()).ToList();
|
||||
return new Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserDetails>>(user, subvaults);
|
||||
var subvaults = (await results.ReadAsync<SubvaultUserSubvaultDetails>()).ToList();
|
||||
return new Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserSubvaultDetails>>(user, subvaults);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,12 +34,12 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ICollection<SubvaultUserDetails>> GetManyDetailsByUserIdAsync(Guid userId)
|
||||
public async Task<ICollection<SubvaultUserSubvaultDetails>> GetManyDetailsByUserIdAsync(Guid userId)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var results = await connection.QueryAsync<SubvaultUserDetails>(
|
||||
$"[{Schema}].[SubvaultUserDetails_ReadByUserId]",
|
||||
var results = await connection.QueryAsync<SubvaultUserSubvaultDetails>(
|
||||
$"[{Schema}].[SubvaultUserSubvaultDetails_ReadByUserId]",
|
||||
new { UserId = userId },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
@ -47,6 +47,19 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ICollection<SubvaultUserUserDetails>> GetManyDetailsBySubvaultIdAsync(Guid subvaultId)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var results = await connection.QueryAsync<SubvaultUserUserDetails>(
|
||||
$"[{Schema}].[SubvaultUserUserDetails_ReadBySubvaultId]",
|
||||
new { SubvaultId = subvaultId },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return results.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ICollection<SubvaultUserPermissions>> GetPermissionsByUserIdAsync(Guid userId,
|
||||
IEnumerable<Guid> subvaultIds, Guid organizationId)
|
||||
{
|
||||
|
13
src/Core/Services/ISubvaultService.cs
Normal file
13
src/Core/Services/ISubvaultService.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Table;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public interface ISubvaultService
|
||||
{
|
||||
|
||||
}
|
||||
}
|
40
src/Core/Services/Implementations/SubvaultService.cs
Normal file
40
src/Core/Services/Implementations/SubvaultService.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Exceptions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public class SubvaultService : ISubvaultService
|
||||
{
|
||||
private readonly IOrganizationRepository _organizationRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly ISubvaultRepository _subvaultRepository;
|
||||
private readonly ISubvaultUserRepository _subvaultUserRepository;
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IMailService _mailService;
|
||||
|
||||
public SubvaultService(
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
ISubvaultRepository subvaultRepository,
|
||||
ISubvaultUserRepository subvaultUserRepository,
|
||||
IUserRepository userRepository,
|
||||
IMailService mailService)
|
||||
{
|
||||
_organizationRepository = organizationRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_subvaultRepository = subvaultRepository;
|
||||
_subvaultUserRepository = subvaultUserRepository;
|
||||
_userRepository = userRepository;
|
||||
_mailService = mailService;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -84,7 +84,7 @@
|
||||
<Build Include="dbo\Tables\GroupUser.sql" />
|
||||
<Build Include="dbo\Tables\SubvaultGroup.sql" />
|
||||
<Build Include="dbo\Views\SubvaultUserView.sql" />
|
||||
<Build Include="dbo\Views\SubvaultUserDetailsView.sql" />
|
||||
<Build Include="dbo\Views\SubvaultUserSubvaultDetailsView.sql" />
|
||||
<Build Include="dbo\Views\DeviceView.sql" />
|
||||
<Build Include="dbo\Views\HistoryView.sql" />
|
||||
<Build Include="dbo\Views\FolderView.sql" />
|
||||
@ -99,7 +99,7 @@
|
||||
<Build Include="dbo\Functions\CipherDetails.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Subvault_ReadByOrganizationId.sql" />
|
||||
<Build Include="dbo\Stored Procedures\SubvaultUser_ReadByOrganizationUserId.sql" />
|
||||
<Build Include="dbo\Stored Procedures\SubvaultUserDetails_ReadByUserId.sql" />
|
||||
<Build Include="dbo\Stored Procedures\SubvaultUserSubvaultDetails_ReadByUserId.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Cipher_Create.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Cipher_DeleteById.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Favorite_Create.sql" />
|
||||
@ -180,5 +180,7 @@
|
||||
<Build Include="dbo\Stored Procedures\OrganizationUser_ReadByOrganizationIdEmail.sql" />
|
||||
<Build Include="dbo\Stored Procedures\OrganizationUser_ReadByOrganizationId.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Subvault_ReadByIdAdminUserId.sql" />
|
||||
<Build Include="dbo\Views\SubvaultUserUserDetailsView.sql" />
|
||||
<Build Include="dbo\Stored Procedures\SubvaultUserUserDetails_ReadBySubvaultId.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -14,7 +14,7 @@ BEGIN
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
[dbo].[SubvaultUserDetailsView]
|
||||
[dbo].[SubvaultUserSubvaultDetailsView]
|
||||
WHERE
|
||||
[OrganizationUserId] = @Id
|
||||
END
|
@ -1,4 +1,4 @@
|
||||
CREATE PROCEDURE [dbo].[SubvaultUserDetails_ReadByUserId]
|
||||
CREATE PROCEDURE [dbo].[SubvaultUserSubvaultDetails_ReadByUserId]
|
||||
@UserId UNIQUEIDENTIFIER
|
||||
AS
|
||||
BEGIN
|
||||
@ -7,7 +7,7 @@ BEGIN
|
||||
SELECT
|
||||
SU.*
|
||||
FROM
|
||||
[dbo].[SubvaultUserDetailsView] SU
|
||||
[dbo].[SubvaultUserSubvaultDetailsView] SU
|
||||
INNER JOIN
|
||||
[OrganizationUser] OU ON SU.[OrganizationUserId] = OU.[Id]
|
||||
WHERE
|
@ -0,0 +1,15 @@
|
||||
CREATE PROCEDURE [dbo].[SubvaultUserUserDetails_ReadBySubvaultId]
|
||||
@SubvaultId UNIQUEIDENTIFIER
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
SU.*
|
||||
FROM
|
||||
[dbo].[SubvaultUserUserDetailsView] SU
|
||||
INNER JOIN
|
||||
[OrganizationUser] OU ON SU.[OrganizationUserId] = OU.[Id]
|
||||
WHERE
|
||||
SU.[SubvaultId] = @SubvaultId
|
||||
END
|
@ -1,4 +1,4 @@
|
||||
CREATE VIEW [dbo].[SubvaultUserDetailsView]
|
||||
CREATE VIEW [dbo].[SubvaultUserSubvaultDetailsView]
|
||||
AS
|
||||
SELECT
|
||||
SU.[Id],
|
18
src/Sql/dbo/Views/SubvaultUserUserDetailsView.sql
Normal file
18
src/Sql/dbo/Views/SubvaultUserUserDetailsView.sql
Normal file
@ -0,0 +1,18 @@
|
||||
CREATE VIEW [dbo].[SubvaultUserUserDetailsView]
|
||||
AS
|
||||
SELECT
|
||||
SU.[Id],
|
||||
SU.[OrganizationUserId],
|
||||
SU.[SubvaultId],
|
||||
U.[Name],
|
||||
ISNULL(U.[Email], OU.[Email]) Email,
|
||||
OU.[Status],
|
||||
OU.[Type],
|
||||
SU.[ReadOnly],
|
||||
SU.[Admin]
|
||||
FROM
|
||||
[dbo].[SubvaultUser] SU
|
||||
INNER JOIN
|
||||
[dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId]
|
||||
LEFT JOIN
|
||||
[dbo].[User] U ON U.[Id] = OU.[UserId]
|
Loading…
Reference in New Issue
Block a user