1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-29 13:25:17 +01:00

Initial db work (#1687)

* Add organization sponsorship databases to all providers

* Generalize create and update for database, specialize in code
This commit is contained in:
Matt Gibson 2021-11-04 10:46:49 -05:00 committed by GitHub
parent ee46a6d63b
commit 079adc60b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 4276 additions and 3 deletions

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
using AutoMapper;
namespace Bit.Core.Models.EntityFramework
{
public class OrganizationSponsorship : Table.OrganizationSponsorship
{
public virtual Installation Installation { get; set; }
public virtual Organization SponsoringOrganization { get; set; }
public virtual Organization SponsoredOrganization { get; set; }
}
public class OrganizationSponsorshipMapperProfile : Profile
{
public OrganizationSponsorshipMapperProfile()
{
CreateMap<Table.OrganizationSponsorship, OrganizationSponsorship>().ReverseMap();
}
}
}

View File

@ -7,15 +7,14 @@ namespace Bit.Core.Models.Table
public class OrganizationSponsorship : ITableObject<Guid>
{
public Guid Id { get; set; }
public Guid InstallationId { get; set; }
public Guid? InstallationId { get; set; }
[Required]
public Guid SponsoringOrganizationId { get; set; }
[Required]
public Guid SponsoringOrganizationUserId { get; set; }
public Guid SponsoringUserId { get; set; }
public Guid? SponsoredOrganizationId { get; set; }
[MaxLength(256)]
public string OfferedToEmail { get; set; }
public Guid? SponsoredOrganizationId { get; set; }
[Required]
public bool CloudSponsor { get; set; }
public DateTime? LastSyncDate { get; set; }

View File

@ -26,6 +26,7 @@ namespace Bit.Core.Repositories.EntityFramework
public DbSet<GroupUser> GroupUsers { get; set; }
public DbSet<Installation> Installations { get; set; }
public DbSet<Organization> Organizations { get; set; }
public DbSet<OrganizationSponsorship> organizationSponsorships { get; set; }
public DbSet<OrganizationUser> OrganizationUsers { get; set; }
public DbSet<Policy> Policies { get; set; }
public DbSet<Provider> Providers { get; set; }
@ -55,6 +56,7 @@ namespace Bit.Core.Repositories.EntityFramework
var eGroupUser = builder.Entity<GroupUser>();
var eInstallation = builder.Entity<Installation>();
var eOrganization = builder.Entity<Organization>();
var eOrganizationSponsorship = builder.Entity<OrganizationSponsorship>();
var eOrganizationUser = builder.Entity<OrganizationUser>();
var ePolicy = builder.Entity<Policy>();
var eProvider = builder.Entity<Provider>();
@ -76,6 +78,7 @@ namespace Bit.Core.Repositories.EntityFramework
eGroup.Property(c => c.Id).ValueGeneratedNever();
eInstallation.Property(c => c.Id).ValueGeneratedNever();
eOrganization.Property(c => c.Id).ValueGeneratedNever();
eOrganizationSponsorship.Property(c => c.Id).ValueGeneratedNever();
eOrganizationUser.Property(c => c.Id).ValueGeneratedNever();
ePolicy.Property(c => c.Id).ValueGeneratedNever();
eProvider.Property(c => c.Id).ValueGeneratedNever();
@ -115,6 +118,7 @@ namespace Bit.Core.Repositories.EntityFramework
eGroupUser.ToTable(nameof(GroupUser));
eInstallation.ToTable(nameof(Installation));
eOrganization.ToTable(nameof(Organization));
eOrganizationSponsorship.ToTable(nameof(OrganizationSponsorship));
eOrganizationUser.ToTable(nameof(OrganizationUser));
ePolicy.ToTable(nameof(Policy));
eProvider.ToTable(nameof(Provider));

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using EFModel = Bit.Core.Models.EntityFramework;
using TableModel = Bit.Core.Models.Table;
namespace Bit.Core.Repositories.EntityFramework
{
public class OrganizationSponsorshipRepository : Repository<TableModel.OrganizationSponsorship, EFModel.OrganizationSponsorship, Guid>, IOrganizationSponsorshipRepository
{
public OrganizationSponsorshipRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) :
base(serviceScopeFactory, mapper, (DatabaseContext context) => context.organizationSponsorships)
{
}
public async Task<TableModel.OrganizationSponsorship> GetByOfferedToEmailAsync(string email)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var dbContext = GetDatabaseContext(scope);
var orgSponsorship = await GetDbSet(dbContext).Where(e => e.OfferedToEmail == email)
.FirstOrDefaultAsync();
return orgSponsorship;
}
}
public async Task<TableModel.OrganizationSponsorship> GetBySponsoredOrganizationIdAsync(Guid sponsoredOrganizationId)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var dbContext = GetDatabaseContext(scope);
var orgSponsorship = await GetDbSet(dbContext).Where(e => e.SponsoredOrganizationId == sponsoredOrganizationId)
.FirstOrDefaultAsync();
return orgSponsorship;
}
}
public async Task<TableModel.OrganizationSponsorship> GetBySponsoringOrganizationUserIdAsync(Guid sponsoringOrganizationUserId)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var dbContext = GetDatabaseContext(scope);
var orgSponsorship = await GetDbSet(dbContext).Where(e => e.SponsoringOrganizationUserId == sponsoringOrganizationUserId)
.FirstOrDefaultAsync();
return orgSponsorship;
}
}
}
}

View File

@ -101,6 +101,7 @@ namespace Bit.Core.Utilities
services.AddSingleton<IInstallationRepository, EntityFrameworkRepos.InstallationRepository>();
services.AddSingleton<IMaintenanceRepository, EntityFrameworkRepos.MaintenanceRepository>();
services.AddSingleton<IOrganizationRepository, EntityFrameworkRepos.OrganizationRepository>();
services.AddSingleton<IOrganizationSponsorshipRepository, EntityFrameworkRepos.OrganizationSponsorshipRepository>();
services.AddSingleton<IOrganizationUserRepository, EntityFrameworkRepos.OrganizationUserRepository>();
services.AddSingleton<IPolicyRepository, EntityFrameworkRepos.PolicyRepository>();
services.AddSingleton<ISendRepository, EntityFrameworkRepos.SendRepository>();
@ -127,6 +128,7 @@ namespace Bit.Core.Utilities
services.AddSingleton<IInstallationRepository, SqlServerRepos.InstallationRepository>();
services.AddSingleton<IMaintenanceRepository, SqlServerRepos.MaintenanceRepository>();
services.AddSingleton<IOrganizationRepository, SqlServerRepos.OrganizationRepository>();
services.AddSingleton<IOrganizationSponsorshipRepository, SqlServerRepos.OrganizationSponsorshipRepository>();
services.AddSingleton<IOrganizationUserRepository, SqlServerRepos.OrganizationUserRepository>();
services.AddSingleton<IPolicyRepository, SqlServerRepos.PolicyRepository>();
services.AddSingleton<ISendRepository, SqlServerRepos.SendRepository>();

View File

@ -0,0 +1,43 @@
CREATE PROCEDURE [dbo].[OrganizationSponsorship_Create]
@Id UNIQUEIDENTIFIER OUTPUT,
@InstallationId UNIQUEIDENTIFIER,
@SponsoringOrganizationId UNIQUEIDENTIFIER,
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
@SponsoredOrganizationId UNIQUEIDENTIFIER,
@OfferedToEmail NVARCHAR(256),
@CloudSponsor BIT,
@LastSyncDate DATETIME2 (7),
@TimesRenewedWithoutValidation TINYINT,
@SponsorshipLapsedDate DATETIME2 (7)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[OrganizationSponsorship]
(
[Id],
[InstallationId],
[SponsoringOrganizationId],
[SponsoringOrganizationUserID],
[SponsoredOrganizationId],
[OfferedToEmail],
[CloudSponsor],
[LastSyncDate],
[TimesRenewedWithoutValidation],
[SponsorshipLapsedDate]
)
VALUES
(
@Id,
@InstallationId,
@SponsoringOrganizationId,
@SponsoringOrganizationUserID,
@SponsoredOrganizationId,
@OfferedToEmail,
@CloudSponsor,
@LastSyncDate,
@TimesRenewedWithoutValidation,
@SponsorshipLapsedDate
)
END
GO

View File

@ -0,0 +1,17 @@
CREATE PROCEDURE [dbo].[OrganizationSponsorship_DeleteById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
BEGIN TRANSACTION OrgSponsorship_DeleteById
DELETE
FROM
[dbo].[OrganizationSponsorship]
WHERE
[Id] = @Id
COMMIT TRANSACTION OrgSponsorship_DeleteById
END
GO

View File

@ -0,0 +1,14 @@
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[Id] = @Id
END
GO

View File

@ -0,0 +1,14 @@
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadByOfferedToEmail]
@OfferedToEmail NVARCHAR (256) -- Should not be null
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[OfferedToEmail] = @OfferedToEmail
END
GO

View File

@ -0,0 +1,14 @@
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadBySponsoredOrganizationId]
@SponsoredOrganizationId UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[SponsoredOrganizationId] = @SponsoredOrganizationId
END
GO

View File

@ -0,0 +1,14 @@
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationUserId]
@SponsoringOrganizationUserId UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[SponsoringOrganizationUserId] = @SponsoringOrganizationUserId
END
GO

View File

@ -0,0 +1,31 @@
CREATE PROCEDURE [dbo].[OrganizationSponsorship_Update]
@Id UNIQUEIDENTIFIER,
@InstallationId UNIQUEIDENTIFIER,
@SponsoringOrganizationId UNIQUEIDENTIFIER,
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
@SponsoredOrganizationId UNIQUEIDENTIFIER,
@OfferedToEmail NVARCHAR(256),
@CloudSponsor BIT,
@LastSyncDate DATETIME2 (7),
@TimesRenewedWithoutValidation TINYINT,
@SponsorshipLapsedDate DATETIME2 (7)
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[OrganizationSponsorship]
SET
[InstallationId] = @InstallationId,
[SponsoringOrganizationId] = @SponsoringOrganizationId,
[SponsoringOrganizationUserID] = @SponsoringOrganizationUserID,
[SponsoredOrganizationId] = @SponsoredOrganizationId,
[OfferedToEmail] = @OfferedToEmail,
[CloudSponsor] = @CloudSponsor,
[LastSyncDate] = @LastSyncDate,
[TimesRenewedWithoutValidation] = @TimesRenewedWithoutValidation,
[SponsorshipLapsedDate] = @SponsorshipLapsedDate
WHERE
[Id] = @Id
END
GO

View File

@ -0,0 +1,41 @@
CREATE TABLE [dbo].[OrganizationSponsorship] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[InstallationId] UNIQUEIDENTIFIER NULL,
[SponsoringOrganizationId] UNIQUEIDENTIFIER NOT NULL,
[SponsorginOrganizationUserID] UNIQUEIDENTIFIER NOT NULL,
[SponsoredOrganizationId] UNIQUEIDENTIFIER NULL,
[OfferedToEmail] NVARCHAR (256) NULL,
[CloudSponsor] BIT NULL,
[LastSyncDate] DATETIME2 (7) NULL,
[TimesRenewedWithoutValidation] TINYINT DEFAULT 0,
[SponsorshipLapsedDate] DATETIME2 (7) NULL,
CONSTRAINT [PK_OrganizationSponsorship] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_OrganizationSponsorship_InstallationId] FOREIGN KEY ([InstallationId]) REFERENCES [dbo].[Installation] ([Id]),
CONSTRAINT [FK_OrganizationSponsorship_SponsoringOrg] FOREIGN KEY ([SponsoringOrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
CONSTRAINT [FK_OrganizationSponsorship_SponsoredOrg] FOREIGN KEY ([SponsoredOrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
);
GO
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_InstallationId]
ON [dbo].[Organization]([Id] ASC, [InstallationId] ASC)
WHERE [InstallationId] IS NOT NULL;
GO
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_SponsoringOrganizationId]
ON [dbo].[Organization]([Id] ASC, [SponsoringOrganizationId] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_SponsoringOrganizationUserId]
ON [dbo].[Organization]([Id] ASC, [SponsorginOrganizationUserID] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_OfferedToEmail]
ON [dbo].[Organization]([Id] ASC, [OfferedToEmail] ASC)
WHERE [OfferedToEmail] IS NOT NULL;
GO
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_SponsoredOrganizationID]
ON [dbo].[Organization]([Id] ASC, [SponsoredOrganizationId] ASC)
WHERE [SponsoredOrganizationId] IS NOT NULL;

View File

@ -76,6 +76,7 @@ namespace Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures
cfg.AddProfile<GroupUserMapperProfile>();
cfg.AddProfile<InstallationMapperProfile>();
cfg.AddProfile<OrganizationMapperProfile>();
cfg.AddProfile<OrganizationSponsorshipMapperProfile>();
cfg.AddProfile<OrganizationUserMapperProfile>();
cfg.AddProfile<ProviderMapperProfile>();
cfg.AddProfile<ProviderUserMapperProfile>();

View File

@ -0,0 +1,59 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using AutoFixture.Kernel;
using System;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
namespace Bit.Core.Test.AutoFixture.OrganizationSponsorshipFixtures
{
internal class OrganizationSponsorshipBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.OrganizationSponsorship))
{
return new NoSpecimen();
}
var fixture = new Fixture();
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.OrganizationSponsorship>();
return obj;
}
}
internal class EfOrganizationSponsorship : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new OrganizationSponsorshipBuilder());
fixture.Customizations.Add(new OrganizationUserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationSponsorshipRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfOrganizationSponsorshipAutoDataAttribute : CustomAutoDataAttribute
{
public EfOrganizationSponsorshipAutoDataAttribute() : base(new SutProviderCustomization(), new EfOrganizationSponsorship())
{ }
}
internal class InlineEfOrganizationSponsorshipAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfOrganizationSponsorshipAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfOrganizationSponsorship) }, values)
{ }
}
}

View File

@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class OrganizationSponsorshipCompare : IEqualityComparer<OrganizationSponsorship>
{
public bool Equals(OrganizationSponsorship x, OrganizationSponsorship y)
{
return x.InstallationId.Equals(y.InstallationId) &&
x.SponsoringOrganizationId.Equals(y.SponsoringOrganizationId) &&
x.SponsoringOrganizationUserId.Equals(y.SponsoringOrganizationUserId) &&
x.SponsoredOrganizationId.Equals(y.SponsoredOrganizationId) &&
x.OfferedToEmail.Equals(y.OfferedToEmail) &&
x.CloudSponsor.Equals(y.CloudSponsor) &&
x.TimesRenewedWithoutValidation.Equals(y.TimesRenewedWithoutValidation) &&
x.SponsorshipLapsedDate.ToString().Equals(y.SponsorshipLapsedDate.ToString());
}
public int GetHashCode([DisallowNull] OrganizationSponsorship obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,138 @@
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Collections.Generic;
using System.Linq;
using TableModel = Bit.Core.Models.Table;
using Xunit;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.OrganizationSponsorshipFixtures;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class OrganizationSponsorshipRepositoryTests
{
[CiSkippedTheory, EfOrganizationSponsorshipAutoData]
public async void CreateAsync_Works_DataMatches(
TableModel.OrganizationSponsorship organizationSponsorship, TableModel.Organization sponsoringOrg,
List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.OrganizationRepository sqlOrganizationRepo,
SqlRepo.OrganizationSponsorshipRepository sqlOrganizationSponsorshipRepo,
OrganizationSponsorshipCompare equalityComparer,
List<EfRepo.OrganizationSponsorshipRepository> suts)
{
organizationSponsorship.InstallationId = null;
organizationSponsorship.SponsoredOrganizationId = null;
var savedOrganizationSponsorships = new List<TableModel.OrganizationSponsorship>();
foreach (var (sut, orgRepo) in suts.Zip(efOrgRepos))
{
var efSponsoringOrg = await orgRepo.CreateAsync(sponsoringOrg);
sut.ClearChangeTracking();
organizationSponsorship.SponsoringOrganizationId = efSponsoringOrg.Id;
await sut.CreateAsync(organizationSponsorship);
sut.ClearChangeTracking();
var savedOrganizationSponsorship = await sut.GetByIdAsync(organizationSponsorship.Id);
savedOrganizationSponsorships.Add(savedOrganizationSponsorship);
}
var sqlSponsoringOrg = await sqlOrganizationRepo.CreateAsync(sponsoringOrg);
organizationSponsorship.SponsoringOrganizationId = sqlSponsoringOrg.Id;
var sqlOrganizationSponsorship = await sqlOrganizationSponsorshipRepo.CreateAsync(organizationSponsorship);
savedOrganizationSponsorships.Add(await sqlOrganizationSponsorshipRepo.GetByIdAsync(sqlOrganizationSponsorship.Id));
var distinctItems = savedOrganizationSponsorships.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfOrganizationSponsorshipAutoData]
public async void ReplaceAsync_Works_DataMatches(TableModel.OrganizationSponsorship postOrganizationSponsorship,
TableModel.OrganizationSponsorship replaceOrganizationSponsorship, TableModel.Organization sponsoringOrg,
List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.OrganizationRepository sqlOrganizationRepo,
SqlRepo.OrganizationSponsorshipRepository sqlOrganizationSponsorshipRepo,
OrganizationSponsorshipCompare equalityComparer, List<EfRepo.OrganizationSponsorshipRepository> suts)
{
postOrganizationSponsorship.InstallationId = null;
postOrganizationSponsorship.SponsoredOrganizationId = null;
replaceOrganizationSponsorship.InstallationId = null;
replaceOrganizationSponsorship.SponsoredOrganizationId = null;
var savedOrganizationSponsorships = new List<TableModel.OrganizationSponsorship>();
foreach (var (sut, orgRepo) in suts.Zip(efOrgRepos))
{
var efSponsoringOrg = await orgRepo.CreateAsync(sponsoringOrg);
sut.ClearChangeTracking();
postOrganizationSponsorship.SponsoringOrganizationId = efSponsoringOrg.Id;
replaceOrganizationSponsorship.SponsoringOrganizationId = efSponsoringOrg.Id;
var postEfOrganizationSponsorship = await sut.CreateAsync(postOrganizationSponsorship);
sut.ClearChangeTracking();
replaceOrganizationSponsorship.Id = postEfOrganizationSponsorship.Id;
await sut.ReplaceAsync(replaceOrganizationSponsorship);
sut.ClearChangeTracking();
var replacedOrganizationSponsorship = await sut.GetByIdAsync(replaceOrganizationSponsorship.Id);
savedOrganizationSponsorships.Add(replacedOrganizationSponsorship);
}
var sqlSponsoringOrg = await sqlOrganizationRepo.CreateAsync(sponsoringOrg);
postOrganizationSponsorship.SponsoringOrganizationId = sqlSponsoringOrg.Id;
var postSqlOrganization = await sqlOrganizationSponsorshipRepo.CreateAsync(postOrganizationSponsorship);
replaceOrganizationSponsorship.Id = postSqlOrganization.Id;
await sqlOrganizationSponsorshipRepo.ReplaceAsync(replaceOrganizationSponsorship);
savedOrganizationSponsorships.Add(await sqlOrganizationSponsorshipRepo.GetByIdAsync(replaceOrganizationSponsorship.Id));
var distinctItems = savedOrganizationSponsorships.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfOrganizationSponsorshipAutoData]
public async void DeleteAsync_Works_DataMatches(TableModel.OrganizationSponsorship organizationSponsorship,
TableModel.Organization sponsoringOrg,
List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.OrganizationRepository sqlOrganizationRepo,
SqlRepo.OrganizationSponsorshipRepository sqlOrganizationSponsorshipRepo,
List<EfRepo.OrganizationSponsorshipRepository> suts)
{
organizationSponsorship.InstallationId = null;
organizationSponsorship.SponsoredOrganizationId = null;
foreach (var (sut, orgRepo) in suts.Zip(efOrgRepos))
{
var efSponsoringOrg = await orgRepo.CreateAsync(sponsoringOrg);
sut.ClearChangeTracking();
organizationSponsorship.SponsoringOrganizationId = efSponsoringOrg.Id;
var postEfOrganizationSponsorship = await sut.CreateAsync(organizationSponsorship);
sut.ClearChangeTracking();
var savedEfOrganizationSponsorship = await sut.GetByIdAsync(postEfOrganizationSponsorship.Id);
sut.ClearChangeTracking();
Assert.True(savedEfOrganizationSponsorship != null);
await sut.DeleteAsync(savedEfOrganizationSponsorship);
sut.ClearChangeTracking();
savedEfOrganizationSponsorship = await sut.GetByIdAsync(savedEfOrganizationSponsorship.Id);
Assert.True(savedEfOrganizationSponsorship == null);
}
var sqlSponsoringOrg = await sqlOrganizationRepo.CreateAsync(sponsoringOrg);
organizationSponsorship.SponsoringOrganizationId = sqlSponsoringOrg.Id;
var postSqlOrganizationSponsorship = await sqlOrganizationSponsorshipRepo.CreateAsync(organizationSponsorship);
var savedSqlOrganizationSponsorship = await sqlOrganizationSponsorshipRepo.GetByIdAsync(postSqlOrganizationSponsorship.Id);
Assert.True(savedSqlOrganizationSponsorship != null);
await sqlOrganizationSponsorshipRepo.DeleteAsync(postSqlOrganizationSponsorship);
savedSqlOrganizationSponsorship = await sqlOrganizationSponsorshipRepo.GetByIdAsync(postSqlOrganizationSponsorship.Id);
Assert.True(savedSqlOrganizationSponsorship == null);
}
}
}

View File

@ -0,0 +1,286 @@
-- Create Organization Sponsorships table
IF OBJECT_ID('[dbo].[OrganizationSponsorship]') IS NULL
BEGIN
CREATE TABLE [dbo].[OrganizationSponsorship] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[InstallationId] UNIQUEIDENTIFIER NULL,
[SponsoringOrganizationId] UNIQUEIDENTIFIER NOT NULL,
[SponsoringOrganizationUserID] UNIQUEIDENTIFIER NOT NULL,
[SponsoredOrganizationId] UNIQUEIDENTIFIER NULL,
[OfferedToEmail] NVARCHAR (256) NULL,
[CloudSponsor] BIT NULL,
[LastSyncDate] DATETIME2 (7) NULL,
[TimesRenewedWithoutValidation] TINYINT DEFAULT 0,
[SponsorshipLapsedDate] DATETIME2 (7) NULL,
CONSTRAINT [PK_OrganizationSponsorship] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_OrganizationSponsorship_InstallationId] FOREIGN KEY ([InstallationId]) REFERENCES [dbo].[Installation] ([Id]),
CONSTRAINT [FK_OrganizationSponsorship_SponsoringOrg] FOREIGN KEY ([SponsoringOrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
CONSTRAINT [FK_OrganizationSponsorship_SponsoredOrg] FOREIGN KEY ([SponsoredOrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
);
END
GO
-- Create indexes
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationSponsorship_InstallationId')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_InstallationId]
ON [dbo].[OrganizationSponsorship]([InstallationId] ASC)
WHERE [InstallationId] IS NOT NULL;
END
GO
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationSponsorship_SponsoringOrganizationId')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_SponsoringOrganizationId]
ON [dbo].[OrganizationSponsorship]([SponsoringOrganizationId] ASC)
END
GO
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationSponsorship_SponsoringOrganizationUserId')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_SponsoringOrganizationUserId]
ON [dbo].[OrganizationSponsorship]([SponsoringOrganizationUserID] ASC)
END
GO
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationSponsorship_OfferedToEmail')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_OfferedToEmail]
ON [dbo].[OrganizationSponsorship]([OfferedToEmail] ASC)
WHERE [OfferedToEmail] IS NOT NULL;
END
GO
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationSponsorship_SponsoredOrganizationID')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_SponsoredOrganizationID]
ON [dbo].[OrganizationSponsorship]([SponsoredOrganizationId] ASC)
WHERE [SponsoredOrganizationId] IS NOT NULL;
END
GO
-- Create View
IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'OrganizationSponsorshipView')
BEGIN
DROP VIEW [dbo].[OrganizationSponsorshipView];
END
GO
CREATE VIEW [dbo].[OrganizationSponsorshipView]
AS
SELECT
*
FROM
[dbo].[OrganizationSponsorship]
GO
-- OrganizationSponsorship_ReadById
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadById]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_ReadById]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[Id] = @Id
END
GO
-- OrganizationSponsorship_Create
IF OBJECT_ID('[dbo].[OrganizationSponsorship_Create]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_Create]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_Create]
@Id UNIQUEIDENTIFIER OUTPUT,
@InstallationId UNIQUEIDENTIFIER,
@SponsoringOrganizationId UNIQUEIDENTIFIER,
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
@SponsoredOrganizationId UNIQUEIDENTIFIER,
@OfferedToEmail NVARCHAR(256),
@CloudSponsor BIT,
@LastSyncDate DATETIME2 (7),
@TimesRenewedWithoutValidation TINYINT,
@SponsorshipLapsedDate DATETIME2 (7)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[OrganizationSponsorship]
(
[Id],
[InstallationId],
[SponsoringOrganizationId],
[SponsoringOrganizationUserID],
[SponsoredOrganizationId],
[OfferedToEmail],
[CloudSponsor],
[LastSyncDate],
[TimesRenewedWithoutValidation],
[SponsorshipLapsedDate]
)
VALUES
(
@Id,
@InstallationId,
@SponsoringOrganizationId,
@SponsoringOrganizationUserID,
@SponsoredOrganizationId,
@OfferedToEmail,
@CloudSponsor,
@LastSyncDate,
@TimesRenewedWithoutValidation,
@SponsorshipLapsedDate
)
END
GO
-- OrganizationSponsorship_Update
IF OBJECT_ID('[dbo].[OrganizationSponsorship_Update]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_Update]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_Update]
@Id UNIQUEIDENTIFIER,
@InstallationId UNIQUEIDENTIFIER,
@SponsoringOrganizationId UNIQUEIDENTIFIER,
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
@SponsoredOrganizationId UNIQUEIDENTIFIER,
@OfferedToEmail NVARCHAR(256),
@CloudSponsor BIT,
@LastSyncDate DATETIME2 (7),
@TimesRenewedWithoutValidation TINYINT,
@SponsorshipLapsedDate DATETIME2 (7)
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[OrganizationSponsorship]
SET
[InstallationId] = @InstallationId,
[SponsoringOrganizationId] = @SponsoringOrganizationId,
[SponsoringOrganizationUserID] = @SponsoringOrganizationUserID,
[SponsoredOrganizationId] = @SponsoredOrganizationId,
[OfferedToEmail] = @OfferedToEmail,
[CloudSponsor] = @CloudSponsor,
[LastSyncDate] = @LastSyncDate,
[TimesRenewedWithoutValidation] = @TimesRenewedWithoutValidation,
[SponsorshipLapsedDate] = @SponsorshipLapsedDate
WHERE
[Id] = @Id
END
GO
-- OrganizationSponsorship_DeleteById
IF OBJECT_ID('[dbo].[OrganizationSponsorship_DeleteById]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_DeleteById]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_DeleteById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
BEGIN TRANSACTION OrgSponsorship_DeleteById
DELETE
FROM
[dbo].[OrganizationSponsorship]
WHERE
[Id] = @Id
COMMIT TRANSACTION OrgSponsorship_DeleteById
END
GO
-- OrganizationSponsorship_ReadBySponsoringOrganizationUserId
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationUserId]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationUserId]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationUserId]
@SponsoringOrganizationUserId UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[SponsoringOrganizationUserId] = @SponsoringOrganizationUserId
END
GO
-- OrganizationSponsorship_ReadBySponsoredOrganizationId
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadBySponsoredOrganizationId]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_ReadBySponsoredOrganizationId]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadBySponsoredOrganizationId]
@SponsoredOrganizationId UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[SponsoredOrganizationId] = @SponsoredOrganizationId
END
GO
-- OrganizationSponsorship_ReadByOfferedToEmail
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadByOfferedToEmail]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_ReadByOfferedToEmail]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadByOfferedToEmail]
@OfferedToEmail NVARCHAR (256) -- Should not be null
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[OfferedToEmail] = @OfferedToEmail
END
GO

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Bit.MySqlMigrations.Migrations
{
public partial class OrganizationSponsorship : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "UsesCryptoAgent",
table: "User",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.CreateTable(
name: "OrganizationSponsorship",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
InstallationId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
SponsoringOrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
SponsoringOrganizationUserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
SponsoredOrganizationId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
OfferedToEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
CloudSponsor = table.Column<bool>(type: "tinyint(1)", nullable: false),
LastSyncDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
TimesRenewedWithoutValidation = table.Column<byte>(type: "tinyint unsigned", nullable: false),
SponsorshipLapsedDate = table.Column<DateTime>(type: "datetime(6)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_OrganizationSponsorship", x => x.Id);
table.ForeignKey(
name: "FK_OrganizationSponsorship_Installation_InstallationId",
column: x => x.InstallationId,
principalTable: "Installation",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_OrganizationSponsorship_Organization_SponsoredOrganizationId",
column: x => x.SponsoredOrganizationId,
principalTable: "Organization",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_OrganizationSponsorship_Organization_SponsoringOrganizationId",
column: x => x.SponsoringOrganizationId,
principalTable: "Organization",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_OrganizationSponsorship_InstallationId",
table: "OrganizationSponsorship",
column: "InstallationId");
migrationBuilder.CreateIndex(
name: "IX_OrganizationSponsorship_SponsoredOrganizationId",
table: "OrganizationSponsorship",
column: "SponsoredOrganizationId");
migrationBuilder.CreateIndex(
name: "IX_OrganizationSponsorship_SponsoringOrganizationId",
table: "OrganizationSponsorship",
column: "SponsoringOrganizationId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "OrganizationSponsorship");
migrationBuilder.DropColumn(
name: "UsesCryptoAgent",
table: "User");
}
}
}

View File

@ -585,6 +585,50 @@ namespace Bit.MySqlMigrations.Migrations
b.ToTable("Organization");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationSponsorship", b =>
{
b.Property<Guid>("Id")
.HasColumnType("char(36)");
b.Property<bool>("CloudSponsor")
.HasColumnType("tinyint(1)");
b.Property<Guid?>("InstallationId")
.HasColumnType("char(36)");
b.Property<DateTime?>("LastSyncDate")
.HasColumnType("datetime(6)");
b.Property<string>("OfferedToEmail")
.HasMaxLength(256)
.HasColumnType("varchar(256)");
b.Property<Guid?>("SponsoredOrganizationId")
.HasColumnType("char(36)");
b.Property<Guid>("SponsoringOrganizationId")
.HasColumnType("char(36)");
b.Property<Guid>("SponsoringOrganizationUserId")
.HasColumnType("char(36)");
b.Property<DateTime?>("SponsorshipLapsedDate")
.HasColumnType("datetime(6)");
b.Property<byte>("TimesRenewedWithoutValidation")
.HasColumnType("tinyint unsigned");
b.HasKey("Id");
b.HasIndex("InstallationId");
b.HasIndex("SponsoredOrganizationId");
b.HasIndex("SponsoringOrganizationId");
b.ToTable("OrganizationSponsorship");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
{
b.Property<Guid>("Id")
@ -1127,6 +1171,9 @@ namespace Bit.MySqlMigrations.Migrations
.HasMaxLength(32)
.HasColumnType("varchar(32)");
b.Property<bool>("UsesCryptoAgent")
.HasColumnType("tinyint(1)");
b.HasKey("Id");
b.ToTable("User");
@ -1292,6 +1339,29 @@ namespace Bit.MySqlMigrations.Migrations
b.Navigation("OrganizationUser");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationSponsorship", b =>
{
b.HasOne("Bit.Core.Models.EntityFramework.Installation", "Installation")
.WithMany()
.HasForeignKey("InstallationId");
b.HasOne("Bit.Core.Models.EntityFramework.Organization", "SponsoredOrganization")
.WithMany()
.HasForeignKey("SponsoredOrganizationId");
b.HasOne("Bit.Core.Models.EntityFramework.Organization", "SponsoringOrganization")
.WithMany()
.HasForeignKey("SponsoringOrganizationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Installation");
b.Navigation("SponsoredOrganization");
b.Navigation("SponsoringOrganization");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
{
b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")

View File

@ -0,0 +1,31 @@
START TRANSACTION;
ALTER TABLE `User` ADD `UsesCryptoAgent` tinyint(1) NOT NULL DEFAULT FALSE;
CREATE TABLE `OrganizationSponsorship` (
`Id` char(36) COLLATE ascii_general_ci NOT NULL,
`InstallationId` char(36) COLLATE ascii_general_ci NULL,
`SponsoringOrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
`SponsoringOrganizationUserId` char(36) COLLATE ascii_general_ci NOT NULL,
`SponsoredOrganizationId` char(36) COLLATE ascii_general_ci NULL,
`OfferedToEmail` varchar(256) CHARACTER SET utf8mb4 NULL,
`CloudSponsor` tinyint(1) NOT NULL,
`LastSyncDate` datetime(6) NULL,
`TimesRenewedWithoutValidation` tinyint unsigned NOT NULL,
`SponsorshipLapsedDate` datetime(6) NULL,
CONSTRAINT `PK_OrganizationSponsorship` PRIMARY KEY (`Id`),
CONSTRAINT `FK_OrganizationSponsorship_Installation_InstallationId` FOREIGN KEY (`InstallationId`) REFERENCES `Installation` (`Id`) ON DELETE RESTRICT,
CONSTRAINT `FK_OrganizationSponsorship_Organization_SponsoredOrganizationId` FOREIGN KEY (`SponsoredOrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
CONSTRAINT `FK_OrganizationSponsorship_Organization_SponsoringOrganizationId` FOREIGN KEY (`SponsoringOrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
) CHARACTER SET utf8mb4;
CREATE INDEX `IX_OrganizationSponsorship_InstallationId` ON `OrganizationSponsorship` (`InstallationId`);
CREATE INDEX `IX_OrganizationSponsorship_SponsoredOrganizationId` ON `OrganizationSponsorship` (`SponsoredOrganizationId`);
CREATE INDEX `IX_OrganizationSponsorship_SponsoringOrganizationId` ON `OrganizationSponsorship` (`SponsoringOrganizationId`);
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
VALUES ('20211102213543_OrganizationSponsorship', '5.0.9');
COMMIT;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Bit.PostgresMigrations.Migrations
{
public partial class OrganizationSponsorship : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "UsesCryptoAgent",
table: "User",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.CreateTable(
name: "OrganizationSponsorship",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
InstallationId = table.Column<Guid>(type: "uuid", nullable: true),
SponsoringOrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
SponsoringOrganizationUserId = table.Column<Guid>(type: "uuid", nullable: false),
SponsoredOrganizationId = table.Column<Guid>(type: "uuid", nullable: true),
OfferedToEmail = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
CloudSponsor = table.Column<bool>(type: "boolean", nullable: false),
LastSyncDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
TimesRenewedWithoutValidation = table.Column<byte>(type: "smallint", nullable: false),
SponsorshipLapsedDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_OrganizationSponsorship", x => x.Id);
table.ForeignKey(
name: "FK_OrganizationSponsorship_Installation_InstallationId",
column: x => x.InstallationId,
principalTable: "Installation",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_OrganizationSponsorship_Organization_SponsoredOrganizationId",
column: x => x.SponsoredOrganizationId,
principalTable: "Organization",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_OrganizationSponsorship_Organization_SponsoringOrganization~",
column: x => x.SponsoringOrganizationId,
principalTable: "Organization",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_OrganizationSponsorship_InstallationId",
table: "OrganizationSponsorship",
column: "InstallationId");
migrationBuilder.CreateIndex(
name: "IX_OrganizationSponsorship_SponsoredOrganizationId",
table: "OrganizationSponsorship",
column: "SponsoredOrganizationId");
migrationBuilder.CreateIndex(
name: "IX_OrganizationSponsorship_SponsoringOrganizationId",
table: "OrganizationSponsorship",
column: "SponsoringOrganizationId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "OrganizationSponsorship");
migrationBuilder.DropColumn(
name: "UsesCryptoAgent",
table: "User");
}
}
}

View File

@ -589,6 +589,50 @@ namespace Bit.PostgresMigrations.Migrations
b.ToTable("Organization");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationSponsorship", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid");
b.Property<bool>("CloudSponsor")
.HasColumnType("boolean");
b.Property<Guid?>("InstallationId")
.HasColumnType("uuid");
b.Property<DateTime?>("LastSyncDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("OfferedToEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<Guid?>("SponsoredOrganizationId")
.HasColumnType("uuid");
b.Property<Guid>("SponsoringOrganizationId")
.HasColumnType("uuid");
b.Property<Guid>("SponsoringOrganizationUserId")
.HasColumnType("uuid");
b.Property<DateTime?>("SponsorshipLapsedDate")
.HasColumnType("timestamp without time zone");
b.Property<byte>("TimesRenewedWithoutValidation")
.HasColumnType("smallint");
b.HasKey("Id");
b.HasIndex("InstallationId");
b.HasIndex("SponsoredOrganizationId");
b.HasIndex("SponsoringOrganizationId");
b.ToTable("OrganizationSponsorship");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
{
b.Property<Guid>("Id")
@ -1136,6 +1180,9 @@ namespace Bit.PostgresMigrations.Migrations
.HasMaxLength(32)
.HasColumnType("character varying(32)");
b.Property<bool>("UsesCryptoAgent")
.HasColumnType("boolean");
b.HasKey("Id");
b.ToTable("User");
@ -1301,6 +1348,29 @@ namespace Bit.PostgresMigrations.Migrations
b.Navigation("OrganizationUser");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationSponsorship", b =>
{
b.HasOne("Bit.Core.Models.EntityFramework.Installation", "Installation")
.WithMany()
.HasForeignKey("InstallationId");
b.HasOne("Bit.Core.Models.EntityFramework.Organization", "SponsoredOrganization")
.WithMany()
.HasForeignKey("SponsoredOrganizationId");
b.HasOne("Bit.Core.Models.EntityFramework.Organization", "SponsoringOrganization")
.WithMany()
.HasForeignKey("SponsoringOrganizationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Installation");
b.Navigation("SponsoredOrganization");
b.Navigation("SponsoringOrganization");
});
modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
{
b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")

View File

@ -0,0 +1,31 @@
START TRANSACTION;
ALTER TABLE "User" ADD "UsesCryptoAgent" boolean NOT NULL DEFAULT FALSE;
CREATE TABLE "OrganizationSponsorship" (
"Id" uuid NOT NULL,
"InstallationId" uuid NULL,
"SponsoringOrganizationId" uuid NOT NULL,
"SponsoringOrganizationUserId" uuid NOT NULL,
"SponsoredOrganizationId" uuid NULL,
"OfferedToEmail" character varying(256) NULL,
"CloudSponsor" boolean NOT NULL,
"LastSyncDate" timestamp without time zone NULL,
"TimesRenewedWithoutValidation" smallint NOT NULL,
"SponsorshipLapsedDate" timestamp without time zone NULL,
CONSTRAINT "PK_OrganizationSponsorship" PRIMARY KEY ("Id"),
CONSTRAINT "FK_OrganizationSponsorship_Installation_InstallationId" FOREIGN KEY ("InstallationId") REFERENCES "Installation" ("Id") ON DELETE RESTRICT,
CONSTRAINT "FK_OrganizationSponsorship_Organization_SponsoredOrganizationId" FOREIGN KEY ("SponsoredOrganizationId") REFERENCES "Organization" ("Id") ON DELETE RESTRICT,
CONSTRAINT "FK_OrganizationSponsorship_Organization_SponsoringOrganization~" FOREIGN KEY ("SponsoringOrganizationId") REFERENCES "Organization" ("Id") ON DELETE CASCADE
);
CREATE INDEX "IX_OrganizationSponsorship_InstallationId" ON "OrganizationSponsorship" ("InstallationId");
CREATE INDEX "IX_OrganizationSponsorship_SponsoredOrganizationId" ON "OrganizationSponsorship" ("SponsoredOrganizationId");
CREATE INDEX "IX_OrganizationSponsorship_SponsoringOrganizationId" ON "OrganizationSponsorship" ("SponsoringOrganizationId");
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20211102205745_OrganizationSponsorship', '5.0.9');
COMMIT;