mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 08:02:49 -05:00
[SM-670] Add permission context to project lists. (#2822)
* Attach permission context to project lists. * restrict service-account actions * Fix project permission details * Add getters and setters * dotnet format * Fix admin create unassigned secret (#2872)
This commit is contained in:
@ -249,14 +249,8 @@ public class AccessPoliciesController : Controller
|
||||
}
|
||||
|
||||
var (accessClient, userId) = await GetAccessClientTypeAsync(project.OrganizationId);
|
||||
var hasAccess = accessClient switch
|
||||
{
|
||||
AccessClientType.NoAccessCheck => true,
|
||||
AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(project.Id, userId),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if (!hasAccess)
|
||||
var access = await _projectRepository.AccessToProjectAsync(project.Id, userId, accessClient);
|
||||
if (!access.Write || accessClient == AccessClientType.ServiceAccount)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
@ -67,7 +67,9 @@ public class ProjectsController : Controller
|
||||
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
var result = await _createProjectCommand.CreateAsync(createRequest.ToProject(organizationId), userId);
|
||||
return new ProjectResponseModel(result);
|
||||
|
||||
// Creating a project means you have read & write permission.
|
||||
return new ProjectResponseModel(result, true, true);
|
||||
}
|
||||
|
||||
[HttpPut("projects/{id}")]
|
||||
@ -76,11 +78,13 @@ public class ProjectsController : Controller
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
|
||||
var result = await _updateProjectCommand.UpdateAsync(updateRequest.ToProject(id), userId);
|
||||
return new ProjectResponseModel(result);
|
||||
|
||||
// Updating a project means you have read & write permission.
|
||||
return new ProjectResponseModel(result, true, true);
|
||||
}
|
||||
|
||||
[HttpGet("projects/{id}")]
|
||||
public async Task<ProjectPermissionDetailsResponseModel> GetAsync([FromRoute] Guid id)
|
||||
public async Task<ProjectResponseModel> GetAsync([FromRoute] Guid id)
|
||||
{
|
||||
var project = await _projectRepository.GetByIdAsync(id);
|
||||
if (project == null)
|
||||
@ -104,7 +108,7 @@ public class ProjectsController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
return new ProjectPermissionDetailsResponseModel(project, access.Read, access.Write);
|
||||
return new ProjectResponseModel(project, access.Read, access.Write);
|
||||
}
|
||||
|
||||
[HttpPost("projects/delete")]
|
||||
|
@ -47,7 +47,7 @@ public class SecretsManagerPortingController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
return new SMExportResponseModel(projects, secrets.Select(s => s.Secret));
|
||||
return new SMExportResponseModel(projects.Select(p => p.Project), secrets.Select(s => s.Secret));
|
||||
}
|
||||
|
||||
[HttpPost("sm/{organizationId}/import")]
|
||||
|
@ -1,22 +0,0 @@
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
|
||||
namespace Bit.Api.SecretsManager.Models.Response;
|
||||
|
||||
public class ProjectPermissionDetailsResponseModel : ProjectResponseModel
|
||||
{
|
||||
private const string _objectName = "projectPermissionDetails";
|
||||
|
||||
public ProjectPermissionDetailsResponseModel(Project project, bool read, bool write, string obj = _objectName) : base(project, obj)
|
||||
{
|
||||
Read = read;
|
||||
Write = write;
|
||||
}
|
||||
|
||||
public ProjectPermissionDetailsResponseModel()
|
||||
{
|
||||
}
|
||||
|
||||
public bool Read { get; set; }
|
||||
|
||||
public bool Write { get; set; }
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Models.Data;
|
||||
|
||||
namespace Bit.Api.SecretsManager.Models.Response;
|
||||
|
||||
@ -7,7 +8,7 @@ public class ProjectResponseModel : ResponseModel
|
||||
{
|
||||
private const string _objectName = "project";
|
||||
|
||||
public ProjectResponseModel(Project project, string obj = _objectName)
|
||||
public ProjectResponseModel(Project project, bool read, bool write, string obj = _objectName)
|
||||
: base(obj)
|
||||
{
|
||||
if (project == null)
|
||||
@ -20,6 +21,25 @@ public class ProjectResponseModel : ResponseModel
|
||||
Name = project.Name;
|
||||
CreationDate = project.CreationDate;
|
||||
RevisionDate = project.RevisionDate;
|
||||
Read = read;
|
||||
Write = write;
|
||||
}
|
||||
|
||||
public ProjectResponseModel(ProjectPermissionDetails projectDetails, string obj = _objectName)
|
||||
: base(obj)
|
||||
{
|
||||
if (projectDetails == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(projectDetails));
|
||||
}
|
||||
|
||||
Id = projectDetails.Project.Id.ToString();
|
||||
OrganizationId = projectDetails.Project.OrganizationId.ToString();
|
||||
Name = projectDetails.Project.Name;
|
||||
CreationDate = projectDetails.Project.CreationDate;
|
||||
RevisionDate = projectDetails.Project.RevisionDate;
|
||||
Read = projectDetails.Read;
|
||||
Write = projectDetails.Write;
|
||||
}
|
||||
|
||||
public ProjectResponseModel() : base(_objectName)
|
||||
@ -36,5 +56,7 @@ public class ProjectResponseModel : ResponseModel
|
||||
|
||||
public DateTime RevisionDate { get; set; }
|
||||
|
||||
public IEnumerable<Guid> Secrets { get; set; }
|
||||
public bool Read { get; set; }
|
||||
|
||||
public bool Write { get; set; }
|
||||
}
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
namespace Bit.Core.SecretsManager.Models.Data;
|
||||
|
||||
public class ProjectPermissionDetails : Project
|
||||
public class ProjectPermissionDetails
|
||||
{
|
||||
public Project Project { get; set; }
|
||||
public bool Read { get; set; }
|
||||
public bool Write { get; set; }
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ namespace Bit.Core.SecretsManager.Models.Data;
|
||||
|
||||
public class SecretPermissionDetails
|
||||
{
|
||||
public Secret Secret;
|
||||
public Secret Secret { get; set; }
|
||||
public bool Read { get; set; }
|
||||
public bool Write { get; set; }
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Models.Data;
|
||||
|
||||
namespace Bit.Core.SecretsManager.Repositories;
|
||||
|
||||
public interface IProjectRepository
|
||||
{
|
||||
Task<IEnumerable<Project>> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType);
|
||||
Task<IEnumerable<ProjectPermissionDetails>> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType);
|
||||
Task<IEnumerable<Project>> GetManyByOrganizationIdWriteAccessAsync(Guid organizationId, Guid userId, AccessClientType accessType);
|
||||
Task<IEnumerable<Project>> GetManyWithSecretsByIds(IEnumerable<Guid> ids);
|
||||
Task<Project> GetByIdAsync(Guid id);
|
||||
@ -13,10 +14,6 @@ public interface IProjectRepository
|
||||
Task ReplaceAsync(Project project);
|
||||
Task DeleteManyByIdAsync(IEnumerable<Guid> ids);
|
||||
Task<IEnumerable<Project>> ImportAsync(IEnumerable<Project> projects);
|
||||
Task<bool> UserHasReadAccessToProject(Guid id, Guid userId);
|
||||
Task<bool> UserHasWriteAccessToProject(Guid id, Guid userId);
|
||||
Task<bool> ServiceAccountHasWriteAccessToProject(Guid id, Guid userId);
|
||||
Task<bool> ServiceAccountHasReadAccessToProject(Guid id, Guid userId);
|
||||
Task<(bool Read, bool Write)> AccessToProjectAsync(Guid id, Guid userId, AccessClientType accessType);
|
||||
Task<bool> ProjectsAreInOrganization(List<Guid> projectIds, Guid organizationId);
|
||||
}
|
||||
|
Reference in New Issue
Block a user