mirror of
https://github.com/bitwarden/server.git
synced 2024-11-29 13:25:17 +01:00
Add PlanSponsorshipType to db model
This commit is contained in:
parent
079adc60b6
commit
d93fcf432f
@ -64,7 +64,7 @@ namespace Bit.Api.Controllers
|
||||
throw new BadRequestException("Can only sponsor one organization per Organization User.");
|
||||
}
|
||||
|
||||
await _organizationsSponsorshipService.OfferSponsorshipAsync(sponsoringOrg, sponsoringOrgUser, model.sponsoredEmail);
|
||||
await _organizationsSponsorshipService.OfferSponsorshipAsync(sponsoringOrg, sponsoringOrgUser, model.PlanSponsorshipType, model.sponsoredEmail);
|
||||
}
|
||||
|
||||
[HttpPost("sponsored/redeem/families-for-enterprise")]
|
||||
|
10
src/Core/Enums/PlanSponsorshipType.cs
Normal file
10
src/Core/Enums/PlanSponsorshipType.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum PlanSponsorshipType : byte
|
||||
{
|
||||
[Display(Name = "Families For Enterprise")]
|
||||
FamiliesForEnterprise = 0,
|
||||
}
|
||||
}
|
@ -1,13 +1,18 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.Models.Api.Request
|
||||
{
|
||||
public class OrganizationSponsorshipRequestModel
|
||||
{
|
||||
[Required]
|
||||
public PlanSponsorshipType PlanSponsorshipType { get; set; }
|
||||
|
||||
[Required]
|
||||
public Guid OrganizationUserId { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(256)]
|
||||
[StrictEmailAddress]
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.Models.Table
|
||||
@ -15,6 +16,7 @@ namespace Bit.Core.Models.Table
|
||||
public Guid? SponsoredOrganizationId { get; set; }
|
||||
[MaxLength(256)]
|
||||
public string OfferedToEmail { get; set; }
|
||||
public PlanSponsorshipType? PlanSponsorshipType { get; set; }
|
||||
[Required]
|
||||
public bool CloudSponsor { get; set; }
|
||||
public DateTime? LastSyncDate { get; set; }
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
@ -6,7 +7,7 @@ namespace Bit.Core.Services
|
||||
public interface IOrganizationSponsorshipService
|
||||
{
|
||||
Task<bool> ValidateRedemptionTokenAsync(string encryptedToken);
|
||||
Task OfferSponsorshipAsync(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, string sponsoredEmail);
|
||||
Task OfferSponsorshipAsync(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, PlanSponsorshipType sponsorshipType, string sponsoredEmail);
|
||||
Task SetUpSponsorshipAsync(OrganizationSponsorship sponsorship, Organization sponsoredOrganization);
|
||||
Task RemoveSponsorshipAsync(OrganizationSponsorship sponsorship);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
@ -38,25 +39,31 @@ namespace Bit.Core.Services
|
||||
|
||||
if (dataParts[0].Equals(FamiliesForEnterpriseTokenName))
|
||||
{
|
||||
if (!Guid.TryParse(dataParts[1], out Guid sponsorshipId))
|
||||
if (!Guid.TryParse(dataParts[1], out Guid sponsorshipId) ||
|
||||
!Enum.TryParse<PlanSponsorshipType>(dataParts[2], true, out var sponsorshipType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var sponsorship = await _organizationSponsorshipRepository.GetByIdAsync(sponsorshipId);
|
||||
return sponsorship != null;
|
||||
if (sponsorship == null || sponsorship.PlanSponsorshipType != sponsorshipType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string RedemptionToken(Guid sponsorshipId) =>
|
||||
private string RedemptionToken(Guid sponsorshipId, PlanSponsorshipType sponsorshipType) =>
|
||||
string.Concat(
|
||||
TokenClearTextPrefix,
|
||||
_dataProtector.Protect($"{FamiliesForEnterpriseTokenName} {sponsorshipId}")
|
||||
_dataProtector.Protect($"{FamiliesForEnterpriseTokenName} {sponsorshipId} {sponsorshipType}")
|
||||
);
|
||||
|
||||
public async Task OfferSponsorshipAsync(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, string sponsoredEmail)
|
||||
public async Task OfferSponsorshipAsync(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, PlanSponsorshipType sponsorshipType, string sponsoredEmail)
|
||||
{
|
||||
var sponsorship = new OrganizationSponsorship
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ CREATE PROCEDURE [dbo].[OrganizationSponsorship_Create]
|
||||
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
|
||||
@SponsoredOrganizationId UNIQUEIDENTIFIER,
|
||||
@OfferedToEmail NVARCHAR(256),
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@CloudSponsor BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@TimesRenewedWithoutValidation TINYINT,
|
||||
@ -21,6 +22,7 @@ BEGIN
|
||||
[SponsoringOrganizationUserID],
|
||||
[SponsoredOrganizationId],
|
||||
[OfferedToEmail],
|
||||
[PlanSponsorshipType],
|
||||
[CloudSponsor],
|
||||
[LastSyncDate],
|
||||
[TimesRenewedWithoutValidation],
|
||||
@ -34,6 +36,7 @@ BEGIN
|
||||
@SponsoringOrganizationUserID,
|
||||
@SponsoredOrganizationId,
|
||||
@OfferedToEmail,
|
||||
@PlanSponsorshipType,
|
||||
@CloudSponsor,
|
||||
@LastSyncDate,
|
||||
@TimesRenewedWithoutValidation,
|
||||
|
@ -5,6 +5,7 @@ CREATE PROCEDURE [dbo].[OrganizationSponsorship_Update]
|
||||
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
|
||||
@SponsoredOrganizationId UNIQUEIDENTIFIER,
|
||||
@OfferedToEmail NVARCHAR(256),
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@CloudSponsor BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@TimesRenewedWithoutValidation TINYINT,
|
||||
@ -21,6 +22,7 @@ BEGIN
|
||||
[SponsoringOrganizationUserID] = @SponsoringOrganizationUserID,
|
||||
[SponsoredOrganizationId] = @SponsoredOrganizationId,
|
||||
[OfferedToEmail] = @OfferedToEmail,
|
||||
[PlanSponsorshipType] = @PlanSponsorshipType,
|
||||
[CloudSponsor] = @CloudSponsor,
|
||||
[LastSyncDate] = @LastSyncDate,
|
||||
[TimesRenewedWithoutValidation] = @TimesRenewedWithoutValidation,
|
||||
|
@ -2,9 +2,10 @@ CREATE TABLE [dbo].[OrganizationSponsorship] (
|
||||
[Id] UNIQUEIDENTIFIER NOT NULL,
|
||||
[InstallationId] UNIQUEIDENTIFIER NULL,
|
||||
[SponsoringOrganizationId] UNIQUEIDENTIFIER NOT NULL,
|
||||
[SponsorginOrganizationUserID] UNIQUEIDENTIFIER NOT NULL,
|
||||
[SponsoringOrganizationUserID] UNIQUEIDENTIFIER NOT NULL,
|
||||
[SponsoredOrganizationId] UNIQUEIDENTIFIER NULL,
|
||||
[OfferedToEmail] NVARCHAR (256) NULL,
|
||||
[PlanSponsorshipType] TINYINT NULL,
|
||||
[CloudSponsor] BIT NULL,
|
||||
[LastSyncDate] DATETIME2 (7) NULL,
|
||||
[TimesRenewedWithoutValidation] TINYINT DEFAULT 0,
|
||||
|
@ -44,7 +44,7 @@ namespace Bit.Api.Test.Controllers
|
||||
Assert.Contains("Specified Organization cannot sponsor other organizations.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipService>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.OfferSponsorshipAsync(default, default, default);
|
||||
.OfferSponsorshipAsync(default, default, default, default);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> NonConfirmedOrganizationUsersStatuses =>
|
||||
@ -73,7 +73,7 @@ namespace Bit.Api.Test.Controllers
|
||||
Assert.Contains("Only confirm users can sponsor other organizations.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipService>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.OfferSponsorshipAsync(default, default, default);
|
||||
.OfferSponsorshipAsync(default, default, default, default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -96,7 +96,7 @@ namespace Bit.Api.Test.Controllers
|
||||
Assert.Contains("Can only create organization sponsorships for yourself.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipService>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.OfferSponsorshipAsync(default, default, default);
|
||||
.OfferSponsorshipAsync(default, default, default, default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -121,7 +121,7 @@ namespace Bit.Api.Test.Controllers
|
||||
Assert.Contains("Can only sponsor one organization per Organization User.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipService>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.OfferSponsorshipAsync(default, default, default);
|
||||
.OfferSponsorshipAsync(default, default, default, default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
@ -35,7 +36,8 @@ namespace Bit.Core.Test.Services
|
||||
public async Task OfferSponsorship_CreatesSponsorship(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser,
|
||||
string sponsoredEmail, SutProvider<OrganizationSponsorshipService> sutProvider)
|
||||
{
|
||||
await sutProvider.Sut.OfferSponsorshipAsync(sponsoringOrg, sponsoringOrgUser, sponsoredEmail);
|
||||
await sutProvider.Sut.OfferSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail);
|
||||
|
||||
var expectedSponsorship = new OrganizationSponsorship
|
||||
{
|
||||
@ -64,7 +66,9 @@ namespace Bit.Core.Test.Services
|
||||
return expectedException;
|
||||
});
|
||||
|
||||
var actualException = await Assert.ThrowsAsync<Exception>(() => sutProvider.Sut.OfferSponsorshipAsync(sponsoringOrg, sponsoringOrgUser, sponsoredEmail));
|
||||
var actualException = await Assert.ThrowsAsync<Exception>(() =>
|
||||
sutProvider.Sut.OfferSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail));
|
||||
Assert.Same(expectedException, actualException);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().Received(1)
|
||||
|
@ -8,6 +8,7 @@ CREATE TABLE [dbo].[OrganizationSponsorship] (
|
||||
[SponsoringOrganizationUserID] UNIQUEIDENTIFIER NOT NULL,
|
||||
[SponsoredOrganizationId] UNIQUEIDENTIFIER NULL,
|
||||
[OfferedToEmail] NVARCHAR (256) NULL,
|
||||
[PlanSponsorshipType] TINYINT NULL,
|
||||
[CloudSponsor] BIT NULL,
|
||||
[LastSyncDate] DATETIME2 (7) NULL,
|
||||
[TimesRenewedWithoutValidation] TINYINT DEFAULT 0,
|
||||
@ -114,6 +115,7 @@ CREATE PROCEDURE [dbo].[OrganizationSponsorship_Create]
|
||||
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
|
||||
@SponsoredOrganizationId UNIQUEIDENTIFIER,
|
||||
@OfferedToEmail NVARCHAR(256),
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@CloudSponsor BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@TimesRenewedWithoutValidation TINYINT,
|
||||
@ -130,6 +132,7 @@ BEGIN
|
||||
[SponsoringOrganizationUserID],
|
||||
[SponsoredOrganizationId],
|
||||
[OfferedToEmail],
|
||||
[PlanSponsorshipType],
|
||||
[CloudSponsor],
|
||||
[LastSyncDate],
|
||||
[TimesRenewedWithoutValidation],
|
||||
@ -143,6 +146,7 @@ BEGIN
|
||||
@SponsoringOrganizationUserID,
|
||||
@SponsoredOrganizationId,
|
||||
@OfferedToEmail,
|
||||
@PlanSponsorshipType,
|
||||
@CloudSponsor,
|
||||
@LastSyncDate,
|
||||
@TimesRenewedWithoutValidation,
|
||||
@ -165,6 +169,7 @@ CREATE PROCEDURE [dbo].[OrganizationSponsorship_Update]
|
||||
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
|
||||
@SponsoredOrganizationId UNIQUEIDENTIFIER,
|
||||
@OfferedToEmail NVARCHAR(256),
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@CloudSponsor BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@TimesRenewedWithoutValidation TINYINT,
|
||||
@ -181,6 +186,7 @@ BEGIN
|
||||
[SponsoringOrganizationUserID] = @SponsoringOrganizationUserID,
|
||||
[SponsoredOrganizationId] = @SponsoredOrganizationId,
|
||||
[OfferedToEmail] = @OfferedToEmail,
|
||||
[PlanSponsorshipType] = @PlanSponsorshipType,
|
||||
[CloudSponsor] = @CloudSponsor,
|
||||
[LastSyncDate] = @LastSyncDate,
|
||||
[TimesRenewedWithoutValidation] = @TimesRenewedWithoutValidation,
|
||||
|
@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace Bit.MySqlMigrations.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20211102213543_OrganizationSponsorship")]
|
||||
[Migration("20211104164838_OrganizationSponsorship")]
|
||||
partial class OrganizationSponsorship
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -605,6 +605,9 @@ namespace Bit.MySqlMigrations.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<byte?>("PlanSponsorshipType")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<Guid?>("SponsoredOrganizationId")
|
||||
.HasColumnType("char(36)");
|
||||
|
@ -25,6 +25,7 @@ namespace Bit.MySqlMigrations.Migrations
|
||||
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"),
|
||||
PlanSponsorshipType = table.Column<byte>(type: "tinyint unsigned", nullable: true),
|
||||
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),
|
@ -603,6 +603,9 @@ namespace Bit.MySqlMigrations.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<byte?>("PlanSponsorshipType")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<Guid?>("SponsoredOrganizationId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
|
@ -9,6 +9,7 @@ CREATE TABLE `OrganizationSponsorship` (
|
||||
`SponsoringOrganizationUserId` char(36) COLLATE ascii_general_ci NOT NULL,
|
||||
`SponsoredOrganizationId` char(36) COLLATE ascii_general_ci NULL,
|
||||
`OfferedToEmail` varchar(256) CHARACTER SET utf8mb4 NULL,
|
||||
`PlanSponsorshipType` tinyint unsigned NULL,
|
||||
`CloudSponsor` tinyint(1) NOT NULL,
|
||||
`LastSyncDate` datetime(6) NULL,
|
||||
`TimesRenewedWithoutValidation` tinyint unsigned NOT NULL,
|
||||
@ -26,6 +27,6 @@ CREATE INDEX `IX_OrganizationSponsorship_SponsoredOrganizationId` ON `Organizati
|
||||
CREATE INDEX `IX_OrganizationSponsorship_SponsoringOrganizationId` ON `OrganizationSponsorship` (`SponsoringOrganizationId`);
|
||||
|
||||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
|
||||
VALUES ('20211102213543_OrganizationSponsorship', '5.0.9');
|
||||
VALUES ('20211104164838_OrganizationSponsorship', '5.0.9');
|
||||
|
||||
COMMIT;
|
||||
|
@ -10,7 +10,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace Bit.PostgresMigrations.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20211102205745_OrganizationSponsorship")]
|
||||
[Migration("20211104164532_OrganizationSponsorship")]
|
||||
partial class OrganizationSponsorship
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -609,6 +609,9 @@ namespace Bit.PostgresMigrations.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<byte?>("PlanSponsorshipType")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("SponsoredOrganizationId")
|
||||
.HasColumnType("uuid");
|
||||
|
@ -24,6 +24,7 @@ namespace Bit.PostgresMigrations.Migrations
|
||||
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),
|
||||
PlanSponsorshipType = table.Column<byte>(type: "smallint", 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),
|
@ -607,6 +607,9 @@ namespace Bit.PostgresMigrations.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<byte?>("PlanSponsorshipType")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("SponsoredOrganizationId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
|
@ -9,6 +9,7 @@ CREATE TABLE "OrganizationSponsorship" (
|
||||
"SponsoringOrganizationUserId" uuid NOT NULL,
|
||||
"SponsoredOrganizationId" uuid NULL,
|
||||
"OfferedToEmail" character varying(256) NULL,
|
||||
"PlanSponsorshipType" smallint NULL,
|
||||
"CloudSponsor" boolean NOT NULL,
|
||||
"LastSyncDate" timestamp without time zone NULL,
|
||||
"TimesRenewedWithoutValidation" smallint NOT NULL,
|
||||
@ -26,6 +27,6 @@ CREATE INDEX "IX_OrganizationSponsorship_SponsoredOrganizationId" ON "Organizati
|
||||
CREATE INDEX "IX_OrganizationSponsorship_SponsoringOrganizationId" ON "OrganizationSponsorship" ("SponsoringOrganizationId");
|
||||
|
||||
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||
VALUES ('20211102205745_OrganizationSponsorship', '5.0.9');
|
||||
VALUES ('20211104164532_OrganizationSponsorship', '5.0.9');
|
||||
|
||||
COMMIT;
|
||||
|
Loading…
Reference in New Issue
Block a user