mirror of
https://github.com/bitwarden/server
synced 2025-12-22 03:03:33 +00:00
create ArchiveCipher table
This commit is contained in:
@@ -25,6 +25,12 @@ public class Cipher : ITableObject<Guid>, ICloneable
|
|||||||
public DateTime? DeletedDate { get; set; }
|
public DateTime? DeletedDate { get; set; }
|
||||||
public Enums.CipherRepromptType? Reprompt { get; set; }
|
public Enums.CipherRepromptType? Reprompt { get; set; }
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deprecated as of Nov 2025.
|
||||||
|
/// Source of truth is now CipherArchive (CipherId + UserId).
|
||||||
|
/// Kept for backward compatibility during phased migration.
|
||||||
|
/// </summary>
|
||||||
public DateTime? ArchivedDate { get; set; }
|
public DateTime? ArchivedDate { get; set; }
|
||||||
|
|
||||||
public void SetNewId()
|
public void SetNewId()
|
||||||
|
|||||||
12
src/Core/Vault/Entities/CipherArchive.cs
Normal file
12
src/Core/Vault/Entities/CipherArchive.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Bit.Core.Vault.Entities;
|
||||||
|
|
||||||
|
public class CipherArchive
|
||||||
|
{
|
||||||
|
public Guid CipherId { get; set; }
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
public DateTime ArchivedDate { get; set; }
|
||||||
|
|
||||||
|
public Cipher Cipher { get; set; }
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@ public class DatabaseContext : DbContext
|
|||||||
public DbSet<ApiKey> ApiKeys { get; set; }
|
public DbSet<ApiKey> ApiKeys { get; set; }
|
||||||
public DbSet<Cache> Cache { get; set; }
|
public DbSet<Cache> Cache { get; set; }
|
||||||
public DbSet<Cipher> Ciphers { get; set; }
|
public DbSet<Cipher> Ciphers { get; set; }
|
||||||
|
public DbSet<CipherArchive> CipherArchives { get; set; }
|
||||||
public DbSet<Collection> Collections { get; set; }
|
public DbSet<Collection> Collections { get; set; }
|
||||||
public DbSet<CollectionCipher> CollectionCiphers { get; set; }
|
public DbSet<CollectionCipher> CollectionCiphers { get; set; }
|
||||||
public DbSet<CollectionGroup> CollectionGroups { get; set; }
|
public DbSet<CollectionGroup> CollectionGroups { get; set; }
|
||||||
@@ -162,6 +163,7 @@ public class DatabaseContext : DbContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
eCipher.ToTable(nameof(Cipher));
|
eCipher.ToTable(nameof(Cipher));
|
||||||
|
eCipherArchive.ToTable(nameof(CipherArchive));
|
||||||
eCollection.ToTable(nameof(Collection));
|
eCollection.ToTable(nameof(Collection));
|
||||||
eCollectionCipher.ToTable(nameof(CollectionCipher));
|
eCollectionCipher.ToTable(nameof(CollectionCipher));
|
||||||
eEmergencyAccess.ToTable(nameof(EmergencyAccess));
|
eEmergencyAccess.ToTable(nameof(EmergencyAccess));
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace Bit.Infrastructure.EntityFramework.Vault.Configurations;
|
||||||
|
|
||||||
|
public class CipherArchiveConfiguration : IEntityTypeConfiguration<CipherArchive>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<CipherArchive> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable(nameof(CipherArchive));
|
||||||
|
|
||||||
|
builder.HasKey(ca => new { ca.CipherId, ca.UserId });
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasOne(ca => ca.Cipher)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(ca => ca.CipherId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
// If you want explicit mapping:
|
||||||
|
builder.Property(ca => ca.ArchivedDate).IsRequired();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#nullable disable
|
||||||
|
|
||||||
|
using Bit.Infrastructure.EntityFramework.Vault.Models;
|
||||||
|
|
||||||
|
public class CipherArchive
|
||||||
|
{
|
||||||
|
public Guid CipherId { get; set; }
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
public DateTime ArchivedDate { get; set; }
|
||||||
|
|
||||||
|
// Optional navigation props – you can drop these if you don't want them.
|
||||||
|
public Cipher Cipher { get; set; }
|
||||||
|
}
|
||||||
55
src/Sql/dbo/Vault/Tables/CipherArchive.sql
Normal file
55
src/Sql/dbo/Vault/Tables/CipherArchive.sql
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
IF OBJECT_ID(N'[dbo].[CipherArchive]', N'U') IS NULL
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE [dbo].[CipherArchive]
|
||||||
|
(
|
||||||
|
[CipherId] UNIQUEIDENTIFIER NOT NULL,
|
||||||
|
[UserId] UNIQUEIDENTIFIER NOT NULL,
|
||||||
|
[ArchivedDate] DATETIME2(7) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT [PK_CipherArchive]
|
||||||
|
PRIMARY KEY CLUSTERED ([CipherId], [UserId])
|
||||||
|
);
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys.foreign_keys
|
||||||
|
WHERE name = N'FK_CipherArchive_Cipher'
|
||||||
|
AND parent_object_id = OBJECT_ID(N'[dbo].[CipherArchive]', N'U')
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE [dbo].[CipherArchive]
|
||||||
|
ADD CONSTRAINT [FK_CipherArchive_Cipher]
|
||||||
|
FOREIGN KEY ([CipherId])
|
||||||
|
REFERENCES [dbo].[Cipher]([Id])
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys.foreign_keys
|
||||||
|
WHERE name = N'FK_CipherArchive_User'
|
||||||
|
AND parent_object_id = OBJECT_ID(N'[dbo].[CipherArchive]', N'U')
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE [dbo].[CipherArchive]
|
||||||
|
ADD CONSTRAINT [FK_CipherArchive_User]
|
||||||
|
FOREIGN KEY ([UserId])
|
||||||
|
REFERENCES [dbo].[User]([Id])
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys.indexes
|
||||||
|
WHERE name = N'IX_CipherArchive_UserId'
|
||||||
|
AND object_id = OBJECT_ID(N'[dbo].[CipherArchive]', N'U')
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_CipherArchive_UserId]
|
||||||
|
ON [dbo].[CipherArchive]([UserId]);
|
||||||
|
END;
|
||||||
|
GO
|
||||||
58
util/Migrator/DbScripts/2025-11-13_00_AddCipherArchive.sql
Normal file
58
util/Migrator/DbScripts/2025-11-13_00_AddCipherArchive.sql
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
IF OBJECT_ID(N'[dbo].[CipherArchive]', N'U') IS NULL
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE [dbo].[CipherArchive]
|
||||||
|
(
|
||||||
|
[CipherId] UNIQUEIDENTIFIER NOT NULL,
|
||||||
|
[UserId] UNIQUEIDENTIFIER NOT NULL,
|
||||||
|
[ArchivedDate] DATETIME2(7) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT [PK_CipherArchive]
|
||||||
|
PRIMARY KEY CLUSTERED ([CipherId], [UserId])
|
||||||
|
);
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- FK → Cipher
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys.foreign_keys
|
||||||
|
WHERE name = N'FK_CipherArchive_Cipher'
|
||||||
|
AND parent_object_id = OBJECT_ID(N'[dbo].[CipherArchive]', N'U')
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE [dbo].[CipherArchive]
|
||||||
|
ADD CONSTRAINT [FK_CipherArchive_Cipher]
|
||||||
|
FOREIGN KEY ([CipherId])
|
||||||
|
REFERENCES [dbo].[Cipher]([Id])
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- FK → User
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys.foreign_keys
|
||||||
|
WHERE name = N'FK_CipherArchive_User'
|
||||||
|
AND parent_object_id = OBJECT_ID(N'[dbo].[CipherArchive]', N'U')
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE [dbo].[CipherArchive]
|
||||||
|
ADD CONSTRAINT [FK_CipherArchive_User]
|
||||||
|
FOREIGN KEY ([UserId])
|
||||||
|
REFERENCES [dbo].[User]([Id])
|
||||||
|
ON DELETE CASCADE;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- Optional index for queries by user
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM sys.indexes
|
||||||
|
WHERE name = N'IX_CipherArchive_UserId'
|
||||||
|
AND object_id = OBJECT_ID(N'[dbo].[CipherArchive]', N'U')
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_CipherArchive_UserId]
|
||||||
|
ON [dbo].[CipherArchive]([UserId]);
|
||||||
|
END;
|
||||||
|
GO
|
||||||
Reference in New Issue
Block a user