1
0
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:
Kyle Spearrin 2017-04-03 12:27:02 -04:00
parent 0961d86d65
commit f1fc7832a0
19 changed files with 230 additions and 17 deletions

View 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);
}
}
}

View File

@ -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 =>

View File

@ -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>(

View File

@ -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)
{

View 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; }
}
}

View File

@ -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; }

View 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; }
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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)
{

View 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
{
}
}

View 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;
}
}
}

View File

@ -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>

View File

@ -14,7 +14,7 @@ BEGIN
SELECT
*
FROM
[dbo].[SubvaultUserDetailsView]
[dbo].[SubvaultUserSubvaultDetailsView]
WHERE
[OrganizationUserId] = @Id
END

View File

@ -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

View File

@ -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

View File

@ -1,4 +1,4 @@
CREATE VIEW [dbo].[SubvaultUserDetailsView]
CREATE VIEW [dbo].[SubvaultUserSubvaultDetailsView]
AS
SELECT
SU.[Id],

View 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]