-
Notifications
You must be signed in to change notification settings - Fork 0
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-13706] Add repository + stored procedures for private key regeneration #11
base: main
Are you sure you want to change the base?
Changes from all commits
a6f2118
4f49c0b
2cb6045
8a1c761
9278677
5554adb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
๏ปฟ#nullable enable | ||
namespace Bit.Core.KeyManagement.Models.Data; | ||
|
||
public class UserAsymmetricKeys | ||
{ | ||
public Guid UserId { get; set; } | ||
public required string PublicKey { get; set; } | ||
public required string UserKeyEncryptedPrivateKey { get; set; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
๏ปฟ#nullable enable | ||
using Bit.Core.KeyManagement.Models.Data; | ||
|
||
namespace Bit.Core.KeyManagement.Repositories; | ||
|
||
public interface IUserAsymmetricKeysRepository | ||
{ | ||
Task RegenerateUserAsymmetricKeysAsync(UserAsymmetricKeys userAsymmetricKeys); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
๏ปฟ#nullable enable | ||
using System.Data; | ||
using Bit.Core.KeyManagement.Models.Data; | ||
using Bit.Core.KeyManagement.Repositories; | ||
using Bit.Core.Settings; | ||
using Bit.Infrastructure.Dapper.Repositories; | ||
using Dapper; | ||
using Microsoft.Data.SqlClient; | ||
|
||
namespace Bit.Infrastructure.Dapper.KeyManagement.Repositories; | ||
|
||
public class UserAsymmetricKeysRepository : BaseRepository, IUserAsymmetricKeysRepository | ||
{ | ||
public UserAsymmetricKeysRepository(GlobalSettings globalSettings) | ||
: this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString) | ||
{ | ||
} | ||
|
||
public UserAsymmetricKeysRepository(string connectionString, string readOnlyConnectionString) : base( | ||
connectionString, readOnlyConnectionString) | ||
{ | ||
} | ||
|
||
public async Task RegenerateUserAsymmetricKeysAsync(UserAsymmetricKeys userAsymmetricKeys) | ||
{ | ||
await using var connection = new SqlConnection(ConnectionString); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: consider using |
||
|
||
await connection.ExecuteAsync("[dbo].[UserAsymmetricKeys_Regenerate]", | ||
new | ||
{ | ||
userAsymmetricKeys.UserId, | ||
userAsymmetricKeys.PublicKey, | ||
PrivateKey = userAsymmetricKeys.UserKeyEncryptedPrivateKey | ||
}, commandType: CommandType.StoredProcedure); | ||
Comment on lines
+28
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: wrap in try-catch to handle potential SQL exceptions |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
๏ปฟ#nullable enable | ||
using AutoMapper; | ||
using Bit.Core.KeyManagement.Models.Data; | ||
using Bit.Core.KeyManagement.Repositories; | ||
using Bit.Infrastructure.EntityFramework.Repositories; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Bit.Infrastructure.EntityFramework.KeyManagement.Repositories; | ||
|
||
public class UserAsymmetricKeysRepository : BaseEntityFrameworkRepository, IUserAsymmetricKeysRepository | ||
{ | ||
public UserAsymmetricKeysRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) : base( | ||
serviceScopeFactory, | ||
mapper) | ||
{ | ||
} | ||
|
||
public async Task RegenerateUserAsymmetricKeysAsync(UserAsymmetricKeys userAsymmetricKeys) | ||
{ | ||
await using var scope = ServiceScopeFactory.CreateAsyncScope(); | ||
var dbContext = GetDatabaseContext(scope); | ||
|
||
var entity = await dbContext.Users.FindAsync(userAsymmetricKeys.UserId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Consider using FirstOrDefaultAsync with a predicate instead of FindAsync for better performance with large datasets |
||
if (entity != null) | ||
{ | ||
var utcNow = DateTime.UtcNow; | ||
entity.PublicKey = userAsymmetricKeys.PublicKey; | ||
entity.PrivateKey = userAsymmetricKeys.UserKeyEncryptedPrivateKey; | ||
entity.RevisionDate = utcNow; | ||
entity.AccountRevisionDate = utcNow; | ||
await dbContext.SaveChangesAsync(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Add error handling around SaveChangesAsync |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
CREATE PROCEDURE [dbo].[UserAsymmetricKeys_Regenerate] | ||
@UserId UNIQUEIDENTIFIER, | ||
@PublicKey VARCHAR(MAX), | ||
@PrivateKey VARCHAR(MAX) | ||
AS | ||
BEGIN | ||
SET NOCOUNT ON | ||
DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); | ||
|
||
UPDATE [dbo].[User] | ||
SET [PublicKey] = @PublicKey, | ||
[PrivateKey] = @PrivateKey, | ||
[RevisionDate] = @UtcNow, | ||
[AccountRevisionDate] = @UtcNow | ||
WHERE [Id] = @UserId | ||
Comment on lines
+10
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Add error handling to check if the update was successful |
||
END |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
CREATE OR ALTER PROCEDURE [dbo].[UserAsymmetricKeys_Regenerate] | ||
@UserId UNIQUEIDENTIFIER, | ||
@PublicKey VARCHAR(MAX), | ||
@PrivateKey VARCHAR(MAX) | ||
Comment on lines
+3
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Consider using NVARCHAR(MAX) for @PublicKey and @privatekey to support Unicode characters |
||
AS | ||
BEGIN | ||
SET NOCOUNT ON | ||
DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); | ||
|
||
UPDATE [dbo].[User] | ||
SET [PublicKey] = @PublicKey, | ||
[PrivateKey] = @PrivateKey, | ||
[RevisionDate] = @UtcNow, | ||
[AccountRevisionDate] = @UtcNow | ||
WHERE [Id] = @UserId | ||
END |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Consider making UserId a required property for consistency