mirror of
https://github.com/bitwarden/server.git
synced 2026-06-01 11:45:20 -05:00
* PM-37165 - Add LastApiKeyRotationDate column to User Adds a nullable DATETIME2(7) LastApiKeyRotationDate column on the User table alongside the other Last*Date audit columns. Covers the MSSQL table, view, User_Create / User_Update stored procedures (new optional parameter, EDD-safe with default NULL), the SSDT source-of-truth, and EF migrations for MySql, Postgres, and Sqlite. Repository round-trip integration tests verify that CreateAsync defaults the column to NULL and ReplaceAsync persists it across all four providers. * PM-37165 - Add RotateUserApiKeyCommand under Auth/UserFeatures Extracts user API key rotation out of UserService into a new CQS command at src/Core/Auth/UserFeatures/UserApiKey/, mirroring the existing decomposition pattern for other Auth user features. The command generates a new 30-char ApiKey, bumps RevisionDate, sets LastApiKeyRotationDate, and persists via IUserRepository.ReplaceAsync. Adds the PM37165_RotateUserApiKeyCommand feature flag so the new path can be rolled out behind a flag in a follow-up commit. Registers the command via AddUserApiKeyCommands inside AddUserServices. Unit tests verify the command assigns a fresh key, updates both RevisionDate and LastApiKeyRotationDate to the same recent UTC value, and calls ReplaceAsync exactly once. * PM-37165 - Flag-gate rotate-api-key endpoint to new command Wires AccountsController.RotateApiKey to dispatch between IRotateUserApiKeyCommand (flag on) and the legacy UserService.RotateApiKeyAsync (flag off) based on PM37165_RotateUserApiKeyCommand. Both paths preserve the existing auth and secret-verification guards, which run before the flag branch. Marks IUserService.RotateApiKeyAsync and its implementation [Obsolete] pointing callers at IRotateUserApiKeyCommand, with TODOs tying their removal to the flag cleanup. The body of the legacy method is deliberately unchanged so it does NOT write LastApiKeyRotationDate while the flag is off; that genuinely gates the new behavior so the ramp is observable and reversible. The single remaining call site (the controller fallback) is wrapped in #pragma warning disable CS0618 so the attribute continues to flag any new callers. Tests: - AccountsControllerTests: dispatch tests for both flag states; the auth and bad-secret guard tests are parameterized over flag state. Pre-existing typo in two tests that called _sut.ApiKey() instead of _sut.RotateApiKey() is fixed. - UserServiceTests: regression test locks in the legacy non-write behavior so it cannot drift before the flag is removed. - AccountsControllerTest (integration): three endpoint tests cover flag-off (LastApiKeyRotationDate stays NULL), flag-on (column is populated), and bad-secret over both flag states (no rotation occurs). Each flag-state-specific test carries a TODO breadcrumb describing the exact rename or deletion when the flag is cleaned up. * PM-37165 - Tweak comment * PM-37165 - Move LastApiKeyRotationDate to end of User schema Append the new column to the end of User.sql, UserView.sql, the matching CREATE OR ALTER VIEW in the migrator script, and the User entity so SSDT mirrors what ALTER TABLE ADD produces in production.