mirror of
https://github.com/bitwarden/server.git
synced 2025-12-10 00:42:07 -06:00
Add support for external actions
This commit is contained in:
parent
9726f4994f
commit
b4681ccf99
@ -48,7 +48,14 @@ public interface IUserRepository : IRepository<User, Guid>
|
||||
/// <summary>
|
||||
/// Sets the account cryptographic state to a user in a single transaction. The provided
|
||||
/// MUST be a V2 encryption state. Passing in a V1 encryption state will throw.
|
||||
/// Extra actions can be passed in case other user data needs to be updated in the same transaction.
|
||||
/// </summary>
|
||||
Task SetV2AccountCryptographicStateAsync(Guid userId, UserAccountKeysData accountKeysData);
|
||||
Task SetV2AccountCryptographicStateAsync(
|
||||
Guid userId,
|
||||
UserAccountKeysData accountKeysData,
|
||||
IEnumerable<UpdateUserData>? updateUserDataActions = null);
|
||||
Task DeleteManyAsync(IEnumerable<User> users);
|
||||
}
|
||||
|
||||
public delegate Task UpdateUserData(Microsoft.Data.SqlClient.SqlConnection? connection = null,
|
||||
Microsoft.Data.SqlClient.SqlTransaction? transaction = null);
|
||||
|
||||
@ -288,7 +288,10 @@ public class UserRepository : Repository<User, Guid>, IUserRepository
|
||||
UnprotectData(user);
|
||||
}
|
||||
|
||||
public async Task SetV2AccountCryptographicStateAsync(Guid userId, UserAccountKeysData accountKeysData)
|
||||
public async Task SetV2AccountCryptographicStateAsync(
|
||||
Guid userId,
|
||||
UserAccountKeysData accountKeysData,
|
||||
IEnumerable<UpdateUserData>? updateUserDataActions = null)
|
||||
{
|
||||
if (!accountKeysData.IsV2Encryption())
|
||||
{
|
||||
@ -299,27 +302,47 @@ public class UserRepository : Repository<User, Guid>, IUserRepository
|
||||
var signatureKeyPairId = CoreHelpers.GenerateComb();
|
||||
|
||||
await using var connection = new SqlConnection(ConnectionString);
|
||||
await using var cmd = new SqlCommand("[dbo].[User_UpdateAccountCryptographicState]", connection);
|
||||
cmd.CommandType = CommandType.StoredProcedure;
|
||||
cmd.Parameters.Add("@Id", SqlDbType.UniqueIdentifier).Value = userId;
|
||||
cmd.Parameters.Add("@PublicKey", SqlDbType.NVarChar).Value = accountKeysData.PublicKeyEncryptionKeyPairData.PublicKey;
|
||||
cmd.Parameters.Add("@PrivateKey", SqlDbType.NVarChar).Value = accountKeysData.PublicKeyEncryptionKeyPairData.WrappedPrivateKey;
|
||||
cmd.Parameters.Add("@SignedPublicKey", SqlDbType.NVarChar).Value =
|
||||
accountKeysData.PublicKeyEncryptionKeyPairData.SignedPublicKey;
|
||||
cmd.Parameters.Add("@SecurityState", SqlDbType.NVarChar).Value =
|
||||
accountKeysData.SecurityStateData!.SecurityState;
|
||||
cmd.Parameters.Add("@SecurityVersion", SqlDbType.Int).Value =
|
||||
accountKeysData.SecurityStateData!.SecurityVersion;
|
||||
cmd.Parameters.Add("@SignatureKeyPairId", SqlDbType.UniqueIdentifier).Value = signatureKeyPairId;
|
||||
cmd.Parameters.Add("@SignatureAlgorithm", SqlDbType.TinyInt).Value = accountKeysData.SignatureKeyPairData!.SignatureAlgorithm;
|
||||
cmd.Parameters.Add("@SigningKey", SqlDbType.VarChar).Value =
|
||||
accountKeysData.SignatureKeyPairData!.WrappedSigningKey;
|
||||
cmd.Parameters.Add("@VerifyingKey", SqlDbType.VarChar).Value =
|
||||
accountKeysData.SignatureKeyPairData!.VerifyingKey;
|
||||
cmd.Parameters.Add("@RevisionDate", SqlDbType.DateTime2).Value = timestamp;
|
||||
cmd.Parameters.Add("@AccountRevisionDate", SqlDbType.DateTime2).Value = timestamp;
|
||||
await connection.OpenAsync();
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
|
||||
await using var transaction = connection.BeginTransaction();
|
||||
try
|
||||
{
|
||||
await connection.ExecuteAsync(
|
||||
"[dbo].[User_UpdateAccountCryptographicState]",
|
||||
new
|
||||
{
|
||||
Id = userId,
|
||||
PublicKey = accountKeysData.PublicKeyEncryptionKeyPairData.PublicKey,
|
||||
PrivateKey = accountKeysData.PublicKeyEncryptionKeyPairData.WrappedPrivateKey,
|
||||
SignedPublicKey = accountKeysData.PublicKeyEncryptionKeyPairData.SignedPublicKey,
|
||||
SecurityState = accountKeysData.SecurityStateData!.SecurityState,
|
||||
SecurityVersion = accountKeysData.SecurityStateData!.SecurityVersion,
|
||||
SignatureKeyPairId = signatureKeyPairId,
|
||||
SignatureAlgorithm = accountKeysData.SignatureKeyPairData!.SignatureAlgorithm,
|
||||
SigningKey = accountKeysData.SignatureKeyPairData!.WrappedSigningKey,
|
||||
VerifyingKey = accountKeysData.SignatureKeyPairData!.VerifyingKey,
|
||||
RevisionDate = timestamp,
|
||||
AccountRevisionDate = timestamp
|
||||
},
|
||||
transaction: transaction,
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
// Update user data that depends on cryptographic state
|
||||
if (updateUserDataActions != null)
|
||||
{
|
||||
foreach (var action in updateUserDataActions)
|
||||
{
|
||||
await action(connection, transaction);
|
||||
}
|
||||
}
|
||||
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<User>> GetManyAsync(IEnumerable<Guid> ids)
|
||||
|
||||
@ -242,7 +242,10 @@ public class UserRepository : Repository<Core.Entities.User, User, Guid>, IUserR
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
|
||||
public async Task SetV2AccountCryptographicStateAsync(Guid userId, UserAccountKeysData accountKeysData)
|
||||
public async Task SetV2AccountCryptographicStateAsync(
|
||||
Guid userId,
|
||||
UserAccountKeysData accountKeysData,
|
||||
IEnumerable<UpdateUserData>? updateUserDataActions = null)
|
||||
{
|
||||
if (!accountKeysData.IsV2Encryption())
|
||||
{
|
||||
@ -301,6 +304,15 @@ public class UserRepository : Repository<Core.Entities.User, User, Guid>, IUserR
|
||||
}
|
||||
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
// Update additional user data within the same transaction
|
||||
if (updateUserDataActions != null)
|
||||
{
|
||||
foreach (var action in updateUserDataActions)
|
||||
{
|
||||
await action();
|
||||
}
|
||||
}
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
|
||||
|
||||
@ -15,62 +15,51 @@ AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
BEGIN TRANSACTION
|
||||
UPDATE
|
||||
[dbo].[User]
|
||||
SET
|
||||
[PublicKey] = @PublicKey,
|
||||
[PrivateKey] = @PrivateKey,
|
||||
[SignedPublicKey] = @SignedPublicKey,
|
||||
[SecurityState] = @SecurityState,
|
||||
[SecurityVersion] = @SecurityVersion,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[AccountRevisionDate] = @AccountRevisionDate
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
BEGIN TRY
|
||||
UPDATE
|
||||
[dbo].[User]
|
||||
IF EXISTS (SELECT 1 FROM [dbo].[UserSignatureKeyPair] WHERE [UserId] = @Id)
|
||||
BEGIN
|
||||
UPDATE [dbo].[UserSignatureKeyPair]
|
||||
SET
|
||||
[PublicKey] = @PublicKey,
|
||||
[PrivateKey] = @PrivateKey,
|
||||
[SignedPublicKey] = @SignedPublicKey,
|
||||
[SecurityState] = @SecurityState,
|
||||
[SecurityVersion] = @SecurityVersion,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[AccountRevisionDate] = @AccountRevisionDate
|
||||
[SignatureAlgorithm] = @SignatureAlgorithm,
|
||||
[SigningKey] = @SigningKey,
|
||||
[VerifyingKey] = @VerifyingKey,
|
||||
[RevisionDate] = @RevisionDate
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
IF EXISTS (SELECT 1 FROM [dbo].[UserSignatureKeyPair] WHERE [UserId] = @Id)
|
||||
BEGIN
|
||||
UPDATE [dbo].[UserSignatureKeyPair]
|
||||
SET
|
||||
[SignatureAlgorithm] = @SignatureAlgorithm,
|
||||
[SigningKey] = @SigningKey,
|
||||
[VerifyingKey] = @VerifyingKey,
|
||||
[RevisionDate] = @RevisionDate
|
||||
WHERE
|
||||
[UserId] = @Id
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
INSERT INTO [dbo].[UserSignatureKeyPair]
|
||||
(
|
||||
[Id],
|
||||
[UserId],
|
||||
[SignatureAlgorithm],
|
||||
[SigningKey],
|
||||
[VerifyingKey],
|
||||
[CreationDate],
|
||||
[RevisionDate]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@SignatureKeyPairId,
|
||||
@Id,
|
||||
@SignatureAlgorithm,
|
||||
@SigningKey,
|
||||
@VerifyingKey,
|
||||
@RevisionDate,
|
||||
@RevisionDate
|
||||
)
|
||||
END
|
||||
|
||||
COMMIT TRANSACTION
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
IF @@TRANCOUNT > 0
|
||||
ROLLBACK TRANSACTION
|
||||
THROW
|
||||
END CATCH
|
||||
[UserId] = @Id
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
INSERT INTO [dbo].[UserSignatureKeyPair]
|
||||
(
|
||||
[Id],
|
||||
[UserId],
|
||||
[SignatureAlgorithm],
|
||||
[SigningKey],
|
||||
[VerifyingKey],
|
||||
[CreationDate],
|
||||
[RevisionDate]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@SignatureKeyPairId,
|
||||
@Id,
|
||||
@SignatureAlgorithm,
|
||||
@SigningKey,
|
||||
@VerifyingKey,
|
||||
@RevisionDate,
|
||||
@RevisionDate
|
||||
)
|
||||
END
|
||||
END
|
||||
|
||||
@ -21,63 +21,52 @@ AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
BEGIN TRANSACTION
|
||||
UPDATE
|
||||
[dbo].[User]
|
||||
SET
|
||||
[PublicKey] = @PublicKey,
|
||||
[PrivateKey] = @PrivateKey,
|
||||
[SignedPublicKey] = @SignedPublicKey,
|
||||
[SecurityState] = @SecurityState,
|
||||
[SecurityVersion] = @SecurityVersion,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[AccountRevisionDate] = @AccountRevisionDate
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
BEGIN TRY
|
||||
UPDATE
|
||||
[dbo].[User]
|
||||
IF EXISTS (SELECT 1 FROM [dbo].[UserSignatureKeyPair] WHERE [UserId] = @Id)
|
||||
BEGIN
|
||||
UPDATE [dbo].[UserSignatureKeyPair]
|
||||
SET
|
||||
[PublicKey] = @PublicKey,
|
||||
[PrivateKey] = @PrivateKey,
|
||||
[SignedPublicKey] = @SignedPublicKey,
|
||||
[SecurityState] = @SecurityState,
|
||||
[SecurityVersion] = @SecurityVersion,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[AccountRevisionDate] = @AccountRevisionDate
|
||||
[SignatureAlgorithm] = @SignatureAlgorithm,
|
||||
[SigningKey] = @SigningKey,
|
||||
[VerifyingKey] = @VerifyingKey,
|
||||
[RevisionDate] = @RevisionDate
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
IF EXISTS (SELECT 1 FROM [dbo].[UserSignatureKeyPair] WHERE [UserId] = @Id)
|
||||
BEGIN
|
||||
UPDATE [dbo].[UserSignatureKeyPair]
|
||||
SET
|
||||
[SignatureAlgorithm] = @SignatureAlgorithm,
|
||||
[SigningKey] = @SigningKey,
|
||||
[VerifyingKey] = @VerifyingKey,
|
||||
[RevisionDate] = @RevisionDate
|
||||
WHERE
|
||||
[UserId] = @Id
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
INSERT INTO [dbo].[UserSignatureKeyPair]
|
||||
(
|
||||
[Id],
|
||||
[UserId],
|
||||
[SignatureAlgorithm],
|
||||
[SigningKey],
|
||||
[VerifyingKey],
|
||||
[CreationDate],
|
||||
[RevisionDate]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@SignatureKeyPairId,
|
||||
@Id,
|
||||
@SignatureAlgorithm,
|
||||
@SigningKey,
|
||||
@VerifyingKey,
|
||||
@RevisionDate,
|
||||
@RevisionDate
|
||||
)
|
||||
END
|
||||
|
||||
COMMIT TRANSACTION
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
IF @@TRANCOUNT > 0
|
||||
ROLLBACK TRANSACTION
|
||||
THROW
|
||||
END CATCH
|
||||
[UserId] = @Id
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
INSERT INTO [dbo].[UserSignatureKeyPair]
|
||||
(
|
||||
[Id],
|
||||
[UserId],
|
||||
[SignatureAlgorithm],
|
||||
[SigningKey],
|
||||
[VerifyingKey],
|
||||
[CreationDate],
|
||||
[RevisionDate]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@SignatureKeyPairId,
|
||||
@Id,
|
||||
@SignatureAlgorithm,
|
||||
@SigningKey,
|
||||
@VerifyingKey,
|
||||
@RevisionDate,
|
||||
@RevisionDate
|
||||
)
|
||||
END
|
||||
END
|
||||
GO
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user