mirror of
https://github.com/bitwarden/server
synced 2025-12-22 11:13:27 +00:00
[PM-3797 Part 4] Add Sends to new Key Rotation (#3442)
* add send validation * add send repo methods * add send rotation to delegate list * add success test
This commit is contained in:
42
src/Infrastructure.Dapper/Tools/Helpers/SendHelpers.cs
Normal file
42
src/Infrastructure.Dapper/Tools/Helpers/SendHelpers.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Data;
|
||||
using Bit.Core.Tools.Entities;
|
||||
|
||||
namespace Bit.Infrastructure.Dapper.Tools.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Dapper helper methods for Sends
|
||||
/// </summary>
|
||||
public static class SendHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an IEnumerable of Sends to a DataTable
|
||||
/// </summary>
|
||||
/// <remarks>Contains a hardcoded list of properties and must be updated with model</remarks>
|
||||
/// <param name="sends">List of sends</param>
|
||||
/// <returns>A data table matching the schema of dbo.Send containing one row mapped from the items in <see cref="Send"/>s</returns>
|
||||
public static DataTable ToDataTable(this IEnumerable<Send> sends)
|
||||
{
|
||||
var sendsTable = new DataTable();
|
||||
|
||||
var columnData = new List<(string name, Type type, Func<Send, object> getter)>
|
||||
{
|
||||
(nameof(Send.Id), typeof(Guid), c => c.Id),
|
||||
(nameof(Send.UserId), typeof(Guid), c => c.UserId),
|
||||
(nameof(Send.OrganizationId), typeof(Guid), c => c.OrganizationId),
|
||||
(nameof(Send.Type), typeof(short), c => c.Type),
|
||||
(nameof(Send.Data), typeof(string), c => c.Data),
|
||||
(nameof(Send.Key), typeof(string), c => c.Key),
|
||||
(nameof(Send.Password), typeof(string), c => c.Password),
|
||||
(nameof(Send.MaxAccessCount), typeof(int), c => c.MaxAccessCount),
|
||||
(nameof(Send.AccessCount), typeof(int), c => c.AccessCount),
|
||||
(nameof(Send.CreationDate), typeof(DateTime), c => c.CreationDate),
|
||||
(nameof(Send.RevisionDate), typeof(DateTime), c => c.RevisionDate),
|
||||
(nameof(Send.ExpirationDate), typeof(DateTime), c => c.ExpirationDate),
|
||||
(nameof(Send.DeletionDate), typeof(DateTime), c => c.DeletionDate),
|
||||
(nameof(Send.Disabled), typeof(bool), c => c.Disabled),
|
||||
(nameof(Send.HideEmail), typeof(bool), c => c.HideEmail),
|
||||
};
|
||||
|
||||
return sends.BuildTable(sendsTable, columnData);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
#nullable enable
|
||||
|
||||
using System.Data;
|
||||
using Bit.Core.Auth.UserFeatures.UserKey;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Tools.Entities;
|
||||
using Bit.Core.Tools.Repositories;
|
||||
using Bit.Infrastructure.Dapper.Repositories;
|
||||
using Bit.Infrastructure.Dapper.Tools.Helpers;
|
||||
using Dapper;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
@@ -48,4 +50,57 @@ public class SendRepository : Repository<Send, Guid>, ISendRepository
|
||||
return results.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public UpdateEncryptedDataForKeyRotation UpdateForKeyRotation(Guid userId, IEnumerable<Send> sends)
|
||||
{
|
||||
return async (connection, transaction) =>
|
||||
{
|
||||
// Create temp table
|
||||
var sqlCreateTemp = @"
|
||||
SELECT TOP 0 *
|
||||
INTO #TempSend
|
||||
FROM [dbo].[Send]";
|
||||
|
||||
await using (var cmd = new SqlCommand(sqlCreateTemp, connection, transaction))
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
// Bulk copy data into temp table
|
||||
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, transaction))
|
||||
{
|
||||
bulkCopy.DestinationTableName = "#TempSend";
|
||||
var sendsTable = sends.ToDataTable();
|
||||
foreach (DataColumn col in sendsTable.Columns)
|
||||
{
|
||||
bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
|
||||
}
|
||||
|
||||
sendsTable.PrimaryKey = new DataColumn[] { sendsTable.Columns[0] };
|
||||
await bulkCopy.WriteToServerAsync(sendsTable);
|
||||
}
|
||||
|
||||
// Update send table from temp table
|
||||
var sql = @"
|
||||
UPDATE
|
||||
[dbo].[Send]
|
||||
SET
|
||||
[Key] = TS.[Key],
|
||||
[RevisionDate] = TS.[RevisionDate]
|
||||
FROM
|
||||
[dbo].[Send] S
|
||||
INNER JOIN
|
||||
#TempSend TS ON S.Id = TS.Id
|
||||
WHERE
|
||||
S.[UserId] = @UserId
|
||||
DROP TABLE #TempSend";
|
||||
|
||||
await using (var cmd = new SqlCommand(sql, connection, transaction))
|
||||
{
|
||||
cmd.Parameters.Add("@UserId", SqlDbType.UniqueIdentifier).Value = userId;
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user