mirror of
https://github.com/bitwarden/server.git
synced 2024-12-11 15:17:44 +01:00
[PM-14373] Introduce SecurityTask database table and repository (#5025)
* [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>
This commit is contained in:
parent
8b1b07884e
commit
eee7494c91
20
src/Core/Vault/Entities/SecurityTask.cs
Normal file
20
src/Core/Vault/Entities/SecurityTask.cs
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
18
src/Core/Vault/Enums/SecurityTaskStatus.cs
Normal file
18
src/Core/Vault/Enums/SecurityTaskStatus.cs
Normal file
@ -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,
|
||||||
|
}
|
12
src/Core/Vault/Enums/SecurityTaskType.cs
Normal file
12
src/Core/Vault/Enums/SecurityTaskType.cs
Normal file
@ -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
|
||||||
|
}
|
9
src/Core/Vault/Repositories/ISecurityTaskRepository.cs
Normal file
9
src/Core/Vault/Repositories/ISecurityTaskRepository.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Vault.Entities;
|
||||||
|
|
||||||
|
namespace Bit.Core.Vault.Repositories;
|
||||||
|
|
||||||
|
public interface ISecurityTaskRepository : IRepository<SecurityTask, Guid>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -59,6 +59,7 @@ public static class DapperServiceCollectionExtensions
|
|||||||
services
|
services
|
||||||
.AddSingleton<IClientOrganizationMigrationRecordRepository, ClientOrganizationMigrationRecordRepository>();
|
.AddSingleton<IClientOrganizationMigrationRecordRepository, ClientOrganizationMigrationRecordRepository>();
|
||||||
services.AddSingleton<IPasswordHealthReportApplicationRepository, PasswordHealthReportApplicationRepository>();
|
services.AddSingleton<IPasswordHealthReportApplicationRepository, PasswordHealthReportApplicationRepository>();
|
||||||
|
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
||||||
|
|
||||||
if (selfHosted)
|
if (selfHosted)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
}
|
@ -96,6 +96,7 @@ public static class EntityFrameworkServiceCollectionExtensions
|
|||||||
services
|
services
|
||||||
.AddSingleton<IClientOrganizationMigrationRecordRepository, ClientOrganizationMigrationRecordRepository>();
|
.AddSingleton<IClientOrganizationMigrationRecordRepository, ClientOrganizationMigrationRecordRepository>();
|
||||||
services.AddSingleton<IPasswordHealthReportApplicationRepository, PasswordHealthReportApplicationRepository>();
|
services.AddSingleton<IPasswordHealthReportApplicationRepository, PasswordHealthReportApplicationRepository>();
|
||||||
|
services.AddSingleton<ISecurityTaskRepository, SecurityTaskRepository>();
|
||||||
|
|
||||||
if (selfHosted)
|
if (selfHosted)
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,7 @@ public class DatabaseContext : DbContext
|
|||||||
public DbSet<NotificationStatus> NotificationStatuses { get; set; }
|
public DbSet<NotificationStatus> NotificationStatuses { get; set; }
|
||||||
public DbSet<ClientOrganizationMigrationRecord> ClientOrganizationMigrationRecords { get; set; }
|
public DbSet<ClientOrganizationMigrationRecord> ClientOrganizationMigrationRecords { get; set; }
|
||||||
public DbSet<PasswordHealthReportApplication> PasswordHealthReportApplications { get; set; }
|
public DbSet<PasswordHealthReportApplication> PasswordHealthReportApplications { get; set; }
|
||||||
|
public DbSet<SecurityTask> SecurityTasks { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
{
|
{
|
||||||
|
@ -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 @@
|
|||||||
|
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 @@
|
|||||||
|
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 @@
|
|||||||
|
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 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[SecurityTask_ReadById]
|
||||||
|
@Id UNIQUEIDENTIFIER
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
[dbo].[SecurityTaskView]
|
||||||
|
WHERE
|
||||||
|
[Id] = @Id
|
||||||
|
END
|
@ -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
|
21
src/Sql/Vault/dbo/Tables/SecurityTask.sql
Normal file
21
src/Sql/Vault/dbo/Tables/SecurityTask.sql
Normal file
@ -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;
|
6
src/Sql/Vault/dbo/Views/SecurityTaskView.sql
Normal file
6
src/Sql/Vault/dbo/Views/SecurityTaskView.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
CREATE VIEW [dbo].[SecurityTaskView]
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
[dbo].[SecurityTask]
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
114
util/Migrator/DbScripts/2024-11-11_00_InitialSecurityTasks.sql
Normal file
114
util/Migrator/DbScripts/2024-11-11_00_InitialSecurityTasks.sql
Normal file
@ -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
|
2940
util/MySqlMigrations/Migrations/20241112001902_SecurityTasks.Designer.cs
generated
Normal file
2940
util/MySqlMigrations/Migrations/20241112001902_SecurityTasks.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||||
|
}
|
||||||
|
}
|
@ -1989,6 +1989,41 @@ namespace Bit.MySqlMigrations.Migrations
|
|||||||
b.ToTable("Folder", (string)null);
|
b.ToTable("Folder", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CipherId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationDate")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<Guid>("OrganizationId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RevisionDate")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<byte>("Status")
|
||||||
|
.HasColumnType("tinyint unsigned");
|
||||||
|
|
||||||
|
b.Property<byte>("Type")
|
||||||
|
.HasColumnType("tinyint unsigned");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", true);
|
||||||
|
|
||||||
|
b.HasIndex("CipherId")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", false);
|
||||||
|
|
||||||
|
b.HasIndex("OrganizationId")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", false);
|
||||||
|
|
||||||
|
b.ToTable("SecurityTask", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ProjectSecret", b =>
|
modelBuilder.Entity("ProjectSecret", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("ProjectsId")
|
b.Property<Guid>("ProjectsId")
|
||||||
@ -2643,6 +2678,23 @@ namespace Bit.MySqlMigrations.Migrations
|
|||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CipherId");
|
||||||
|
|
||||||
|
b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OrganizationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Cipher");
|
||||||
|
|
||||||
|
b.Navigation("Organization");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ProjectSecret", b =>
|
modelBuilder.Entity("ProjectSecret", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null)
|
b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null)
|
||||||
|
2946
util/PostgresMigrations/Migrations/20241112001757_SecurityTasks.Designer.cs
generated
Normal file
2946
util/PostgresMigrations/Migrations/20241112001757_SecurityTasks.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||||
|
}
|
||||||
|
}
|
@ -1995,6 +1995,41 @@ namespace Bit.PostgresMigrations.Migrations
|
|||||||
b.ToTable("Folder", (string)null);
|
b.ToTable("Folder", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CipherId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<Guid>("OrganizationId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RevisionDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<byte>("Status")
|
||||||
|
.HasColumnType("smallint");
|
||||||
|
|
||||||
|
b.Property<byte>("Type")
|
||||||
|
.HasColumnType("smallint");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", true);
|
||||||
|
|
||||||
|
b.HasIndex("CipherId")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", false);
|
||||||
|
|
||||||
|
b.HasIndex("OrganizationId")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", false);
|
||||||
|
|
||||||
|
b.ToTable("SecurityTask", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ProjectSecret", b =>
|
modelBuilder.Entity("ProjectSecret", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("ProjectsId")
|
b.Property<Guid>("ProjectsId")
|
||||||
@ -2649,6 +2684,23 @@ namespace Bit.PostgresMigrations.Migrations
|
|||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CipherId");
|
||||||
|
|
||||||
|
b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OrganizationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Cipher");
|
||||||
|
|
||||||
|
b.Navigation("Organization");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ProjectSecret", b =>
|
modelBuilder.Entity("ProjectSecret", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null)
|
b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null)
|
||||||
|
2929
util/SqliteMigrations/Migrations/20241112001814_SecurityTasks.Designer.cs
generated
Normal file
2929
util/SqliteMigrations/Migrations/20241112001814_SecurityTasks.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||||
|
}
|
||||||
|
}
|
@ -1978,6 +1978,41 @@ namespace Bit.SqliteMigrations.Migrations
|
|||||||
b.ToTable("Folder", (string)null);
|
b.ToTable("Folder", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CipherId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationDate")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("OrganizationId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RevisionDate")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<byte>("Status")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<byte>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", true);
|
||||||
|
|
||||||
|
b.HasIndex("CipherId")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", false);
|
||||||
|
|
||||||
|
b.HasIndex("OrganizationId")
|
||||||
|
.HasAnnotation("SqlServer:Clustered", false);
|
||||||
|
|
||||||
|
b.ToTable("SecurityTask", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ProjectSecret", b =>
|
modelBuilder.Entity("ProjectSecret", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("ProjectsId")
|
b.Property<Guid>("ProjectsId")
|
||||||
@ -2632,6 +2667,23 @@ namespace Bit.SqliteMigrations.Migrations
|
|||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CipherId");
|
||||||
|
|
||||||
|
b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OrganizationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Cipher");
|
||||||
|
|
||||||
|
b.Navigation("Organization");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ProjectSecret", b =>
|
modelBuilder.Entity("ProjectSecret", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null)
|
b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null)
|
||||||
|
Loading…
Reference in New Issue
Block a user