Skip to content

[SM-999] Add Bulk Move to Project Endpoint#66

Open
lizard-boy wants to merge 19 commits into
mainfrom
sm-add-bulk-move-to-project
Open

[SM-999] Add Bulk Move to Project Endpoint#66
lizard-boy wants to merge 19 commits into
mainfrom
sm-add-bulk-move-to-project

Conversation

@lizard-boy

@lizard-boy lizard-boy commented Oct 19, 2024

Copy link
Copy Markdown

Type of change

- [ ] Bug fix
- [x] New feature development
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
- [ ] Build/deploy pipeline (DevOps)
- [ ] Other

Objective

Add new endpoint for updating the projects of many secrets to the same project.

Clients PR: bitwarden/clients#6665

Code changes

  • bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs: This interacts with the virtual table ProjectSecret to avoid making large changes in the code base or to make this update one row at a time. It deletes all current relationships for the given secrets and then creates new relationships for them based on the supplied project ids.
  • src/Api/SecretsManager/Controllers/SecretsController.cs: Controller method for validating that the current user has the permissions to do the specified action.

Before you submit

  • Please check for formatting errors (dotnet format --verify-no-changes) (required)
  • If making database changes - make sure you also update Entity Framework queries and/or migrations
  • Please add unit tests where it makes sense to do so (encouraged but not required)
  • If this change requires a documentation update - notify the documentation team
  • If this change has particular deployment requirements - notify the DevOps team

Greptile Summary

This pull request adds a new endpoint for bulk moving secrets to a project in the Secrets Manager, including necessary authorization, command implementation, and unit tests.

  • Added BulkMoveToProjectAsync method in SecretsController.cs to handle the new bulk move endpoint
  • Implemented MoveSecretsCommand and BulkSecretAuthorizationHandler for executing and authorizing bulk secret operations
  • Created ProjectSecret entity to represent many-to-many relationships between projects and secrets
  • Added new methods AccessToSecretsAsync and MoveSecretsAsync to ISecretRepository interface and implementations
  • Created empty migration files for MySQL, PostgreSQL, and SQLite that need to be properly implemented

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

26 file(s) reviewed, 24 comment(s)
Edit PR Review Bot Settings | Greptile

BulkSecretOperationRequirement requirement,
IReadOnlyList<Secret> resource)
{
var secretsByOrganizationId = resource.GroupBy(s => s.OrganizationId).ToArray();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider using FirstOrDefault() instead of ToArray() for better performance when only checking for a single group.

Comment on lines +65 to +66
var secretAccesses = await _secretRepository.AccessToSecretsAsync(
secrets.Select(s => s.Id).ToArray(), userId, accessClientType);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: This could potentially be a performance bottleneck for large numbers of secrets. Consider implementing a batch operation in the repository.

secrets.Select(s => s.Id).ToArray(), userId, accessClientType);

// If we don't have the write permission
return secretAccesses.All(a => a.Value.Write);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Ensure that secretAccesses contains an entry for every secret, otherwise this check might pass incorrectly.

Comment on lines +354 to +356
await dbContext.ProjectSecrets
.Where(ps => secretIds.Contains(ps.SecretsId))
.ExecuteDeleteAsync();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: This operation deletes all existing project-secret relationships. Ensure this is the intended behavior, as it may have unintended consequences

Guid userId,
AccessClientType accessType)
{
await using var scope = ServiceScopeFactory.CreateAsyncScope();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Use 'using' instead of 'await using' for consistency with other methods

Comment on lines +2188 to +2201
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ProjectSecret", b =>
{
b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null)
.WithMany()
.HasForeignKey("ProjectsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", null)
.WithMany()
.HasForeignKey("SecretsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Cascade delete behavior for ProjectSecret relationships may cause unintended data loss if not carefully managed

Comment on lines +11 to +14
protected override void Up(MigrationBuilder migrationBuilder)
{

}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Up method is empty. Implement table creation, indexes, and foreign keys for ProjectSecret entity.

Comment on lines +17 to +20
protected override void Down(MigrationBuilder migrationBuilder)
{

}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Down method is empty. Implement logic to revert changes made in Up method.

Comment on lines +11 to +14
protected override void Up(MigrationBuilder migrationBuilder)
{

}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: The Up method is empty. It should create the ProjectSecret table with appropriate columns.

Comment on lines +17 to +20
protected override void Down(MigrationBuilder migrationBuilder)
{

}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: The Down method is empty. It should drop the ProjectSecret table to revert the migration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants