1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-05 05:00:19 -05:00
bitwarden/src/Api/SecretsManager/Controllers/ProjectsController.cs
cd-bitwarden 3f3f52399b
[SM-716] Adding ability for service account to have write access (#3021)
* adding ability for service account to have write access

* Suggested changes

* fixing tests

* dotnet format changes

* Adding RunAsServiceAccountWIthPermission logic to ProjectAuthorizationhandlerTests

* Removing logic that prevents deleting and updating a secret. Adding Service Account logic to tests inside of secretAuthorizationhandlerTests.

* Removing Service Account from CanUpdateSecret_NotSupportedClientTypes_DoesNotSuceed because it is a supported client type now :)

* thomas sugested changes

* using Arg.Any<AccessClientType>() instead of default in tests

* merge conflict changes and code updates to remove service account tests that are  outdated

* fixing tests

* removing extra  spaces that lint hates
2023-06-30 17:17:41 +00:00

138 lines
5.4 KiB
C#

using Bit.Api.Models.Response;
using Bit.Api.SecretsManager.Models.Request;
using Bit.Api.SecretsManager.Models.Response;
using Bit.Core.Context;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.SecretsManager.AuthorizationRequirements;
using Bit.Core.SecretsManager.Commands.Projects.Interfaces;
using Bit.Core.SecretsManager.Repositories;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Bit.Api.SecretsManager.Controllers;
[Authorize("secrets")]
[SelfHosted(NotSelfHostedOnly = true)]
public class ProjectsController : Controller
{
private readonly ICurrentContext _currentContext;
private readonly IUserService _userService;
private readonly IProjectRepository _projectRepository;
private readonly ICreateProjectCommand _createProjectCommand;
private readonly IUpdateProjectCommand _updateProjectCommand;
private readonly IDeleteProjectCommand _deleteProjectCommand;
private readonly IAuthorizationService _authorizationService;
public ProjectsController(
ICurrentContext currentContext,
IUserService userService,
IProjectRepository projectRepository,
ICreateProjectCommand createProjectCommand,
IUpdateProjectCommand updateProjectCommand,
IDeleteProjectCommand deleteProjectCommand,
IAuthorizationService authorizationService)
{
_currentContext = currentContext;
_userService = userService;
_projectRepository = projectRepository;
_createProjectCommand = createProjectCommand;
_updateProjectCommand = updateProjectCommand;
_deleteProjectCommand = deleteProjectCommand;
_authorizationService = authorizationService;
}
[HttpGet("organizations/{organizationId}/projects")]
public async Task<ListResponseModel<ProjectResponseModel>> ListByOrganizationAsync([FromRoute] Guid organizationId)
{
if (!_currentContext.AccessSecretsManager(organizationId))
{
throw new NotFoundException();
}
var userId = _userService.GetProperUserId(User).Value;
var orgAdmin = await _currentContext.OrganizationAdmin(organizationId);
var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin);
var projects = await _projectRepository.GetManyByOrganizationIdAsync(organizationId, userId, accessClient);
var responses = projects.Select(project => new ProjectResponseModel(project));
return new ListResponseModel<ProjectResponseModel>(responses);
}
[HttpPost("organizations/{organizationId}/projects")]
public async Task<ProjectResponseModel> CreateAsync([FromRoute] Guid organizationId,
[FromBody] ProjectCreateRequestModel createRequest)
{
var project = createRequest.ToProject(organizationId);
var authorizationResult =
await _authorizationService.AuthorizeAsync(User, project, ProjectOperations.Create);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
var userId = _userService.GetProperUserId(User).Value;
var result = await _createProjectCommand.CreateAsync(project, userId, _currentContext.ClientType);
// Creating a project means you have read & write permission.
return new ProjectResponseModel(result, true, true);
}
[HttpPut("projects/{id}")]
public async Task<ProjectResponseModel> UpdateAsync([FromRoute] Guid id,
[FromBody] ProjectUpdateRequestModel updateRequest)
{
var project = await _projectRepository.GetByIdAsync(id);
var authorizationResult =
await _authorizationService.AuthorizeAsync(User, project, ProjectOperations.Update);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
var result = await _updateProjectCommand.UpdateAsync(updateRequest.ToProject(id));
// Updating a project means you have read & write permission.
return new ProjectResponseModel(result, true, true);
}
[HttpGet("projects/{id}")]
public async Task<ProjectResponseModel> GetAsync([FromRoute] Guid id)
{
var project = await _projectRepository.GetByIdAsync(id);
if (project == null)
{
throw new NotFoundException();
}
if (!_currentContext.AccessSecretsManager(project.OrganizationId))
{
throw new NotFoundException();
}
var userId = _userService.GetProperUserId(User).Value;
var orgAdmin = await _currentContext.OrganizationAdmin(project.OrganizationId);
var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin);
var access = await _projectRepository.AccessToProjectAsync(id, userId, accessClient);
if (!access.Read)
{
throw new NotFoundException();
}
return new ProjectResponseModel(project, access.Read, access.Write);
}
[HttpPost("projects/delete")]
public async Task<ListResponseModel<BulkDeleteResponseModel>> BulkDeleteAsync([FromBody] List<Guid> ids)
{
var userId = _userService.GetProperUserId(User).Value;
var results = await _deleteProjectCommand.DeleteProjects(ids, userId);
var responses = results.Select(r => new BulkDeleteResponseModel(r.Item1.Id, r.Item2));
return new ListResponseModel<BulkDeleteResponseModel>(responses);
}
}