Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-13013] add delete many async method to i user repository and i user service for bulk user deletion #5035

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

BTreston
Copy link
Contributor

@BTreston BTreston commented Nov 13, 2024

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-13013

📔 Objective

WIP: Creates the method DeleteManyAsync and adds User_DeleteByIds stored procedure to enable bulk deletion of users

📸 Screenshots

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@BTreston
Copy link
Contributor Author

WIP: I am yet to add this functionality to IUserService.

Copy link

codecov bot commented Nov 13, 2024

Codecov Report

Attention: Patch coverage is 0% with 51 lines in your changes missing coverage. Please review.

Project coverage is 42.63%. Comparing base (e16cad5) to head (9368004).

Files with missing lines Patch % Lines
...ure.EntityFramework/Repositories/UserRepository.cs 0.00% 39 Missing ⚠️
...frastructure.Dapper/Repositories/UserRepository.cs 0.00% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5035      +/-   ##
==========================================
- Coverage   42.66%   42.63%   -0.04%     
==========================================
  Files        1411     1411              
  Lines       65087    65137      +50     
  Branches     5959     5960       +1     
==========================================
  Hits        27772    27772              
- Misses      36075    36125      +50     
  Partials     1240     1240              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.


🚨 Try these New Features:

Copy link
Contributor

github-actions bot commented Nov 13, 2024

Logo
Checkmarx One – Scan Summary & Details7f8616f5-9d9f-43bb-a160-18264c4694ea

New Issues

Severity Issue Source File / Package Checkmarx Insight
LOW Log_Forging /src/Api/Auth/Controllers/TwoFactorController.cs: 438 Attack Vector

Fixed Issues

Severity Issue Source File / Package
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 106
MEDIUM CSRF /src/Billing/Controllers/RecoveryController.cs: 38
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 81
MEDIUM CSRF /src/Billing/Controllers/StripeController.cs: 164
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 238
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 81
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 131
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 122
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 362
MEDIUM CSRF /src/Admin/AdminConsole/Controllers/OrganizationsController.cs: 372
MEDIUM Unpinned Actions Full Length Commit SHA /build.yml: 579
MEDIUM Unpinned Actions Full Length Commit SHA /repository-management.yml: 153
MEDIUM Unpinned Actions Full Length Commit SHA /repository-management.yml: 96
MEDIUM Unpinned Actions Full Length Commit SHA /build.yml: 545
MEDIUM Unpinned Actions Full Length Commit SHA /build.yml: 664
MEDIUM Unpinned Actions Full Length Commit SHA /repository-management.yml: 168
MEDIUM Unpinned Actions Full Length Commit SHA /repository-management.yml: 160
MEDIUM Unpinned Actions Full Length Commit SHA /build.yml: 220
MEDIUM Unpinned Actions Full Length Commit SHA /build.yml: 616
LOW Log_Forging /src/Api/AdminConsole/Controllers/ProvidersController.cs: 72
LOW Log_Forging /src/Api/AdminConsole/Controllers/ProvidersController.cs: 72
LOW Log_Forging /src/Api/AdminConsole/Controllers/ProvidersController.cs: 72

Copy link
Contributor

@r-tome r-tome left a comment

Choose a reason for hiding this comment

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

Looking great! We'll sync up later today and discuss the suggestions I've made

Copy link
Contributor

Choose a reason for hiding this comment

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

It may be better to avoid changing this stored procedure and instead create a new one called User_DeleteManyByIds. This approach could simplify maintenance by allowing the database to be updated first without needing to worry about request failures if the API hasn't been updated yet.

Then, in a later release, we can switch to just using the new sproc and delete the old one.

CREATE PROCEDURE [dbo].[User_DeleteById]
@Id UNIQUEIDENTIFIER
CREATE PROCEDURE [dbo].[User_DeleteByIds]
@Ids [dbo].[GuidIdArray]
Copy link
Contributor

Choose a reason for hiding this comment

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

We're no longer using GuidIdArray, instead we parse a json string. Example: https://github.com/bitwarden/server/blob/main/src/Sql/dbo/Stored%20Procedures/User_ReadByIdsWithCalculatedPremium.sql

Copy link
Contributor

Choose a reason for hiding this comment

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

Infrastructure.EFIntegration.Test is deprecated. Database testing should be done in Infrastructure.Integration.Test.

@BTreston BTreston marked this pull request as ready for review November 18, 2024 17:24
@BTreston BTreston requested review from a team as code owners November 18, 2024 17:24
Copy link
Contributor

@r-tome r-tome left a comment

Choose a reason for hiding this comment

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

Great work! There's just a tiny change to revert on the single delete method.

@@ -167,7 +167,19 @@ public override async Task DeleteAsync(User user)
{
await connection.ExecuteAsync(
$"[{Schema}].[{Table}_DeleteById]",
new { Id = user.Id },
new { Ids = new List<Guid> { user.Id }.ToGuidIdArrayTVP() },
Copy link
Contributor

Choose a reason for hiding this comment

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

Revert this change to pass the single Id. The failing integration test will pass then.

-- Delete ciphers
WHILE @BatchSize > 0
BEGIN
BEGIN TRANSACTION User_DeleteById_Ciphers
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we may want a big transaction that scopes deleting everything related to each single user. @rkac-bw will have much better insights

Copy link
Contributor

Choose a reason for hiding this comment

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

As a single migration on release night I like a large transaction, it is a one time script and must succeed. As a reoccurring script that runs at any time creating a large transaction will lead to lots of locking and potential deadlocks on a busy db like ours, I would prefer a retry on error with smaller transactions and possibly
give it a deadlock priority of high so it is not the victim

@r-tome
Copy link
Contributor

r-tome commented Nov 19, 2024

@BTreston, I forgot to mention this in the description of the ticket but can you wire up this new method in

public async Task<IEnumerable<(Guid OrganizationUserId, string? ErrorMessage)>> DeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid? deletingUserId)
?

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.

3 participants