Browse Source
* [PM-14373] Introduce SecurityTask entity and related enums * [PM-14373] Add Dapper SecurityTask repository * [PM-14373] Introduce MSSQL table, view, and stored procedures * [PM-14373] Add EF SecurityTask repository and type configurations * [PM-14373] Add EF Migration * [PM-14373] Add integration tests * [PM-14373] Formatting * Typo Co-authored-by: Matt Bishop <mbishop@bitwarden.com> * Typo Co-authored-by: Matt Bishop <mbishop@bitwarden.com> * [PM-14373] Remove DeleteById sproc * [PM-14373] SQL formatting --------- Co-authored-by: Matt Bishop <mbishop@bitwarden.com>pull/5044/head
27 changed files with 9622 additions and 0 deletions
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
using Bit.Core.Entities; |
||||
using Bit.Core.Utilities; |
||||
|
||||
namespace Bit.Core.Vault.Entities; |
||||
|
||||
public class SecurityTask : ITableObject<Guid> |
||||
{ |
||||
public Guid Id { get; set; } |
||||
public Guid OrganizationId { get; set; } |
||||
public Guid? CipherId { get; set; } |
||||
public Enums.SecurityTaskType Type { get; set; } |
||||
public Enums.SecurityTaskStatus Status { get; set; } |
||||
public DateTime CreationDate { get; set; } = DateTime.UtcNow; |
||||
public DateTime RevisionDate { get; set; } = DateTime.UtcNow; |
||||
|
||||
public void SetNewId() |
||||
{ |
||||
Id = CoreHelpers.GenerateComb(); |
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
using System.ComponentModel.DataAnnotations; |
||||
|
||||
namespace Bit.Core.Vault.Enums; |
||||
|
||||
public enum SecurityTaskStatus : byte |
||||
{ |
||||
/// <summary> |
||||
/// Default status for newly created tasks that have not been completed. |
||||
/// </summary> |
||||
[Display(Name = "Pending")] |
||||
Pending = 0, |
||||
|
||||
/// <summary> |
||||
/// Status when a task is considered complete and has no remaining actions |
||||
/// </summary> |
||||
[Display(Name = "Completed")] |
||||
Completed = 1, |
||||
} |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations; |
||||
|
||||
namespace Bit.Core.Vault.Enums; |
||||
|
||||
public enum SecurityTaskType : byte |
||||
{ |
||||
/// <summary> |
||||
/// Task to update a cipher's password that was found to be at-risk by an administrator |
||||
/// </summary> |
||||
[Display(Name = "Update at-risk credential")] |
||||
UpdateAtRiskCredential = 0 |
||||
} |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
using Bit.Core.Repositories; |
||||
using Bit.Core.Vault.Entities; |
||||
|
||||
namespace Bit.Core.Vault.Repositories; |
||||
|
||||
public interface ISecurityTaskRepository : IRepository<SecurityTask, Guid> |
||||
{ |
||||
|
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
using Bit.Core.Settings; |
||||
using Bit.Core.Vault.Entities; |
||||
using Bit.Core.Vault.Repositories; |
||||
using Bit.Infrastructure.Dapper.Repositories; |
||||
|
||||
namespace Bit.Infrastructure.Dapper.Vault.Repositories; |
||||
|
||||
public class SecurityTaskRepository : Repository<SecurityTask, Guid>, ISecurityTaskRepository |
||||
{ |
||||
public SecurityTaskRepository(GlobalSettings globalSettings) |
||||
: this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString) |
||||
{ } |
||||
|
||||
public SecurityTaskRepository(string connectionString, string readOnlyConnectionString) |
||||
: base(connectionString, readOnlyConnectionString) |
||||
{ } |
||||
|
||||
} |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
using Bit.Infrastructure.EntityFramework.Vault.Models; |
||||
using Microsoft.EntityFrameworkCore; |
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders; |
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Vault.Configurations; |
||||
|
||||
public class SecurityTaskEntityTypeConfiguration : IEntityTypeConfiguration<SecurityTask> |
||||
{ |
||||
public void Configure(EntityTypeBuilder<SecurityTask> builder) |
||||
{ |
||||
builder |
||||
.Property(s => s.Id) |
||||
.ValueGeneratedNever(); |
||||
|
||||
builder |
||||
.HasKey(s => s.Id) |
||||
.IsClustered(); |
||||
|
||||
builder |
||||
.HasIndex(s => s.OrganizationId) |
||||
.IsClustered(false); |
||||
|
||||
builder |
||||
.HasIndex(s => s.CipherId) |
||||
.IsClustered(false); |
||||
|
||||
builder |
||||
.ToTable(nameof(SecurityTask)); |
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
using AutoMapper; |
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models; |
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Vault.Models; |
||||
|
||||
public class SecurityTask : Core.Vault.Entities.SecurityTask |
||||
{ |
||||
public virtual Organization Organization { get; set; } |
||||
public virtual Cipher Cipher { get; set; } |
||||
} |
||||
|
||||
public class SecurityTaskMapperProfile : Profile |
||||
{ |
||||
public SecurityTaskMapperProfile() |
||||
{ |
||||
CreateMap<Core.Vault.Entities.SecurityTask, SecurityTask>().ReverseMap(); |
||||
} |
||||
} |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
using AutoMapper; |
||||
using Bit.Core.Vault.Repositories; |
||||
using Bit.Infrastructure.EntityFramework.Repositories; |
||||
using Bit.Infrastructure.EntityFramework.Vault.Models; |
||||
using Microsoft.Extensions.DependencyInjection; |
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Vault.Repositories; |
||||
|
||||
public class SecurityTaskRepository : Repository<Core.Vault.Entities.SecurityTask, SecurityTask, Guid>, ISecurityTaskRepository |
||||
{ |
||||
public SecurityTaskRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) |
||||
: base(serviceScopeFactory, mapper, (context) => context.SecurityTasks) |
||||
{ } |
||||
} |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
CREATE PROCEDURE [dbo].[SecurityTask_Create] |
||||
@Id UNIQUEIDENTIFIER OUTPUT, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@CipherId UNIQUEIDENTIFIER, |
||||
@Type TINYINT, |
||||
@Status TINYINT, |
||||
@CreationDate DATETIME2(7), |
||||
@RevisionDate DATETIME2(7) |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
INSERT INTO [dbo].[SecurityTask] |
||||
( |
||||
[Id], |
||||
[OrganizationId], |
||||
[CipherId], |
||||
[Type], |
||||
[Status], |
||||
[CreationDate], |
||||
[RevisionDate] |
||||
) |
||||
VALUES |
||||
( |
||||
@Id, |
||||
@OrganizationId, |
||||
@CipherId, |
||||
@Type, |
||||
@Status, |
||||
@CreationDate, |
||||
@RevisionDate |
||||
) |
||||
END |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
CREATE PROCEDURE [dbo].[SecurityTask_ReadById] |
||||
@Id UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
* |
||||
FROM |
||||
[dbo].[SecurityTaskView] |
||||
WHERE |
||||
[Id] = @Id |
||||
END |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
CREATE PROCEDURE [dbo].[SecurityTask_Update] |
||||
@Id UNIQUEIDENTIFIER, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@CipherId UNIQUEIDENTIFIER, |
||||
@Type TINYINT, |
||||
@Status TINYINT, |
||||
@CreationDate DATETIME2(7), |
||||
@RevisionDate DATETIME2(7) |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
UPDATE |
||||
[dbo].[SecurityTask] |
||||
SET |
||||
[OrganizationId] = @OrganizationId, |
||||
[CipherId] = @CipherId, |
||||
[Type] = @Type, |
||||
[Status] = @Status, |
||||
[CreationDate] = @CreationDate, |
||||
[RevisionDate] = @RevisionDate |
||||
WHERE |
||||
[Id] = @Id |
||||
END |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
CREATE TABLE [dbo].[SecurityTask] |
||||
( |
||||
[Id] UNIQUEIDENTIFIER NOT NULL, |
||||
[OrganizationId] UNIQUEIDENTIFIER NOT NULL, |
||||
[CipherId] UNIQUEIDENTIFIER NULL, |
||||
[Type] TINYINT NOT NULL, |
||||
[Status] TINYINT NOT NULL, |
||||
[CreationDate] DATETIME2 (7) NOT NULL, |
||||
[RevisionDate] DATETIME2 (7) NOT NULL, |
||||
CONSTRAINT [PK_SecurityTask] PRIMARY KEY CLUSTERED ([Id] ASC), |
||||
CONSTRAINT [FK_SecurityTask_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE, |
||||
CONSTRAINT [FK_SecurityTask_Cipher] FOREIGN KEY ([CipherId]) REFERENCES [dbo].[Cipher] ([Id]) ON DELETE CASCADE, |
||||
); |
||||
|
||||
GO |
||||
CREATE NONCLUSTERED INDEX [IX_SecurityTask_CipherId] |
||||
ON [dbo].[SecurityTask]([CipherId] ASC) WHERE CipherId IS NOT NULL; |
||||
|
||||
GO |
||||
CREATE NONCLUSTERED INDEX [IX_SecurityTask_OrganizationId] |
||||
ON [dbo].[SecurityTask]([OrganizationId] ASC) WHERE OrganizationId IS NOT NULL; |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
CREATE VIEW [dbo].[SecurityTaskView] |
||||
AS |
||||
SELECT |
||||
* |
||||
FROM |
||||
[dbo].[SecurityTask] |
||||
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
using Bit.Core.AdminConsole.Entities; |
||||
using Bit.Core.Billing.Enums; |
||||
using Bit.Core.Repositories; |
||||
using Bit.Core.Vault.Entities; |
||||
using Bit.Core.Vault.Enums; |
||||
using Bit.Core.Vault.Repositories; |
||||
using Xunit; |
||||
|
||||
namespace Bit.Infrastructure.IntegrationTest.Vault.Repositories; |
||||
|
||||
public class SecurityTaskRepositoryTests |
||||
{ |
||||
[DatabaseTheory, DatabaseData] |
||||
public async Task CreateAsync( |
||||
IOrganizationRepository organizationRepository, |
||||
ICipherRepository cipherRepository, |
||||
ISecurityTaskRepository securityTaskRepository) |
||||
{ |
||||
var organization = await organizationRepository.CreateAsync(new Organization |
||||
{ |
||||
Name = "Test Org", |
||||
PlanType = PlanType.EnterpriseAnnually, |
||||
Plan = "Test Plan", |
||||
BillingEmail = "billing@email.com" |
||||
}); |
||||
|
||||
var cipher = await cipherRepository.CreateAsync(new Cipher |
||||
{ |
||||
Type = CipherType.Login, |
||||
OrganizationId = organization.Id, |
||||
Data = "", |
||||
}); |
||||
|
||||
var task = await securityTaskRepository.CreateAsync(new SecurityTask |
||||
{ |
||||
OrganizationId = organization.Id, |
||||
CipherId = cipher.Id, |
||||
Status = SecurityTaskStatus.Pending, |
||||
Type = SecurityTaskType.UpdateAtRiskCredential, |
||||
}); |
||||
|
||||
Assert.NotNull(task); |
||||
} |
||||
|
||||
[DatabaseTheory, DatabaseData] |
||||
public async Task ReadByIdAsync( |
||||
IOrganizationRepository organizationRepository, |
||||
ICipherRepository cipherRepository, |
||||
ISecurityTaskRepository securityTaskRepository) |
||||
{ |
||||
var organization = await organizationRepository.CreateAsync(new Organization |
||||
{ |
||||
Name = "Test Org", |
||||
PlanType = PlanType.EnterpriseAnnually, |
||||
Plan = "Test Plan", |
||||
BillingEmail = "billing@email.com" |
||||
}); |
||||
|
||||
var cipher = await cipherRepository.CreateAsync(new Cipher |
||||
{ |
||||
Type = CipherType.Login, |
||||
OrganizationId = organization.Id, |
||||
Data = "", |
||||
}); |
||||
|
||||
var task = await securityTaskRepository.CreateAsync(new SecurityTask |
||||
{ |
||||
OrganizationId = organization.Id, |
||||
CipherId = cipher.Id, |
||||
Status = SecurityTaskStatus.Pending, |
||||
Type = SecurityTaskType.UpdateAtRiskCredential, |
||||
}); |
||||
|
||||
Assert.NotNull(task); |
||||
|
||||
var readTask = await securityTaskRepository.GetByIdAsync(task.Id); |
||||
|
||||
Assert.NotNull(readTask); |
||||
Assert.Equal(task.Id, readTask.Id); |
||||
Assert.Equal(task.Status, readTask.Status); |
||||
} |
||||
|
||||
[DatabaseTheory, DatabaseData] |
||||
public async Task UpdateAsync( |
||||
IOrganizationRepository organizationRepository, |
||||
ICipherRepository cipherRepository, |
||||
ISecurityTaskRepository securityTaskRepository) |
||||
{ |
||||
var organization = await organizationRepository.CreateAsync(new Organization |
||||
{ |
||||
Name = "Test Org", |
||||
PlanType = PlanType.EnterpriseAnnually, |
||||
Plan = "Test Plan", |
||||
BillingEmail = "billing@email.com" |
||||
}); |
||||
|
||||
var cipher = await cipherRepository.CreateAsync(new Cipher |
||||
{ |
||||
Type = CipherType.Login, |
||||
OrganizationId = organization.Id, |
||||
Data = "", |
||||
}); |
||||
|
||||
var task = await securityTaskRepository.CreateAsync(new SecurityTask |
||||
{ |
||||
OrganizationId = organization.Id, |
||||
CipherId = cipher.Id, |
||||
Status = SecurityTaskStatus.Pending, |
||||
Type = SecurityTaskType.UpdateAtRiskCredential, |
||||
}); |
||||
|
||||
Assert.NotNull(task); |
||||
|
||||
task.Status = SecurityTaskStatus.Completed; |
||||
await securityTaskRepository.ReplaceAsync(task); |
||||
|
||||
var updatedTask = await securityTaskRepository.GetByIdAsync(task.Id); |
||||
|
||||
Assert.NotNull(updatedTask); |
||||
Assert.Equal(task.Id, updatedTask.Id); |
||||
Assert.Equal(SecurityTaskStatus.Completed, updatedTask.Status); |
||||
} |
||||
} |
||||
@ -0,0 +1,114 @@
@@ -0,0 +1,114 @@
|
||||
-- Security Tasks |
||||
|
||||
-- Table |
||||
IF OBJECT_ID('[dbo].[SecurityTask]') IS NULL |
||||
BEGIN |
||||
CREATE TABLE [dbo].[SecurityTask] |
||||
( |
||||
[Id] UNIQUEIDENTIFIER NOT NULL, |
||||
[OrganizationId] UNIQUEIDENTIFIER NOT NULL, |
||||
[CipherId] UNIQUEIDENTIFIER NULL, |
||||
[Type] TINYINT NOT NULL, |
||||
[Status] TINYINT NOT NULL, |
||||
[CreationDate] DATETIME2 (7) NOT NULL, |
||||
[RevisionDate] DATETIME2 (7) NOT NULL, |
||||
CONSTRAINT [PK_SecurityTask] PRIMARY KEY CLUSTERED ([Id] ASC), |
||||
CONSTRAINT [FK_SecurityTask_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE, |
||||
CONSTRAINT [FK_SecurityTask_Cipher] FOREIGN KEY ([CipherId]) REFERENCES [dbo].[Cipher] ([Id]) ON DELETE CASCADE, |
||||
); |
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_SecurityTask_CipherId] |
||||
ON [dbo].[SecurityTask]([CipherId] ASC) WHERE CipherId IS NOT NULL; |
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_SecurityTask_OrganizationId] |
||||
ON [dbo].[SecurityTask]([OrganizationId] ASC) WHERE OrganizationId IS NOT NULL; |
||||
END |
||||
GO |
||||
|
||||
-- View SecurityTask |
||||
CREATE OR ALTER VIEW [dbo].[SecurityTaskView] |
||||
AS |
||||
SELECT |
||||
* |
||||
FROM |
||||
[dbo].[SecurityTask] |
||||
GO |
||||
|
||||
-- Stored Procedures: Create |
||||
CREATE OR ALTER PROCEDURE [dbo].[SecurityTask_Create] |
||||
@Id UNIQUEIDENTIFIER OUTPUT, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@CipherId UNIQUEIDENTIFIER, |
||||
@Type TINYINT, |
||||
@Status TINYINT, |
||||
@CreationDate DATETIME2(7), |
||||
@RevisionDate DATETIME2(7) |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
INSERT INTO [dbo].[SecurityTask] |
||||
( |
||||
[Id], |
||||
[OrganizationId], |
||||
[CipherId], |
||||
[Type], |
||||
[Status], |
||||
[CreationDate], |
||||
[RevisionDate] |
||||
) |
||||
VALUES |
||||
( |
||||
@Id, |
||||
@OrganizationId, |
||||
@CipherId, |
||||
@Type, |
||||
@Status, |
||||
@CreationDate, |
||||
@RevisionDate |
||||
) |
||||
END |
||||
GO |
||||
|
||||
-- Stored Procedures: Update |
||||
CREATE OR ALTER PROCEDURE [dbo].[SecurityTask_Update] |
||||
@Id UNIQUEIDENTIFIER, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@CipherId UNIQUEIDENTIFIER, |
||||
@Type TINYINT, |
||||
@Status TINYINT, |
||||
@CreationDate DATETIME2(7), |
||||
@RevisionDate DATETIME2(7) |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
UPDATE |
||||
[dbo].[SecurityTask] |
||||
SET |
||||
[OrganizationId] = @OrganizationId, |
||||
[CipherId] = @CipherId, |
||||
[Type] = @Type, |
||||
[Status] = @Status, |
||||
[CreationDate] = @CreationDate, |
||||
[RevisionDate] = @RevisionDate |
||||
WHERE |
||||
[Id] = @Id |
||||
END |
||||
GO |
||||
|
||||
-- Stored Procedures: ReadById |
||||
CREATE OR ALTER PROCEDURE [dbo].[SecurityTask_ReadById] |
||||
@Id UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
* |
||||
FROM |
||||
[dbo].[SecurityTaskView] |
||||
WHERE |
||||
[Id] = @Id |
||||
END |
||||
GO |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
||||
#nullable disable |
||||
|
||||
namespace Bit.MySqlMigrations.Migrations; |
||||
|
||||
/// <inheritdoc /> |
||||
public partial class SecurityTasks : Migration |
||||
{ |
||||
/// <inheritdoc /> |
||||
protected override void Up(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.CreateTable( |
||||
name: "SecurityTask", |
||||
columns: table => new |
||||
{ |
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
OrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
CipherId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
Type = table.Column<byte>(type: "tinyint unsigned", nullable: false), |
||||
Status = table.Column<byte>(type: "tinyint unsigned", nullable: false), |
||||
CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false) |
||||
}, |
||||
constraints: table => |
||||
{ |
||||
table.PrimaryKey("PK_SecurityTask", x => x.Id); |
||||
table.ForeignKey( |
||||
name: "FK_SecurityTask_Cipher_CipherId", |
||||
column: x => x.CipherId, |
||||
principalTable: "Cipher", |
||||
principalColumn: "Id"); |
||||
table.ForeignKey( |
||||
name: "FK_SecurityTask_Organization_OrganizationId", |
||||
column: x => x.OrganizationId, |
||||
principalTable: "Organization", |
||||
principalColumn: "Id", |
||||
onDelete: ReferentialAction.Cascade); |
||||
}) |
||||
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
||||
migrationBuilder.CreateIndex( |
||||
name: "IX_SecurityTask_CipherId", |
||||
table: "SecurityTask", |
||||
column: "CipherId"); |
||||
|
||||
migrationBuilder.CreateIndex( |
||||
name: "IX_SecurityTask_OrganizationId", |
||||
table: "SecurityTask", |
||||
column: "OrganizationId"); |
||||
} |
||||
|
||||
/// <inheritdoc /> |
||||
protected override void Down(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.DropTable( |
||||
name: "SecurityTask"); |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
||||
#nullable disable |
||||
|
||||
namespace Bit.PostgresMigrations.Migrations; |
||||
|
||||
/// <inheritdoc /> |
||||
public partial class SecurityTasks : Migration |
||||
{ |
||||
/// <inheritdoc /> |
||||
protected override void Up(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.CreateTable( |
||||
name: "SecurityTask", |
||||
columns: table => new |
||||
{ |
||||
Id = table.Column<Guid>(type: "uuid", nullable: false), |
||||
OrganizationId = table.Column<Guid>(type: "uuid", nullable: false), |
||||
CipherId = table.Column<Guid>(type: "uuid", nullable: true), |
||||
Type = table.Column<byte>(type: "smallint", nullable: false), |
||||
Status = table.Column<byte>(type: "smallint", nullable: false), |
||||
CreationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), |
||||
RevisionDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false) |
||||
}, |
||||
constraints: table => |
||||
{ |
||||
table.PrimaryKey("PK_SecurityTask", x => x.Id); |
||||
table.ForeignKey( |
||||
name: "FK_SecurityTask_Cipher_CipherId", |
||||
column: x => x.CipherId, |
||||
principalTable: "Cipher", |
||||
principalColumn: "Id"); |
||||
table.ForeignKey( |
||||
name: "FK_SecurityTask_Organization_OrganizationId", |
||||
column: x => x.OrganizationId, |
||||
principalTable: "Organization", |
||||
principalColumn: "Id", |
||||
onDelete: ReferentialAction.Cascade); |
||||
}); |
||||
|
||||
migrationBuilder.CreateIndex( |
||||
name: "IX_SecurityTask_CipherId", |
||||
table: "SecurityTask", |
||||
column: "CipherId"); |
||||
|
||||
migrationBuilder.CreateIndex( |
||||
name: "IX_SecurityTask_OrganizationId", |
||||
table: "SecurityTask", |
||||
column: "OrganizationId"); |
||||
} |
||||
|
||||
/// <inheritdoc /> |
||||
protected override void Down(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.DropTable( |
||||
name: "SecurityTask"); |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
||||
#nullable disable |
||||
|
||||
namespace Bit.SqliteMigrations.Migrations; |
||||
|
||||
/// <inheritdoc /> |
||||
public partial class SecurityTasks : Migration |
||||
{ |
||||
/// <inheritdoc /> |
||||
protected override void Up(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.CreateTable( |
||||
name: "SecurityTask", |
||||
columns: table => new |
||||
{ |
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false), |
||||
OrganizationId = table.Column<Guid>(type: "TEXT", nullable: false), |
||||
CipherId = table.Column<Guid>(type: "TEXT", nullable: true), |
||||
Type = table.Column<byte>(type: "INTEGER", nullable: false), |
||||
Status = table.Column<byte>(type: "INTEGER", nullable: false), |
||||
CreationDate = table.Column<DateTime>(type: "TEXT", nullable: false), |
||||
RevisionDate = table.Column<DateTime>(type: "TEXT", nullable: false) |
||||
}, |
||||
constraints: table => |
||||
{ |
||||
table.PrimaryKey("PK_SecurityTask", x => x.Id); |
||||
table.ForeignKey( |
||||
name: "FK_SecurityTask_Cipher_CipherId", |
||||
column: x => x.CipherId, |
||||
principalTable: "Cipher", |
||||
principalColumn: "Id"); |
||||
table.ForeignKey( |
||||
name: "FK_SecurityTask_Organization_OrganizationId", |
||||
column: x => x.OrganizationId, |
||||
principalTable: "Organization", |
||||
principalColumn: "Id", |
||||
onDelete: ReferentialAction.Cascade); |
||||
}); |
||||
|
||||
migrationBuilder.CreateIndex( |
||||
name: "IX_SecurityTask_CipherId", |
||||
table: "SecurityTask", |
||||
column: "CipherId"); |
||||
|
||||
migrationBuilder.CreateIndex( |
||||
name: "IX_SecurityTask_OrganizationId", |
||||
table: "SecurityTask", |
||||
column: "OrganizationId"); |
||||
} |
||||
|
||||
/// <inheritdoc /> |
||||
protected override void Down(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.DropTable( |
||||
name: "SecurityTask"); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue