mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 16:12:49 -05:00
Merge branch 'master' into feature/flexible-collections
This commit is contained in:
@ -36,6 +36,7 @@ public class CiphersController : Controller
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly ILogger<CiphersController> _logger;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
private readonly Version _cipherKeyEncryptionMinimumVersion = new Version(Constants.CipherKeyEncryptionMinimumVersion);
|
||||
|
||||
public CiphersController(
|
||||
ICipherRepository cipherRepository,
|
||||
@ -177,6 +178,8 @@ public class CiphersController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
ValidateItemLevelEncryptionIsAvailable(cipher);
|
||||
|
||||
var collectionIds = (await _collectionCipherRepository.GetManyByUserIdCipherIdAsync(userId, id)).Select(c => c.CollectionId).ToList();
|
||||
var modelOrgId = string.IsNullOrWhiteSpace(model.OrganizationId) ?
|
||||
(Guid?)null : new Guid(model.OrganizationId);
|
||||
@ -198,6 +201,9 @@ public class CiphersController : Controller
|
||||
{
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
var cipher = await _cipherRepository.GetOrganizationDetailsByIdAsync(id);
|
||||
|
||||
ValidateItemLevelEncryptionIsAvailable(cipher);
|
||||
|
||||
if (cipher == null || !cipher.OrganizationId.HasValue ||
|
||||
!await _currentContext.EditAnyCollection(cipher.OrganizationId.Value))
|
||||
{
|
||||
@ -576,6 +582,8 @@ public class CiphersController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
ValidateItemLevelEncryptionIsAvailable(cipher);
|
||||
|
||||
if (request.FileSize > CipherService.MAX_FILE_SIZE)
|
||||
{
|
||||
throw new BadRequestException($"Max file size is {CipherService.MAX_FILE_SIZE_READABLE}.");
|
||||
@ -795,4 +803,12 @@ public class CiphersController : Controller
|
||||
throw new BadRequestException("Invalid content.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateItemLevelEncryptionIsAvailable(Cipher cipher)
|
||||
{
|
||||
if (cipher.Key != null && _currentContext.ClientVersion < _cipherKeyEncryptionMinimumVersion)
|
||||
{
|
||||
throw new BadRequestException("Cannot edit item. Update to the latest version of Bitwarden and try again.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ public class CipherRequestModel
|
||||
public string FolderId { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public CipherRepromptType Reprompt { get; set; }
|
||||
public string Key { get; set; }
|
||||
[Required]
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
@ -86,6 +87,7 @@ public class CipherRequestModel
|
||||
}
|
||||
|
||||
existingCipher.Reprompt = Reprompt;
|
||||
existingCipher.Key = Key;
|
||||
|
||||
var hasAttachments2 = (Attachments2?.Count ?? 0) > 0;
|
||||
var hasAttachments = (Attachments?.Count ?? 0) > 0;
|
||||
|
@ -63,6 +63,7 @@ public class CipherMiniResponseModel : ResponseModel
|
||||
CreationDate = cipher.CreationDate;
|
||||
DeletedDate = cipher.DeletedDate;
|
||||
Reprompt = cipher.Reprompt.GetValueOrDefault(CipherRepromptType.None);
|
||||
Key = cipher.Key;
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
@ -83,6 +84,7 @@ public class CipherMiniResponseModel : ResponseModel
|
||||
public DateTime CreationDate { get; set; }
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
public CipherRepromptType Reprompt { get; set; }
|
||||
public string Key { get; set; }
|
||||
}
|
||||
|
||||
public class CipherResponseModel : CipherMiniResponseModel
|
||||
|
@ -19,6 +19,8 @@ public static class Constants
|
||||
/// their subscription has expired.
|
||||
/// </summary>
|
||||
public const int OrganizationSelfHostSubscriptionGracePeriodDays = 60;
|
||||
|
||||
public const string CipherKeyEncryptionMinimumVersion = "2023.9.1";
|
||||
}
|
||||
|
||||
public static class TokenPurposes
|
||||
|
@ -21,6 +21,7 @@ public class Cipher : ITableObject<Guid>, ICloneable
|
||||
public DateTime RevisionDate { get; set; } = DateTime.UtcNow;
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
public Enums.CipherRepromptType? Reprompt { get; set; }
|
||||
public string Key { get; set; }
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
|
@ -392,7 +392,8 @@ public class CipherRepository : Repository<Cipher, Guid>, ICipherRepository
|
||||
SET
|
||||
[Data] = TC.[Data],
|
||||
[Attachments] = TC.[Attachments],
|
||||
[RevisionDate] = TC.[RevisionDate]
|
||||
[RevisionDate] = TC.[RevisionDate],
|
||||
[Key] = TC.[Key]
|
||||
FROM
|
||||
[dbo].[Cipher] C
|
||||
INNER JOIN
|
||||
@ -506,7 +507,8 @@ public class CipherRepository : Repository<Cipher, Guid>, ICipherRepository
|
||||
[Data] = TC.[Data],
|
||||
[Attachments] = TC.[Attachments],
|
||||
[RevisionDate] = TC.[RevisionDate],
|
||||
[DeletedDate] = TC.[DeletedDate]
|
||||
[DeletedDate] = TC.[DeletedDate],
|
||||
[Key] = TC.[Key]
|
||||
FROM
|
||||
[dbo].[Cipher] C
|
||||
INNER JOIN
|
||||
@ -728,6 +730,8 @@ public class CipherRepository : Repository<Cipher, Guid>, ICipherRepository
|
||||
ciphersTable.Columns.Add(deletedDateColumn);
|
||||
var repromptColumn = new DataColumn(nameof(c.Reprompt), typeof(short));
|
||||
ciphersTable.Columns.Add(repromptColumn);
|
||||
var keyColummn = new DataColumn(nameof(c.Key), typeof(string));
|
||||
ciphersTable.Columns.Add(keyColummn);
|
||||
|
||||
foreach (DataColumn col in ciphersTable.Columns)
|
||||
{
|
||||
@ -754,6 +758,7 @@ public class CipherRepository : Repository<Cipher, Guid>, ICipherRepository
|
||||
row[revisionDateColumn] = cipher.RevisionDate;
|
||||
row[deletedDateColumn] = cipher.DeletedDate.HasValue ? (object)cipher.DeletedDate : DBNull.Value;
|
||||
row[repromptColumn] = cipher.Reprompt;
|
||||
row[keyColummn] = cipher.Key;
|
||||
|
||||
ciphersTable.Rows.Add(row);
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ public class UserCipherDetailsQuery : IQuery<CipherDetails>
|
||||
Reprompt = c.Reprompt,
|
||||
ViewPassword = true,
|
||||
OrganizationUseTotp = false,
|
||||
Key = c.Key
|
||||
});
|
||||
return union;
|
||||
}
|
||||
|
@ -366,6 +366,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
Reprompt = c.Reprompt,
|
||||
ViewPassword = true,
|
||||
OrganizationUseTotp = false,
|
||||
Key = c.Key
|
||||
};
|
||||
}
|
||||
var ciphers = await cipherDetailsView.ToListAsync();
|
||||
@ -591,6 +592,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
trackedCipher.Attachments = cipher.Attachments;
|
||||
trackedCipher.RevisionDate = cipher.RevisionDate;
|
||||
trackedCipher.DeletedDate = cipher.DeletedDate;
|
||||
trackedCipher.Key = cipher.Key;
|
||||
|
||||
await transaction.CommitAsync();
|
||||
|
||||
|
@ -29,6 +29,7 @@ public class CipherDetailsQuery : IQuery<CipherDetails>
|
||||
RevisionDate = c.RevisionDate,
|
||||
DeletedDate = c.DeletedDate,
|
||||
Reprompt = c.Reprompt,
|
||||
Key = c.Key,
|
||||
Favorite = _userId.HasValue && c.Favorites != null && c.Favorites.ToLowerInvariant().Contains($"\"{_userId}\":true"),
|
||||
FolderId = (_ignoreFolders || !_userId.HasValue || c.Folders == null || !c.Folders.ToLowerInvariant().Contains(_userId.Value.ToString())) ?
|
||||
null :
|
||||
|
@ -26,6 +26,7 @@ SELECT
|
||||
ELSE TRY_CONVERT(UNIQUEIDENTIFIER, JSON_VALUE(C.[Folders], CONCAT('$."', @UserId, '"')))
|
||||
END [FolderId],
|
||||
C.[DeletedDate],
|
||||
C.[Reprompt]
|
||||
C.[Reprompt],
|
||||
C.[Key]
|
||||
FROM
|
||||
[dbo].[Cipher] C
|
@ -15,7 +15,8 @@
|
||||
@ViewPassword BIT, -- not used
|
||||
@OrganizationUseTotp BIT, -- not used
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -35,7 +36,8 @@ BEGIN
|
||||
[CreationDate],
|
||||
[RevisionDate],
|
||||
[DeletedDate],
|
||||
[Reprompt]
|
||||
[Reprompt],
|
||||
[Key]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@ -49,7 +51,8 @@ BEGIN
|
||||
@CreationDate,
|
||||
@RevisionDate,
|
||||
@DeletedDate,
|
||||
@Reprompt
|
||||
@Reprompt,
|
||||
@Key
|
||||
)
|
||||
|
||||
IF @OrganizationId IS NOT NULL
|
||||
|
@ -16,6 +16,7 @@
|
||||
@OrganizationUseTotp BIT, -- not used
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL,
|
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
@ -23,7 +24,7 @@ BEGIN
|
||||
|
||||
EXEC [dbo].[CipherDetails_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||
@Attachments, @CreationDate, @RevisionDate, @FolderId, @Favorite, @Edit, @ViewPassword,
|
||||
@OrganizationUseTotp, @DeletedDate, @Reprompt
|
||||
@OrganizationUseTotp, @DeletedDate, @Reprompt, @Key
|
||||
|
||||
DECLARE @UpdateCollectionsSuccess INT
|
||||
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||
|
@ -6,7 +6,7 @@
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX), -- not used
|
||||
@Folders NVARCHAR(MAX), -- not used
|
||||
@Attachments NVARCHAR(MAX), -- not used
|
||||
@Attachments NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@FolderId UNIQUEIDENTIFIER,
|
||||
@ -15,7 +15,8 @@
|
||||
@ViewPassword BIT, -- not used
|
||||
@OrganizationUseTotp BIT, -- not used
|
||||
@DeletedDate DATETIME2(2),
|
||||
@Reprompt TINYINT
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -48,10 +49,12 @@ BEGIN
|
||||
ELSE
|
||||
JSON_MODIFY([Favorites], @UserIdPath, NULL)
|
||||
END,
|
||||
[Attachments] = @Attachments,
|
||||
[Reprompt] = @Reprompt,
|
||||
[CreationDate] = @CreationDate,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[DeletedDate] = @DeletedDate
|
||||
[DeletedDate] = @DeletedDate,
|
||||
[Key] = @Key
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
|
@ -10,7 +10,8 @@
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -28,7 +29,8 @@ BEGIN
|
||||
[CreationDate],
|
||||
[RevisionDate],
|
||||
[DeletedDate],
|
||||
[Reprompt]
|
||||
[Reprompt],
|
||||
[Key]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@ -43,7 +45,8 @@ BEGIN
|
||||
@CreationDate,
|
||||
@RevisionDate,
|
||||
@DeletedDate,
|
||||
@Reprompt
|
||||
@Reprompt,
|
||||
@Key
|
||||
)
|
||||
|
||||
IF @OrganizationId IS NOT NULL
|
||||
|
@ -11,13 +11,14 @@
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL,
|
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
EXEC [dbo].[Cipher_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||
@Attachments, @CreationDate, @RevisionDate, @DeletedDate, @Reprompt
|
||||
@Attachments, @CreationDate, @RevisionDate, @DeletedDate, @Reprompt, @Key
|
||||
|
||||
DECLARE @UpdateCollectionsSuccess INT
|
||||
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||
|
@ -10,7 +10,8 @@
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -28,7 +29,8 @@ BEGIN
|
||||
[CreationDate] = @CreationDate,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[DeletedDate] = @DeletedDate,
|
||||
[Reprompt] = @Reprompt
|
||||
[Reprompt] = @Reprompt,
|
||||
[Key] = @Key
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL,
|
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
@ -36,7 +37,8 @@ BEGIN
|
||||
[Data] = @Data,
|
||||
[Attachments] = @Attachments,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[DeletedDate] = @DeletedDate
|
||||
[DeletedDate] = @DeletedDate,
|
||||
[Key] = @Key
|
||||
-- No need to update CreationDate, Favorites, Folders, or Type since that data will not change
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
@ -12,6 +12,7 @@ CREATE TABLE [dbo].[Cipher] (
|
||||
[RevisionDate] DATETIME2 (7) NOT NULL,
|
||||
[DeletedDate] DATETIME2 (7) NULL,
|
||||
[Reprompt] TINYINT NULL,
|
||||
[Key] VARCHAR(MAX) NULL,
|
||||
CONSTRAINT [PK_Cipher] PRIMARY KEY CLUSTERED ([Id] ASC),
|
||||
CONSTRAINT [FK_Cipher_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
|
||||
CONSTRAINT [FK_Cipher_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id])
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Reflection;
|
||||
using Bit.Core;
|
||||
using DbUp;
|
||||
using DbUp.Helpers;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@ -24,6 +25,8 @@ public class DbMigrator
|
||||
}
|
||||
|
||||
public bool MigrateMsSqlDatabaseWithRetries(bool enableLogging = true,
|
||||
bool repeatable = false,
|
||||
string folderName = MigratorConstants.DefaultMigrationsFolderName,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var attempt = 1;
|
||||
@ -32,7 +35,7 @@ public class DbMigrator
|
||||
{
|
||||
try
|
||||
{
|
||||
var success = MigrateDatabase(enableLogging, cancellationToken);
|
||||
var success = MigrateDatabase(enableLogging, repeatable, folderName, cancellationToken);
|
||||
return success;
|
||||
}
|
||||
catch (SqlException ex)
|
||||
@ -54,6 +57,8 @@ public class DbMigrator
|
||||
}
|
||||
|
||||
public bool MigrateDatabase(bool enableLogging = true,
|
||||
bool repeatable = false,
|
||||
string folderName = MigratorConstants.DefaultMigrationsFolderName,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (_logger != null)
|
||||
@ -98,12 +103,20 @@ public class DbMigrator
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var builder = DeployChanges.To
|
||||
.SqlDatabase(_connectionString)
|
||||
.JournalToSqlTable("dbo", "Migration")
|
||||
.WithScriptsAndCodeEmbeddedInAssembly(Assembly.GetExecutingAssembly(),
|
||||
s => s.Contains($".DbScripts.") && !s.Contains(".Archive."))
|
||||
s => s.Contains($".{folderName}.") && !s.Contains(".Archive."))
|
||||
.WithTransaction()
|
||||
.WithExecutionTimeout(new TimeSpan(0, 5, 0));
|
||||
|
||||
if (repeatable)
|
||||
{
|
||||
builder.JournalTo(new NullJournal());
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.JournalToSqlTable("dbo", MigratorConstants.SqlTableJournalName);
|
||||
}
|
||||
|
||||
if (enableLogging)
|
||||
{
|
||||
if (_logger != null)
|
||||
|
428
util/Migrator/DbScripts/2023-09-27_00_CipherKeyUpdate.sql
Normal file
428
util/Migrator/DbScripts/2023-09-27_00_CipherKeyUpdate.sql
Normal file
@ -0,0 +1,428 @@
|
||||
-- Add Key Column
|
||||
IF COL_LENGTH('[dbo].[Cipher]', 'Key') IS NULL
|
||||
BEGIN
|
||||
ALTER TABLE [dbo].[Cipher] ADD [Key] VARCHAR (MAX) NULL;
|
||||
END
|
||||
GO
|
||||
|
||||
-- Remove ForceKeyRotation Column from the Cipher table
|
||||
-- (this is to help with the dev work as the column was no longer needed)
|
||||
IF COL_LENGTH('[dbo].[Cipher]', 'ForceKeyRotation') IS NOT NULL
|
||||
BEGIN
|
||||
ALTER TABLE [dbo].[Cipher] DROP CONSTRAINT [D_Cipher_ForceKeyRotation];
|
||||
ALTER TABLE [dbo].[Cipher] DROP COLUMN [ForceKeyRotation];
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER FUNCTION [dbo].[CipherDetails](@UserId UNIQUEIDENTIFIER)
|
||||
RETURNS TABLE
|
||||
AS RETURN
|
||||
SELECT
|
||||
C.[Id],
|
||||
C.[UserId],
|
||||
C.[OrganizationId],
|
||||
C.[Type],
|
||||
C.[Data],
|
||||
C.[Attachments],
|
||||
C.[CreationDate],
|
||||
C.[RevisionDate],
|
||||
CASE
|
||||
WHEN
|
||||
@UserId IS NULL
|
||||
OR C.[Favorites] IS NULL
|
||||
OR JSON_VALUE(C.[Favorites], CONCAT('$."', @UserId, '"')) IS NULL
|
||||
THEN 0
|
||||
ELSE 1
|
||||
END [Favorite],
|
||||
CASE
|
||||
WHEN
|
||||
@UserId IS NULL
|
||||
OR C.[Folders] IS NULL
|
||||
THEN NULL
|
||||
ELSE TRY_CONVERT(UNIQUEIDENTIFIER, JSON_VALUE(C.[Folders], CONCAT('$."', @UserId, '"')))
|
||||
END [FolderId],
|
||||
C.[DeletedDate],
|
||||
C.[Reprompt],
|
||||
C.[Key]
|
||||
FROM
|
||||
[dbo].[Cipher] C
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[UserCipherDetails]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[UserCipherDetails]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[CipherView]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[CipherView]';
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_Create]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT,
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX), -- not used
|
||||
@Folders NVARCHAR(MAX), -- not used
|
||||
@Attachments NVARCHAR(MAX), -- not used
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@FolderId UNIQUEIDENTIFIER,
|
||||
@Favorite BIT,
|
||||
@Edit BIT, -- not used
|
||||
@ViewPassword BIT, -- not used
|
||||
@OrganizationUseTotp BIT, -- not used
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
DECLARE @UserIdKey VARCHAR(50) = CONCAT('"', @UserId, '"')
|
||||
DECLARE @UserIdPath VARCHAR(50) = CONCAT('$.', @UserIdKey)
|
||||
|
||||
INSERT INTO [dbo].[Cipher]
|
||||
(
|
||||
[Id],
|
||||
[UserId],
|
||||
[OrganizationId],
|
||||
[Type],
|
||||
[Data],
|
||||
[Favorites],
|
||||
[Folders],
|
||||
[CreationDate],
|
||||
[RevisionDate],
|
||||
[DeletedDate],
|
||||
[Reprompt],
|
||||
[Key]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@Id,
|
||||
CASE WHEN @OrganizationId IS NULL THEN @UserId ELSE NULL END,
|
||||
@OrganizationId,
|
||||
@Type,
|
||||
@Data,
|
||||
CASE WHEN @Favorite = 1 THEN CONCAT('{', @UserIdKey, ':true}') ELSE NULL END,
|
||||
CASE WHEN @FolderId IS NOT NULL THEN CONCAT('{', @UserIdKey, ':"', @FolderId, '"', '}') ELSE NULL END,
|
||||
@CreationDate,
|
||||
@RevisionDate,
|
||||
@DeletedDate,
|
||||
@Reprompt,
|
||||
@Key
|
||||
)
|
||||
|
||||
IF @OrganizationId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId
|
||||
END
|
||||
ELSE IF @UserId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
|
||||
END
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_Update]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT,
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX), -- not used
|
||||
@Folders NVARCHAR(MAX), -- not used
|
||||
@Attachments NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@FolderId UNIQUEIDENTIFIER,
|
||||
@Favorite BIT,
|
||||
@Edit BIT, -- not used
|
||||
@ViewPassword BIT, -- not used
|
||||
@OrganizationUseTotp BIT, -- not used
|
||||
@DeletedDate DATETIME2(2),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
DECLARE @UserIdKey VARCHAR(50) = CONCAT('"', @UserId, '"')
|
||||
DECLARE @UserIdPath VARCHAR(50) = CONCAT('$.', @UserIdKey)
|
||||
|
||||
UPDATE
|
||||
[dbo].[Cipher]
|
||||
SET
|
||||
[UserId] = CASE WHEN @OrganizationId IS NULL THEN @UserId ELSE NULL END,
|
||||
[OrganizationId] = @OrganizationId,
|
||||
[Type] = @Type,
|
||||
[Data] = @Data,
|
||||
[Folders] =
|
||||
CASE
|
||||
WHEN @FolderId IS NOT NULL AND [Folders] IS NULL THEN
|
||||
CONCAT('{', @UserIdKey, ':"', @FolderId, '"', '}')
|
||||
WHEN @FolderId IS NOT NULL THEN
|
||||
JSON_MODIFY([Folders], @UserIdPath, CAST(@FolderId AS VARCHAR(50)))
|
||||
ELSE
|
||||
JSON_MODIFY([Folders], @UserIdPath, NULL)
|
||||
END,
|
||||
[Favorites] =
|
||||
CASE
|
||||
WHEN @Favorite = 1 AND [Favorites] IS NULL THEN
|
||||
CONCAT('{', @UserIdKey, ':true}')
|
||||
WHEN @Favorite = 1 THEN
|
||||
JSON_MODIFY([Favorites], @UserIdPath, CAST(1 AS BIT))
|
||||
ELSE
|
||||
JSON_MODIFY([Favorites], @UserIdPath, NULL)
|
||||
END,
|
||||
[Attachments] = @Attachments,
|
||||
[Reprompt] = @Reprompt,
|
||||
[CreationDate] = @CreationDate,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[DeletedDate] = @DeletedDate,
|
||||
[Key] = @Key
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
IF @OrganizationId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId
|
||||
END
|
||||
ELSE IF @UserId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
|
||||
END
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Cipher_Update]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT,
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX),
|
||||
@Folders NVARCHAR(MAX),
|
||||
@Attachments NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
UPDATE
|
||||
[dbo].[Cipher]
|
||||
SET
|
||||
[UserId] = CASE WHEN @OrganizationId IS NULL THEN @UserId ELSE NULL END,
|
||||
[OrganizationId] = @OrganizationId,
|
||||
[Type] = @Type,
|
||||
[Data] = @Data,
|
||||
[Favorites] = @Favorites,
|
||||
[Folders] = @Folders,
|
||||
[Attachments] = @Attachments,
|
||||
[CreationDate] = @CreationDate,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[DeletedDate] = @DeletedDate,
|
||||
[Reprompt] = @Reprompt,
|
||||
[Key] = @Key
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
IF @OrganizationId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId
|
||||
END
|
||||
ELSE IF @UserId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
|
||||
END
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Cipher_Create]
|
||||
@Id UNIQUEIDENTIFIER OUTPUT,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT,
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX),
|
||||
@Folders NVARCHAR(MAX),
|
||||
@Attachments NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
INSERT INTO [dbo].[Cipher]
|
||||
(
|
||||
[Id],
|
||||
[UserId],
|
||||
[OrganizationId],
|
||||
[Type],
|
||||
[Data],
|
||||
[Favorites],
|
||||
[Folders],
|
||||
[Attachments],
|
||||
[CreationDate],
|
||||
[RevisionDate],
|
||||
[DeletedDate],
|
||||
[Reprompt],
|
||||
[Key]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@Id,
|
||||
CASE WHEN @OrganizationId IS NULL THEN @UserId ELSE NULL END,
|
||||
@OrganizationId,
|
||||
@Type,
|
||||
@Data,
|
||||
@Favorites,
|
||||
@Folders,
|
||||
@Attachments,
|
||||
@CreationDate,
|
||||
@RevisionDate,
|
||||
@DeletedDate,
|
||||
@Reprompt,
|
||||
@Key
|
||||
)
|
||||
|
||||
IF @OrganizationId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId
|
||||
END
|
||||
ELSE IF @UserId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
|
||||
END
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Cipher_CreateWithCollections]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT,
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX),
|
||||
@Folders NVARCHAR(MAX),
|
||||
@Attachments NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL,
|
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
EXEC [dbo].[Cipher_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||
@Attachments, @CreationDate, @RevisionDate, @DeletedDate, @Reprompt, @Key
|
||||
|
||||
DECLARE @UpdateCollectionsSuccess INT
|
||||
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Cipher_UpdateWithCollections]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT,
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX),
|
||||
@Folders NVARCHAR(MAX),
|
||||
@Attachments NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL,
|
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
BEGIN TRANSACTION Cipher_UpdateWithCollections
|
||||
|
||||
DECLARE @UpdateCollectionsSuccess INT
|
||||
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||
|
||||
IF @UpdateCollectionsSuccess < 0
|
||||
BEGIN
|
||||
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||
SELECT -1 -- -1 = Failure
|
||||
RETURN
|
||||
END
|
||||
|
||||
UPDATE
|
||||
[dbo].[Cipher]
|
||||
SET
|
||||
[UserId] = NULL,
|
||||
[OrganizationId] = @OrganizationId,
|
||||
[Data] = @Data,
|
||||
[Attachments] = @Attachments,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[DeletedDate] = @DeletedDate,
|
||||
[Key] = @Key
|
||||
-- No need to update CreationDate, Favorites, Folders, or Type since that data will not change
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
|
||||
COMMIT TRANSACTION Cipher_UpdateWithCollections
|
||||
|
||||
IF @Attachments IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[Organization_UpdateStorage] @OrganizationId
|
||||
EXEC [dbo].[User_UpdateStorage] @UserId
|
||||
END
|
||||
|
||||
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId
|
||||
|
||||
SELECT 0 -- 0 = Success
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_CreateWithCollections]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER,
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Type TINYINT,
|
||||
@Data NVARCHAR(MAX),
|
||||
@Favorites NVARCHAR(MAX), -- not used
|
||||
@Folders NVARCHAR(MAX), -- not used
|
||||
@Attachments NVARCHAR(MAX), -- not used
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@FolderId UNIQUEIDENTIFIER,
|
||||
@Favorite BIT,
|
||||
@Edit BIT, -- not used
|
||||
@ViewPassword BIT, -- not used
|
||||
@OrganizationUseTotp BIT, -- not used
|
||||
@DeletedDate DATETIME2(7),
|
||||
@Reprompt TINYINT,
|
||||
@Key VARCHAR(MAX) = NULL,
|
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
EXEC [dbo].[CipherDetails_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders,
|
||||
@Attachments, @CreationDate, @RevisionDate, @FolderId, @Favorite, @Edit, @ViewPassword,
|
||||
@OrganizationUseTotp, @DeletedDate, @Reprompt, @Key
|
||||
|
||||
DECLARE @UpdateCollectionsSuccess INT
|
||||
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds
|
||||
END
|
||||
GO
|
@ -2,6 +2,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="DbScripts\**\*.sql" />
|
||||
<EmbeddedResource Include="DbScripts_data_migration\**\*.sql" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
8
util/Migrator/MigratorConstants.cs
Normal file
8
util/Migrator/MigratorConstants.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Bit.Migrator;
|
||||
|
||||
public static class MigratorConstants
|
||||
{
|
||||
public const string SqlTableJournalName = "Migration";
|
||||
public const string DefaultMigrationsFolderName = "DbScripts";
|
||||
public const string TransitionMigrationsFolderName = "DbScripts_data_migration";
|
||||
}
|
@ -70,7 +70,7 @@ public class SqlServerDbMigrator : IDbMigrator
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var builder = DeployChanges.To
|
||||
.SqlDatabase(_connectionString)
|
||||
.JournalToSqlTable("dbo", "Migration")
|
||||
.JournalToSqlTable("dbo", MigratorConstants.SqlTableJournalName)
|
||||
.WithScriptsAndCodeEmbeddedInAssembly(Assembly.GetExecutingAssembly(),
|
||||
s => s.Contains($".DbScripts.") && !s.Contains(".Archive."))
|
||||
.WithTransaction()
|
||||
|
@ -10,6 +10,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandDotNet" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
@ -1,55 +1,51 @@
|
||||
using Bit.Migrator;
|
||||
using CommandDotNet;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
private static IDictionary<string, string> Parameters { get; set; }
|
||||
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
Console.WriteLine("Please enter a database connection string argument.");
|
||||
WriteUsageToConsole();
|
||||
return 1;
|
||||
return new AppRunner<Program>().Run(args);
|
||||
}
|
||||
|
||||
if (args.Length == 1 && (args[0] == "--verbose" || args[0] == "-v"))
|
||||
{
|
||||
Console.WriteLine($"Please enter a database connection string argument before {args[0]} option.");
|
||||
WriteUsageToConsole();
|
||||
return 1;
|
||||
}
|
||||
|
||||
var databaseConnectionString = args[0];
|
||||
|
||||
var verbose = false;
|
||||
|
||||
if (args.Length == 2 && (args[1] == "--verbose" || args[1] == "-v"))
|
||||
{
|
||||
verbose = true;
|
||||
}
|
||||
|
||||
var success = MigrateDatabase(databaseConnectionString, verbose);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
[DefaultCommand]
|
||||
public void Execute(
|
||||
[Operand(Description = "Database connection string")]
|
||||
string databaseConnectionString,
|
||||
[Option('v', "verbose", Description = "Enable verbose output of migrator logs")]
|
||||
bool verbose = false,
|
||||
[Option('r', "repeatable", Description = "Mark scripts as repeatable")]
|
||||
bool repeatable = false,
|
||||
[Option('f', "folder", Description = "Folder name of database scripts")]
|
||||
string folderName = MigratorConstants.DefaultMigrationsFolderName) => MigrateDatabase(databaseConnectionString, verbose, repeatable, folderName);
|
||||
|
||||
private static void WriteUsageToConsole()
|
||||
{
|
||||
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string>");
|
||||
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -v|--verbose (for verbose output of migrator logs)");
|
||||
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -r|--repeatable (for marking scripts as repeatable) -f|--folder <folder-name-in-migrator-project> (for specifying folder name of scripts)");
|
||||
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -v|--verbose (for verbose output of migrator logs) -r|--repeatable (for marking scripts as repeatable) -f|--folder <folder-name-in-migrator-project> (for specifying folder name of scripts)");
|
||||
}
|
||||
|
||||
private static bool MigrateDatabase(string databaseConnectionString, bool verbose = false, int attempt = 1)
|
||||
private static bool MigrateDatabase(string databaseConnectionString, bool verbose = false, bool repeatable = false, string folderName = "")
|
||||
{
|
||||
var logger = CreateLogger(verbose);
|
||||
|
||||
logger.LogInformation($"Migrating database with repeatable: {repeatable} and folderName: {folderName}.");
|
||||
|
||||
var migrator = new DbMigrator(databaseConnectionString, logger);
|
||||
var success = migrator.MigrateMsSqlDatabaseWithRetries(verbose);
|
||||
bool success = false;
|
||||
if (!string.IsNullOrWhiteSpace(folderName))
|
||||
{
|
||||
success = migrator.MigrateMsSqlDatabaseWithRetries(verbose, repeatable, folderName);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = migrator.MigrateMsSqlDatabaseWithRetries(verbose, repeatable);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -2,6 +2,15 @@
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net6.0": {
|
||||
"CommandDotNet": {
|
||||
"type": "Direct",
|
||||
"requested": "[7.0.2, )",
|
||||
"resolved": "7.0.2",
|
||||
"contentHash": "sFfqn4T6Ux4AbGnhS+BZvf9iVeP6b9p9bwaMT8nsefVcYH2tC9MHj3AoY+GG0nnBPmFawRqdgud08cBjBdPByQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.CSharp": "4.7.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "Direct",
|
||||
"requested": "[6.0.0, )",
|
||||
|
2135
util/MySqlMigrations/Migrations/20230208212115_CipherKeyUpdate.Designer.cs
generated
Normal file
2135
util/MySqlMigrations/Migrations/20230208212115_CipherKeyUpdate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Bit.MySqlMigrations.Migrations;
|
||||
|
||||
public partial class CipherKeyUpdate : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Key",
|
||||
table: "Cipher",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Key",
|
||||
table: "Cipher");
|
||||
}
|
||||
}
|
@ -1509,6 +1509,9 @@ namespace Bit.MySqlMigrations.Migrations
|
||||
b.Property<string>("Folders")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<Guid?>("OrganizationId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
|
2146
util/PostgresMigrations/Migrations/20230208210621_CipherKeyUpdate.Designer.cs
generated
Normal file
2146
util/PostgresMigrations/Migrations/20230208210621_CipherKeyUpdate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Bit.PostgresMigrations.Migrations;
|
||||
|
||||
public partial class CipherKeyUpdate : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Key",
|
||||
table: "Cipher",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Key",
|
||||
table: "Cipher");
|
||||
}
|
||||
}
|
@ -1520,6 +1520,9 @@ namespace Bit.PostgresMigrations.Migrations
|
||||
b.Property<string>("Folders")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("OrganizationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
|
@ -190,7 +190,12 @@ public class Program
|
||||
var vaultConnectionString = Helpers.GetValueFromEnvFile("global",
|
||||
"globalSettings__sqlServer__connectionString");
|
||||
var migrator = new DbMigrator(vaultConnectionString, null);
|
||||
migrator.MigrateMsSqlDatabaseWithRetries(false);
|
||||
|
||||
var log = false;
|
||||
|
||||
migrator.MigrateMsSqlDatabaseWithRetries(log);
|
||||
|
||||
migrator.MigrateMsSqlDatabaseWithRetries(log, true, MigratorConstants.TransitionMigrationsFolderName);
|
||||
}
|
||||
|
||||
private static bool ValidateInstallation()
|
||||
|
2133
util/SqliteMigrations/Migrations/20230208210629_CipherKeyUpdate.Designer.cs
generated
Normal file
2133
util/SqliteMigrations/Migrations/20230208210629_CipherKeyUpdate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Bit.SqliteMigrations.Migrations;
|
||||
|
||||
public partial class CipherKeyUpdate : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Key",
|
||||
table: "Cipher",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Key",
|
||||
table: "Cipher");
|
||||
}
|
||||
}
|
@ -1507,6 +1507,9 @@ namespace Bit.SqliteMigrations.Migrations
|
||||
b.Property<string>("Folders")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("OrganizationId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
Reference in New Issue
Block a user