mirror of
https://github.com/bitwarden/server.git
synced 2025-07-04 01:22:50 -05:00
Turn on file scoped namespaces (#2225)
This commit is contained in:
@ -7,114 +7,113 @@ using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.Public.Controllers
|
||||
namespace Bit.Api.Public.Controllers;
|
||||
|
||||
[Route("public/collections")]
|
||||
[Authorize("Organization")]
|
||||
public class CollectionsController : Controller
|
||||
{
|
||||
[Route("public/collections")]
|
||||
[Authorize("Organization")]
|
||||
public class CollectionsController : Controller
|
||||
private readonly ICollectionRepository _collectionRepository;
|
||||
private readonly ICollectionService _collectionService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
public CollectionsController(
|
||||
ICollectionRepository collectionRepository,
|
||||
ICollectionService collectionService,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
private readonly ICollectionRepository _collectionRepository;
|
||||
private readonly ICollectionService _collectionService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
_collectionRepository = collectionRepository;
|
||||
_collectionService = collectionService;
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
public CollectionsController(
|
||||
ICollectionRepository collectionRepository,
|
||||
ICollectionService collectionService,
|
||||
ICurrentContext currentContext)
|
||||
/// <summary>
|
||||
/// Retrieve a collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of an existing collection. You need only supply the unique collection identifier
|
||||
/// that was returned upon collection creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the collection to be retrieved.</param>
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(typeof(CollectionResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
{
|
||||
var collectionWithGroups = await _collectionRepository.GetByIdWithGroupsAsync(id);
|
||||
var collection = collectionWithGroups?.Item1;
|
||||
if (collection == null || collection.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
_collectionRepository = collectionRepository;
|
||||
_collectionService = collectionService;
|
||||
_currentContext = currentContext;
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new CollectionResponseModel(collection, collectionWithGroups.Item2);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of an existing collection. You need only supply the unique collection identifier
|
||||
/// that was returned upon collection creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the collection to be retrieved.</param>
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(typeof(CollectionResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
{
|
||||
var collectionWithGroups = await _collectionRepository.GetByIdWithGroupsAsync(id);
|
||||
var collection = collectionWithGroups?.Item1;
|
||||
if (collection == null || collection.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new CollectionResponseModel(collection, collectionWithGroups.Item2);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
/// <summary>
|
||||
/// List all collections.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's collections.
|
||||
/// Collection objects listed in this call do not include information about their associated groups.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<CollectionResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
{
|
||||
var collections = await _collectionRepository.GetManyByOrganizationIdAsync(
|
||||
_currentContext.OrganizationId.Value);
|
||||
// TODO: Get all CollectionGroup associations for the organization and marry them up here for the response.
|
||||
var collectionResponses = collections.Select(c => new CollectionResponseModel(c, null));
|
||||
var response = new ListResponseModel<CollectionResponseModel>(collectionResponses);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all collections.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's collections.
|
||||
/// Collection objects listed in this call do not include information about their associated groups.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<CollectionResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
/// <summary>
|
||||
/// Update a collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified collection object. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the collection to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(CollectionResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(Guid id, [FromBody] CollectionUpdateRequestModel model)
|
||||
{
|
||||
var existingCollection = await _collectionRepository.GetByIdAsync(id);
|
||||
if (existingCollection == null || existingCollection.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var collections = await _collectionRepository.GetManyByOrganizationIdAsync(
|
||||
_currentContext.OrganizationId.Value);
|
||||
// TODO: Get all CollectionGroup associations for the organization and marry them up here for the response.
|
||||
var collectionResponses = collections.Select(c => new CollectionResponseModel(c, null));
|
||||
var response = new ListResponseModel<CollectionResponseModel>(collectionResponses);
|
||||
return new JsonResult(response);
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var updatedCollection = model.ToCollection(existingCollection);
|
||||
var associations = model.Groups?.Select(c => c.ToSelectionReadOnly());
|
||||
await _collectionService.SaveAsync(updatedCollection, associations);
|
||||
var response = new CollectionResponseModel(updatedCollection, associations);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified collection object. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the collection to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(CollectionResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(Guid id, [FromBody] CollectionUpdateRequestModel model)
|
||||
/// <summary>
|
||||
/// Delete a collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanently deletes a collection. This cannot be undone.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the collection to be deleted.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var collection = await _collectionRepository.GetByIdAsync(id);
|
||||
if (collection == null || collection.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var existingCollection = await _collectionRepository.GetByIdAsync(id);
|
||||
if (existingCollection == null || existingCollection.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var updatedCollection = model.ToCollection(existingCollection);
|
||||
var associations = model.Groups?.Select(c => c.ToSelectionReadOnly());
|
||||
await _collectionService.SaveAsync(updatedCollection, associations);
|
||||
var response = new CollectionResponseModel(updatedCollection, associations);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete a collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanently deletes a collection. This cannot be undone.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the collection to be deleted.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var collection = await _collectionRepository.GetByIdAsync(id);
|
||||
if (collection == null || collection.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _collectionRepository.DeleteAsync(collection);
|
||||
return new OkResult();
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _collectionRepository.DeleteAsync(collection);
|
||||
return new OkResult();
|
||||
}
|
||||
}
|
||||
|
@ -7,65 +7,64 @@ using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.Public.Controllers
|
||||
namespace Bit.Api.Public.Controllers;
|
||||
|
||||
[Route("public/events")]
|
||||
[Authorize("Organization")]
|
||||
public class EventsController : Controller
|
||||
{
|
||||
[Route("public/events")]
|
||||
[Authorize("Organization")]
|
||||
public class EventsController : Controller
|
||||
private readonly IEventRepository _eventRepository;
|
||||
private readonly ICipherRepository _cipherRepository;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
public EventsController(
|
||||
IEventRepository eventRepository,
|
||||
ICipherRepository cipherRepository,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
private readonly IEventRepository _eventRepository;
|
||||
private readonly ICipherRepository _cipherRepository;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
_eventRepository = eventRepository;
|
||||
_cipherRepository = cipherRepository;
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
public EventsController(
|
||||
IEventRepository eventRepository,
|
||||
ICipherRepository cipherRepository,
|
||||
ICurrentContext currentContext)
|
||||
/// <summary>
|
||||
/// List all events.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a filtered list of your organization's event logs, paged by a continuation token.
|
||||
/// If no filters are provided, it will return the last 30 days of event for the organization.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<EventResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List([FromQuery] EventFilterRequestModel request)
|
||||
{
|
||||
var dateRange = request.ToDateRange();
|
||||
var result = new PagedResult<IEvent>();
|
||||
if (request.ActingUserId.HasValue)
|
||||
{
|
||||
_eventRepository = eventRepository;
|
||||
_cipherRepository = cipherRepository;
|
||||
_currentContext = currentContext;
|
||||
result = await _eventRepository.GetManyByOrganizationActingUserAsync(
|
||||
_currentContext.OrganizationId.Value, request.ActingUserId.Value, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = request.ContinuationToken });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all events.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a filtered list of your organization's event logs, paged by a continuation token.
|
||||
/// If no filters are provided, it will return the last 30 days of event for the organization.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<EventResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List([FromQuery] EventFilterRequestModel request)
|
||||
else if (request.ItemId.HasValue)
|
||||
{
|
||||
var dateRange = request.ToDateRange();
|
||||
var result = new PagedResult<IEvent>();
|
||||
if (request.ActingUserId.HasValue)
|
||||
var cipher = await _cipherRepository.GetByIdAsync(request.ItemId.Value);
|
||||
if (cipher != null && cipher.OrganizationId == _currentContext.OrganizationId.Value)
|
||||
{
|
||||
result = await _eventRepository.GetManyByOrganizationActingUserAsync(
|
||||
_currentContext.OrganizationId.Value, request.ActingUserId.Value, dateRange.Item1, dateRange.Item2,
|
||||
result = await _eventRepository.GetManyByCipherAsync(
|
||||
cipher, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = request.ContinuationToken });
|
||||
}
|
||||
else if (request.ItemId.HasValue)
|
||||
{
|
||||
var cipher = await _cipherRepository.GetByIdAsync(request.ItemId.Value);
|
||||
if (cipher != null && cipher.OrganizationId == _currentContext.OrganizationId.Value)
|
||||
{
|
||||
result = await _eventRepository.GetManyByCipherAsync(
|
||||
cipher, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = request.ContinuationToken });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await _eventRepository.GetManyByOrganizationAsync(
|
||||
_currentContext.OrganizationId.Value, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = request.ContinuationToken });
|
||||
}
|
||||
|
||||
var eventResponses = result.Data.Select(e => new EventResponseModel(e));
|
||||
var response = new ListResponseModel<EventResponseModel>(eventResponses, result.ContinuationToken);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await _eventRepository.GetManyByOrganizationAsync(
|
||||
_currentContext.OrganizationId.Value, dateRange.Item1, dateRange.Item2,
|
||||
new PageOptions { ContinuationToken = request.ContinuationToken });
|
||||
}
|
||||
|
||||
var eventResponses = result.Data.Select(e => new EventResponseModel(e));
|
||||
var response = new ListResponseModel<EventResponseModel>(eventResponses, result.ContinuationToken);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
}
|
||||
|
@ -7,177 +7,176 @@ using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.Public.Controllers
|
||||
namespace Bit.Api.Public.Controllers;
|
||||
|
||||
[Route("public/groups")]
|
||||
[Authorize("Organization")]
|
||||
public class GroupsController : Controller
|
||||
{
|
||||
[Route("public/groups")]
|
||||
[Authorize("Organization")]
|
||||
public class GroupsController : Controller
|
||||
private readonly IGroupRepository _groupRepository;
|
||||
private readonly IGroupService _groupService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
public GroupsController(
|
||||
IGroupRepository groupRepository,
|
||||
IGroupService groupService,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
private readonly IGroupRepository _groupRepository;
|
||||
private readonly IGroupService _groupService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
_groupRepository = groupRepository;
|
||||
_groupService = groupService;
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
public GroupsController(
|
||||
IGroupRepository groupRepository,
|
||||
IGroupService groupService,
|
||||
ICurrentContext currentContext)
|
||||
/// <summary>
|
||||
/// Retrieve a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of an existing group. You need only supply the unique group identifier
|
||||
/// that was returned upon group creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be retrieved.</param>
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
{
|
||||
var groupDetails = await _groupRepository.GetByIdWithCollectionsAsync(id);
|
||||
var group = groupDetails?.Item1;
|
||||
if (group == null || group.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
_groupRepository = groupRepository;
|
||||
_groupService = groupService;
|
||||
_currentContext = currentContext;
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new GroupResponseModel(group, groupDetails.Item2);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of an existing group. You need only supply the unique group identifier
|
||||
/// that was returned upon group creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be retrieved.</param>
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
/// <summary>
|
||||
/// Retrieve a groups's member ids
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the unique identifiers for all members that are associated with this group. You need only
|
||||
/// supply the unique group identifier that was returned upon group creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be retrieved.</param>
|
||||
[HttpGet("{id}/member-ids")]
|
||||
[ProducesResponseType(typeof(HashSet<Guid>), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> GetMemberIds(Guid id)
|
||||
{
|
||||
var group = await _groupRepository.GetByIdAsync(id);
|
||||
if (group == null || group.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var groupDetails = await _groupRepository.GetByIdWithCollectionsAsync(id);
|
||||
var group = groupDetails?.Item1;
|
||||
if (group == null || group.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new GroupResponseModel(group, groupDetails.Item2);
|
||||
return new JsonResult(response);
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var orgUserIds = await _groupRepository.GetManyUserIdsByIdAsync(id);
|
||||
return new JsonResult(orgUserIds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a groups's member ids
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the unique identifiers for all members that are associated with this group. You need only
|
||||
/// supply the unique group identifier that was returned upon group creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be retrieved.</param>
|
||||
[HttpGet("{id}/member-ids")]
|
||||
[ProducesResponseType(typeof(HashSet<Guid>), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> GetMemberIds(Guid id)
|
||||
{
|
||||
var group = await _groupRepository.GetByIdAsync(id);
|
||||
if (group == null || group.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var orgUserIds = await _groupRepository.GetManyUserIdsByIdAsync(id);
|
||||
return new JsonResult(orgUserIds);
|
||||
}
|
||||
/// <summary>
|
||||
/// List all groups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's groups.
|
||||
/// Group objects listed in this call do not include information about their associated collections.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<GroupResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
{
|
||||
var groups = await _groupRepository.GetManyByOrganizationIdAsync(_currentContext.OrganizationId.Value);
|
||||
// TODO: Get all CollectionGroup associations for the organization and marry them up here for the response.
|
||||
var groupResponses = groups.Select(g => new GroupResponseModel(g, null));
|
||||
var response = new ListResponseModel<GroupResponseModel>(groupResponses);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all groups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's groups.
|
||||
/// Group objects listed in this call do not include information about their associated collections.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<GroupResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
{
|
||||
var groups = await _groupRepository.GetManyByOrganizationIdAsync(_currentContext.OrganizationId.Value);
|
||||
// TODO: Get all CollectionGroup associations for the organization and marry them up here for the response.
|
||||
var groupResponses = groups.Select(g => new GroupResponseModel(g, null));
|
||||
var response = new ListResponseModel<GroupResponseModel>(groupResponses);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
/// <summary>
|
||||
/// Create a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a new group object.
|
||||
/// </remarks>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
public async Task<IActionResult> Post([FromBody] GroupCreateUpdateRequestModel model)
|
||||
{
|
||||
var group = model.ToGroup(_currentContext.OrganizationId.Value);
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
await _groupService.SaveAsync(group, associations);
|
||||
var response = new GroupResponseModel(group, associations);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a new group object.
|
||||
/// </remarks>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
public async Task<IActionResult> Post([FromBody] GroupCreateUpdateRequestModel model)
|
||||
/// <summary>
|
||||
/// Update a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified group object. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(Guid id, [FromBody] GroupCreateUpdateRequestModel model)
|
||||
{
|
||||
var existingGroup = await _groupRepository.GetByIdAsync(id);
|
||||
if (existingGroup == null || existingGroup.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var group = model.ToGroup(_currentContext.OrganizationId.Value);
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
await _groupService.SaveAsync(group, associations);
|
||||
var response = new GroupResponseModel(group, associations);
|
||||
return new JsonResult(response);
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var updatedGroup = model.ToGroup(existingGroup);
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
await _groupService.SaveAsync(updatedGroup, associations);
|
||||
var response = new GroupResponseModel(updatedGroup, associations);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified group object. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(Guid id, [FromBody] GroupCreateUpdateRequestModel model)
|
||||
/// <summary>
|
||||
/// Update a group's members.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified group's member associations.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}/member-ids")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> PutMemberIds(Guid id, [FromBody] UpdateMemberIdsRequestModel model)
|
||||
{
|
||||
var existingGroup = await _groupRepository.GetByIdAsync(id);
|
||||
if (existingGroup == null || existingGroup.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var existingGroup = await _groupRepository.GetByIdAsync(id);
|
||||
if (existingGroup == null || existingGroup.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var updatedGroup = model.ToGroup(existingGroup);
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
await _groupService.SaveAsync(updatedGroup, associations);
|
||||
var response = new GroupResponseModel(updatedGroup, associations);
|
||||
return new JsonResult(response);
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _groupRepository.UpdateUsersAsync(existingGroup.Id, model.MemberIds);
|
||||
return new OkResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a group's members.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified group's member associations.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}/member-ids")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> PutMemberIds(Guid id, [FromBody] UpdateMemberIdsRequestModel model)
|
||||
/// <summary>
|
||||
/// Delete a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanently deletes a group. This cannot be undone.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be deleted.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var group = await _groupRepository.GetByIdAsync(id);
|
||||
if (group == null || group.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var existingGroup = await _groupRepository.GetByIdAsync(id);
|
||||
if (existingGroup == null || existingGroup.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _groupRepository.UpdateUsersAsync(existingGroup.Id, model.MemberIds);
|
||||
return new OkResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanently deletes a group. This cannot be undone.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the group to be deleted.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var group = await _groupRepository.GetByIdAsync(id);
|
||||
if (group == null || group.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _groupRepository.DeleteAsync(group);
|
||||
return new OkResult();
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _groupRepository.DeleteAsync(group);
|
||||
return new OkResult();
|
||||
}
|
||||
}
|
||||
|
@ -8,227 +8,226 @@ using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.Public.Controllers
|
||||
namespace Bit.Api.Public.Controllers;
|
||||
|
||||
[Route("public/members")]
|
||||
[Authorize("Organization")]
|
||||
public class MembersController : Controller
|
||||
{
|
||||
[Route("public/members")]
|
||||
[Authorize("Organization")]
|
||||
public class MembersController : Controller
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IGroupRepository _groupRepository;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly IUserService _userService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
public MembersController(
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IGroupRepository groupRepository,
|
||||
IOrganizationService organizationService,
|
||||
IUserService userService,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IGroupRepository _groupRepository;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly IUserService _userService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_groupRepository = groupRepository;
|
||||
_organizationService = organizationService;
|
||||
_userService = userService;
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
public MembersController(
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IGroupRepository groupRepository,
|
||||
IOrganizationService organizationService,
|
||||
IUserService userService,
|
||||
ICurrentContext currentContext)
|
||||
/// <summary>
|
||||
/// Retrieve a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of an existing member of the organization. You need only supply the
|
||||
/// unique member identifier that was returned upon member creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be retrieved.</param>
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
{
|
||||
var userDetails = await _organizationUserRepository.GetDetailsByIdWithCollectionsAsync(id);
|
||||
var orgUser = userDetails?.Item1;
|
||||
if (orgUser == null || orgUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_groupRepository = groupRepository;
|
||||
_organizationService = organizationService;
|
||||
_userService = userService;
|
||||
_currentContext = currentContext;
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new MemberResponseModel(orgUser, await _userService.TwoFactorIsEnabledAsync(orgUser),
|
||||
userDetails.Item2);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of an existing member of the organization. You need only supply the
|
||||
/// unique member identifier that was returned upon member creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be retrieved.</param>
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
/// <summary>
|
||||
/// Retrieve a member's group ids
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the unique identifiers for all groups that are associated with this member. You need only
|
||||
/// supply the unique member identifier that was returned upon member creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be retrieved.</param>
|
||||
[HttpGet("{id}/group-ids")]
|
||||
[ProducesResponseType(typeof(HashSet<Guid>), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> GetGroupIds(Guid id)
|
||||
{
|
||||
var orgUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (orgUser == null || orgUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var userDetails = await _organizationUserRepository.GetDetailsByIdWithCollectionsAsync(id);
|
||||
var orgUser = userDetails?.Item1;
|
||||
if (orgUser == null || orgUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new MemberResponseModel(orgUser, await _userService.TwoFactorIsEnabledAsync(orgUser),
|
||||
userDetails.Item2);
|
||||
return new JsonResult(response);
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var groupIds = await _groupRepository.GetManyIdsByUserIdAsync(id);
|
||||
return new JsonResult(groupIds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a member's group ids
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the unique identifiers for all groups that are associated with this member. You need only
|
||||
/// supply the unique member identifier that was returned upon member creation.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be retrieved.</param>
|
||||
[HttpGet("{id}/group-ids")]
|
||||
[ProducesResponseType(typeof(HashSet<Guid>), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> GetGroupIds(Guid id)
|
||||
{
|
||||
var orgUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (orgUser == null || orgUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var groupIds = await _groupRepository.GetManyIdsByUserIdAsync(id);
|
||||
return new JsonResult(groupIds);
|
||||
}
|
||||
/// <summary>
|
||||
/// List all members.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's members.
|
||||
/// Member objects listed in this call do not include information about their associated collections.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<MemberResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
{
|
||||
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(
|
||||
_currentContext.OrganizationId.Value);
|
||||
// TODO: Get all CollectionUser associations for the organization and marry them up here for the response.
|
||||
var memberResponsesTasks = users.Select(async u => new MemberResponseModel(u,
|
||||
await _userService.TwoFactorIsEnabledAsync(u), null));
|
||||
var memberResponses = await Task.WhenAll(memberResponsesTasks);
|
||||
var response = new ListResponseModel<MemberResponseModel>(memberResponses);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all members.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's members.
|
||||
/// Member objects listed in this call do not include information about their associated collections.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<MemberResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
/// <summary>
|
||||
/// Create a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a new member object by inviting a user to the organization.
|
||||
/// </remarks>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
public async Task<IActionResult> Post([FromBody] MemberCreateRequestModel model)
|
||||
{
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
var invite = new OrganizationUserInvite
|
||||
{
|
||||
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(
|
||||
_currentContext.OrganizationId.Value);
|
||||
// TODO: Get all CollectionUser associations for the organization and marry them up here for the response.
|
||||
var memberResponsesTasks = users.Select(async u => new MemberResponseModel(u,
|
||||
await _userService.TwoFactorIsEnabledAsync(u), null));
|
||||
var memberResponses = await Task.WhenAll(memberResponsesTasks);
|
||||
var response = new ListResponseModel<MemberResponseModel>(memberResponses);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
Emails = new List<string> { model.Email },
|
||||
Type = model.Type.Value,
|
||||
AccessAll = model.AccessAll.Value,
|
||||
Collections = associations
|
||||
};
|
||||
var user = await _organizationService.InviteUserAsync(_currentContext.OrganizationId.Value, null,
|
||||
model.Email, model.Type.Value, model.AccessAll.Value, model.ExternalId, associations);
|
||||
var response = new MemberResponseModel(user, associations);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a new member object by inviting a user to the organization.
|
||||
/// </remarks>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
public async Task<IActionResult> Post([FromBody] MemberCreateRequestModel model)
|
||||
/// <summary>
|
||||
/// Update a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified member object. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(Guid id, [FromBody] MemberUpdateRequestModel model)
|
||||
{
|
||||
var existingUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (existingUser == null || existingUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
var invite = new OrganizationUserInvite
|
||||
{
|
||||
Emails = new List<string> { model.Email },
|
||||
Type = model.Type.Value,
|
||||
AccessAll = model.AccessAll.Value,
|
||||
Collections = associations
|
||||
};
|
||||
var user = await _organizationService.InviteUserAsync(_currentContext.OrganizationId.Value, null,
|
||||
model.Email, model.Type.Value, model.AccessAll.Value, model.ExternalId, associations);
|
||||
var response = new MemberResponseModel(user, associations);
|
||||
return new JsonResult(response);
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var updatedUser = model.ToOrganizationUser(existingUser);
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
await _organizationService.SaveUserAsync(updatedUser, null, associations);
|
||||
MemberResponseModel response = null;
|
||||
if (existingUser.UserId.HasValue)
|
||||
{
|
||||
var existingUserDetails = await _organizationUserRepository.GetDetailsByIdAsync(id);
|
||||
response = new MemberResponseModel(existingUserDetails,
|
||||
await _userService.TwoFactorIsEnabledAsync(existingUserDetails), associations);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = new MemberResponseModel(updatedUser, associations);
|
||||
}
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified member object. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(Guid id, [FromBody] MemberUpdateRequestModel model)
|
||||
/// <summary>
|
||||
/// Update a member's groups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified member's group associations.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}/group-ids")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> PutGroupIds(Guid id, [FromBody] UpdateGroupIdsRequestModel model)
|
||||
{
|
||||
var existingUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (existingUser == null || existingUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var existingUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (existingUser == null || existingUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var updatedUser = model.ToOrganizationUser(existingUser);
|
||||
var associations = model.Collections?.Select(c => c.ToSelectionReadOnly());
|
||||
await _organizationService.SaveUserAsync(updatedUser, null, associations);
|
||||
MemberResponseModel response = null;
|
||||
if (existingUser.UserId.HasValue)
|
||||
{
|
||||
var existingUserDetails = await _organizationUserRepository.GetDetailsByIdAsync(id);
|
||||
response = new MemberResponseModel(existingUserDetails,
|
||||
await _userService.TwoFactorIsEnabledAsync(existingUserDetails), associations);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = new MemberResponseModel(updatedUser, associations);
|
||||
}
|
||||
return new JsonResult(response);
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _organizationService.UpdateUserGroupsAsync(existingUser, model.GroupIds, null);
|
||||
return new OkResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a member's groups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified member's group associations.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}/group-ids")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> PutGroupIds(Guid id, [FromBody] UpdateGroupIdsRequestModel model)
|
||||
/// <summary>
|
||||
/// Delete a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanently deletes a member from the organization. This cannot be undone.
|
||||
/// The user account will still remain. The user is only removed from the organization.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be deleted.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var user = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (user == null || user.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var existingUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (existingUser == null || existingUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _organizationService.UpdateUserGroupsAsync(existingUser, model.GroupIds, null);
|
||||
return new OkResult();
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _organizationService.DeleteUserAsync(_currentContext.OrganizationId.Value, id, null);
|
||||
return new OkResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Permanently deletes a member from the organization. This cannot be undone.
|
||||
/// The user account will still remain. The user is only removed from the organization.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to be deleted.</param>
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
/// <summary>
|
||||
/// Re-invite a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Re-sends the invitation email to an organization member.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to re-invite.</param>
|
||||
[HttpPost("{id}/reinvite")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> PostReinvite(Guid id)
|
||||
{
|
||||
var existingUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (existingUser == null || existingUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
var user = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (user == null || user.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _organizationService.DeleteUserAsync(_currentContext.OrganizationId.Value, id, null);
|
||||
return new OkResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Re-invite a member.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Re-sends the invitation email to an organization member.
|
||||
/// </remarks>
|
||||
/// <param name="id">The identifier of the member to re-invite.</param>
|
||||
[HttpPost("{id}/reinvite")]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> PostReinvite(Guid id)
|
||||
{
|
||||
var existingUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (existingUser == null || existingUser.OrganizationId != _currentContext.OrganizationId)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _organizationService.ResendInviteAsync(_currentContext.OrganizationId.Value, null, id);
|
||||
return new OkResult();
|
||||
return new NotFoundResult();
|
||||
}
|
||||
await _organizationService.ResendInviteAsync(_currentContext.OrganizationId.Value, null, id);
|
||||
return new OkResult();
|
||||
}
|
||||
}
|
||||
|
@ -8,52 +8,51 @@ using Bit.Core.Settings;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.Public.Controllers
|
||||
namespace Bit.Api.Public.Controllers;
|
||||
|
||||
[Route("public/organization")]
|
||||
[Authorize("Organization")]
|
||||
public class OrganizationController : Controller
|
||||
{
|
||||
[Route("public/organization")]
|
||||
[Authorize("Organization")]
|
||||
public class OrganizationController : Controller
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public OrganizationController(
|
||||
IOrganizationService organizationService,
|
||||
ICurrentContext currentContext,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
_organizationService = organizationService;
|
||||
_currentContext = currentContext;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public OrganizationController(
|
||||
IOrganizationService organizationService,
|
||||
ICurrentContext currentContext,
|
||||
GlobalSettings globalSettings)
|
||||
/// <summary>
|
||||
/// Import members and groups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Import members and groups from an external system.
|
||||
/// </remarks>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPost("import")]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
public async Task<IActionResult> Import([FromBody] OrganizationImportRequestModel model)
|
||||
{
|
||||
if (!_globalSettings.SelfHosted && !model.LargeImport &&
|
||||
(model.Groups.Count() > 2000 || model.Members.Count(u => !u.Deleted) > 2000))
|
||||
{
|
||||
_organizationService = organizationService;
|
||||
_currentContext = currentContext;
|
||||
_globalSettings = globalSettings;
|
||||
throw new BadRequestException("You cannot import this much data at once.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import members and groups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Import members and groups from an external system.
|
||||
/// </remarks>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPost("import")]
|
||||
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
public async Task<IActionResult> Import([FromBody] OrganizationImportRequestModel model)
|
||||
{
|
||||
if (!_globalSettings.SelfHosted && !model.LargeImport &&
|
||||
(model.Groups.Count() > 2000 || model.Members.Count(u => !u.Deleted) > 2000))
|
||||
{
|
||||
throw new BadRequestException("You cannot import this much data at once.");
|
||||
}
|
||||
|
||||
await _organizationService.ImportAsync(
|
||||
_currentContext.OrganizationId.Value,
|
||||
null,
|
||||
model.Groups.Select(g => g.ToImportedGroup(_currentContext.OrganizationId.Value)),
|
||||
model.Members.Where(u => !u.Deleted).Select(u => u.ToImportedOrganizationUser()),
|
||||
model.Members.Where(u => u.Deleted).Select(u => u.ExternalId),
|
||||
model.OverwriteExisting.GetValueOrDefault());
|
||||
return new OkResult();
|
||||
}
|
||||
await _organizationService.ImportAsync(
|
||||
_currentContext.OrganizationId.Value,
|
||||
null,
|
||||
model.Groups.Select(g => g.ToImportedGroup(_currentContext.OrganizationId.Value)),
|
||||
model.Members.Where(u => !u.Deleted).Select(u => u.ToImportedOrganizationUser()),
|
||||
model.Members.Where(u => u.Deleted).Select(u => u.ExternalId),
|
||||
model.OverwriteExisting.GetValueOrDefault());
|
||||
return new OkResult();
|
||||
}
|
||||
}
|
||||
|
@ -8,98 +8,97 @@ using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.Public.Controllers
|
||||
namespace Bit.Api.Public.Controllers;
|
||||
|
||||
[Route("public/policies")]
|
||||
[Authorize("Organization")]
|
||||
public class PoliciesController : Controller
|
||||
{
|
||||
[Route("public/policies")]
|
||||
[Authorize("Organization")]
|
||||
public class PoliciesController : Controller
|
||||
private readonly IPolicyRepository _policyRepository;
|
||||
private readonly IPolicyService _policyService;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
public PoliciesController(
|
||||
IPolicyRepository policyRepository,
|
||||
IPolicyService policyService,
|
||||
IUserService userService,
|
||||
IOrganizationService organizationService,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
private readonly IPolicyRepository _policyRepository;
|
||||
private readonly IPolicyService _policyService;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
_policyRepository = policyRepository;
|
||||
_policyService = policyService;
|
||||
_userService = userService;
|
||||
_organizationService = organizationService;
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
public PoliciesController(
|
||||
IPolicyRepository policyRepository,
|
||||
IPolicyService policyService,
|
||||
IUserService userService,
|
||||
IOrganizationService organizationService,
|
||||
ICurrentContext currentContext)
|
||||
/// <summary>
|
||||
/// Retrieve a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of a policy.
|
||||
/// </remarks>
|
||||
/// <param name="type">The type of policy to be retrieved.</param>
|
||||
[HttpGet("{type}")]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(PolicyType type)
|
||||
{
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(
|
||||
_currentContext.OrganizationId.Value, type);
|
||||
if (policy == null)
|
||||
{
|
||||
_policyRepository = policyRepository;
|
||||
_policyService = policyService;
|
||||
_userService = userService;
|
||||
_organizationService = organizationService;
|
||||
_currentContext = currentContext;
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new PolicyResponseModel(policy);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Retrieves the details of a policy.
|
||||
/// </remarks>
|
||||
/// <param name="type">The type of policy to be retrieved.</param>
|
||||
[HttpGet("{type}")]
|
||||
[ProducesResponseType(typeof(GroupResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Get(PolicyType type)
|
||||
{
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(
|
||||
_currentContext.OrganizationId.Value, type);
|
||||
if (policy == null)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
var response = new PolicyResponseModel(policy);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
/// <summary>
|
||||
/// List all policies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's policies.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<PolicyResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
{
|
||||
var policies = await _policyRepository.GetManyByOrganizationIdAsync(_currentContext.OrganizationId.Value);
|
||||
var policyResponses = policies.Select(p => new PolicyResponseModel(p));
|
||||
var response = new ListResponseModel<PolicyResponseModel>(policyResponses);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all policies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a list of your organization's policies.
|
||||
/// </remarks>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(ListResponseModel<PolicyResponseModel>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> List()
|
||||
/// <summary>
|
||||
/// Update a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified policy. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="type">The type of policy to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(PolicyResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(PolicyType type, [FromBody] PolicyUpdateRequestModel model)
|
||||
{
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(
|
||||
_currentContext.OrganizationId.Value, type);
|
||||
if (policy == null)
|
||||
{
|
||||
var policies = await _policyRepository.GetManyByOrganizationIdAsync(_currentContext.OrganizationId.Value);
|
||||
var policyResponses = policies.Select(p => new PolicyResponseModel(p));
|
||||
var response = new ListResponseModel<PolicyResponseModel>(policyResponses);
|
||||
return new JsonResult(response);
|
||||
policy = model.ToPolicy(_currentContext.OrganizationId.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update a policy.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Updates the specified policy. If a property is not provided,
|
||||
/// the value of the existing property will be reset.
|
||||
/// </remarks>
|
||||
/// <param name="type">The type of policy to be updated.</param>
|
||||
/// <param name="model">The request model.</param>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(typeof(PolicyResponseModel), (int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
public async Task<IActionResult> Put(PolicyType type, [FromBody] PolicyUpdateRequestModel model)
|
||||
else
|
||||
{
|
||||
var policy = await _policyRepository.GetByOrganizationIdTypeAsync(
|
||||
_currentContext.OrganizationId.Value, type);
|
||||
if (policy == null)
|
||||
{
|
||||
policy = model.ToPolicy(_currentContext.OrganizationId.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
policy = model.ToPolicy(policy);
|
||||
}
|
||||
await _policyService.SaveAsync(policy, _userService, _organizationService, null);
|
||||
var response = new PolicyResponseModel(policy);
|
||||
return new JsonResult(response);
|
||||
policy = model.ToPolicy(policy);
|
||||
}
|
||||
await _policyService.SaveAsync(policy, _userService, _organizationService, null);
|
||||
var response = new PolicyResponseModel(policy);
|
||||
return new JsonResult(response);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user