mirror of
https://github.com/bitwarden/server.git
synced 2025-04-26 07:12:20 -05:00
[PM-17830] Backend changes for admin initiated sponsorships (#5531)
* WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * Add `Notes` column to `OrganizationSponsorships` table * Add feature flag to `CreateAdminInitiatedSponsorshipHandler` * Unit tests for `CreateSponsorshipHandler` * More tests for `CreateSponsorshipHandler` * Forgot to add `Notes` column to `OrganizationSponsorships` table in the migration script * `CreateAdminInitiatedSponsorshipHandler` unit tests * Fix `CreateSponsorshipCommandTests` * Encrypt the notes field * Wrong business logic checking for invalid permissions. * Wrong business logic checking for invalid permissions. * Remove design patterns * duplicate definition in Constants.cs * Allow rollback * Fix stored procedures & type * Fix stored procedures & type * Properly encapsulating this PR behind its feature flag * Removed comments * Updated ValidateSponsorshipCommand to validate admin initiated requirements --------- Co-authored-by: Conner Turnbull <133619638+cturnbull-bitwarden@users.noreply.github.com> Co-authored-by: Conner Turnbull <cturnbull@bitwarden.com>
This commit is contained in:
parent
f678e3db79
commit
c182b37347
@ -86,6 +86,7 @@ public class OrganizationEditModel : OrganizationViewModel
|
||||
UseApi = org.UseApi;
|
||||
UseSecretsManager = org.UseSecretsManager;
|
||||
UseRiskInsights = org.UseRiskInsights;
|
||||
UseAdminSponsoredFamilies = org.UseAdminSponsoredFamilies;
|
||||
UseResetPassword = org.UseResetPassword;
|
||||
SelfHost = org.SelfHost;
|
||||
UsersGetPremium = org.UsersGetPremium;
|
||||
@ -154,6 +155,8 @@ public class OrganizationEditModel : OrganizationViewModel
|
||||
public new bool UseSecretsManager { get; set; }
|
||||
[Display(Name = "Risk Insights")]
|
||||
public new bool UseRiskInsights { get; set; }
|
||||
[Display(Name = "Admin Sponsored Families")]
|
||||
public bool UseAdminSponsoredFamilies { get; set; }
|
||||
[Display(Name = "Self Host")]
|
||||
public bool SelfHost { get; set; }
|
||||
[Display(Name = "Users Get Premium")]
|
||||
@ -295,6 +298,7 @@ public class OrganizationEditModel : OrganizationViewModel
|
||||
existingOrganization.UseApi = UseApi;
|
||||
existingOrganization.UseSecretsManager = UseSecretsManager;
|
||||
existingOrganization.UseRiskInsights = UseRiskInsights;
|
||||
existingOrganization.UseAdminSponsoredFamilies = UseAdminSponsoredFamilies;
|
||||
existingOrganization.UseResetPassword = UseResetPassword;
|
||||
existingOrganization.SelfHost = SelfHost;
|
||||
existingOrganization.UsersGetPremium = UsersGetPremium;
|
||||
|
@ -64,6 +64,7 @@ public class OrganizationResponseModel : ResponseModel
|
||||
LimitItemDeletion = organization.LimitItemDeletion;
|
||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||
UseRiskInsights = organization.UseRiskInsights;
|
||||
UseAdminSponsoredFamilies = organization.UseAdminSponsoredFamilies;
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
@ -110,6 +111,7 @@ public class OrganizationResponseModel : ResponseModel
|
||||
public bool LimitItemDeletion { get; set; }
|
||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||
public bool UseRiskInsights { get; set; }
|
||||
public bool UseAdminSponsoredFamilies { get; set; }
|
||||
}
|
||||
|
||||
public class OrganizationSubscriptionResponseModel : OrganizationResponseModel
|
||||
|
@ -72,6 +72,7 @@ public class ProfileOrganizationResponseModel : ResponseModel
|
||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||
UserIsClaimedByOrganization = organizationIdsClaimingUser.Contains(organization.OrganizationId);
|
||||
UseRiskInsights = organization.UseRiskInsights;
|
||||
UseAdminSponsoredFamilies = organization.UseAdminSponsoredFamilies;
|
||||
|
||||
if (organization.SsoConfig != null)
|
||||
{
|
||||
@ -155,4 +156,5 @@ public class ProfileOrganizationResponseModel : ResponseModel
|
||||
/// </returns>
|
||||
public bool UserIsClaimedByOrganization { get; set; }
|
||||
public bool UseRiskInsights { get; set; }
|
||||
public bool UseAdminSponsoredFamilies { get; set; }
|
||||
}
|
||||
|
@ -50,5 +50,6 @@ public class ProfileProviderOrganizationResponseModel : ProfileOrganizationRespo
|
||||
LimitItemDeletion = organization.LimitItemDeletion;
|
||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||
UseRiskInsights = organization.UseRiskInsights;
|
||||
UseAdminSponsoredFamilies = organization.UseAdminSponsoredFamilies;
|
||||
}
|
||||
}
|
||||
|
@ -84,10 +84,27 @@ public class OrganizationSponsorshipsController : Controller
|
||||
throw new BadRequestException("Free Bitwarden Families sponsorship has been disabled by your organization administrator.");
|
||||
}
|
||||
|
||||
if (!_featureService.IsEnabled(Bit.Core.FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
||||
{
|
||||
if (model.SponsoringUserId.HasValue)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(model.Notes))
|
||||
{
|
||||
model.Notes = null;
|
||||
}
|
||||
}
|
||||
|
||||
var targetUser = model.SponsoringUserId ?? _currentContext.UserId!.Value;
|
||||
var sponsorship = await _createSponsorshipCommand.CreateSponsorshipAsync(
|
||||
sponsoringOrg,
|
||||
await _organizationUserRepository.GetByOrganizationAsync(sponsoringOrgId, _currentContext.UserId ?? default),
|
||||
model.PlanSponsorshipType, model.SponsoredEmail, model.FriendlyName);
|
||||
await _organizationUserRepository.GetByOrganizationAsync(sponsoringOrgId, targetUser),
|
||||
model.PlanSponsorshipType,
|
||||
model.SponsoredEmail,
|
||||
model.FriendlyName,
|
||||
model.Notes);
|
||||
await _sendSponsorshipOfferCommand.SendSponsorshipOfferAsync(sponsorship, sponsoringOrg.Name);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ using Bit.Core.Context;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -20,6 +21,7 @@ public class SelfHostedOrganizationSponsorshipsController : Controller
|
||||
private readonly ICreateSponsorshipCommand _offerSponsorshipCommand;
|
||||
private readonly IRevokeSponsorshipCommand _revokeSponsorshipCommand;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IFeatureService _featureService;
|
||||
|
||||
public SelfHostedOrganizationSponsorshipsController(
|
||||
ICreateSponsorshipCommand offerSponsorshipCommand,
|
||||
@ -27,7 +29,8 @@ public class SelfHostedOrganizationSponsorshipsController : Controller
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationSponsorshipRepository organizationSponsorshipRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
ICurrentContext currentContext
|
||||
ICurrentContext currentContext,
|
||||
IFeatureService featureService
|
||||
)
|
||||
{
|
||||
_offerSponsorshipCommand = offerSponsorshipCommand;
|
||||
@ -36,15 +39,29 @@ public class SelfHostedOrganizationSponsorshipsController : Controller
|
||||
_organizationSponsorshipRepository = organizationSponsorshipRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_currentContext = currentContext;
|
||||
_featureService = featureService;
|
||||
}
|
||||
|
||||
[HttpPost("{sponsoringOrgId}/families-for-enterprise")]
|
||||
public async Task CreateSponsorship(Guid sponsoringOrgId, [FromBody] OrganizationSponsorshipCreateRequestModel model)
|
||||
{
|
||||
if (!_featureService.IsEnabled(Bit.Core.FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
||||
{
|
||||
if (model.SponsoringUserId.HasValue)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(model.Notes))
|
||||
{
|
||||
model.Notes = null;
|
||||
}
|
||||
}
|
||||
|
||||
await _offerSponsorshipCommand.CreateSponsorshipAsync(
|
||||
await _organizationRepository.GetByIdAsync(sponsoringOrgId),
|
||||
await _organizationUserRepository.GetByOrganizationAsync(sponsoringOrgId, _currentContext.UserId ?? default),
|
||||
model.PlanSponsorshipType, model.SponsoredEmail, model.FriendlyName);
|
||||
await _organizationUserRepository.GetByOrganizationAsync(sponsoringOrgId, model.SponsoringUserId ?? _currentContext.UserId ?? default),
|
||||
model.PlanSponsorshipType, model.SponsoredEmail, model.FriendlyName, model.Notes);
|
||||
}
|
||||
|
||||
[HttpDelete("{sponsoringOrgId}")]
|
||||
|
@ -16,4 +16,14 @@ public class OrganizationSponsorshipCreateRequestModel
|
||||
|
||||
[StringLength(256)]
|
||||
public string FriendlyName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// (optional) The user to target for the sponsorship.
|
||||
/// </summary>
|
||||
/// <remarks>Left empty when creating a sponsorship for the authenticated user.</remarks>
|
||||
public Guid? SponsoringUserId { get; set; }
|
||||
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(512)]
|
||||
public string Notes { get; set; }
|
||||
}
|
||||
|
@ -114,6 +114,11 @@ public class Organization : ITableObject<Guid>, IStorableSubscriber, IRevisable,
|
||||
/// </summary>
|
||||
public bool UseRiskInsights { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, admins can initiate organization-issued sponsorships.
|
||||
/// </summary>
|
||||
public bool UseAdminSponsoredFamilies { get; set; }
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
if (Id == default(Guid))
|
||||
|
@ -26,6 +26,7 @@ public class OrganizationAbility
|
||||
LimitItemDeletion = organization.LimitItemDeletion;
|
||||
AllowAdminAccessToAllCollectionItems = organization.AllowAdminAccessToAllCollectionItems;
|
||||
UseRiskInsights = organization.UseRiskInsights;
|
||||
UseAdminSponsoredFamilies = organization.UseAdminSponsoredFamilies;
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
@ -45,4 +46,5 @@ public class OrganizationAbility
|
||||
public bool LimitItemDeletion { get; set; }
|
||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||
public bool UseRiskInsights { get; set; }
|
||||
public bool UseAdminSponsoredFamilies { get; set; }
|
||||
}
|
||||
|
@ -59,4 +59,5 @@ public class OrganizationUserOrganizationDetails
|
||||
public bool LimitItemDeletion { get; set; }
|
||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||
public bool UseRiskInsights { get; set; }
|
||||
public bool UseAdminSponsoredFamilies { get; set; }
|
||||
}
|
||||
|
@ -45,5 +45,6 @@ public class ProviderUserOrganizationDetails
|
||||
public bool LimitItemDeletion { get; set; }
|
||||
public bool AllowAdminAccessToAllCollectionItems { get; set; }
|
||||
public bool UseRiskInsights { get; set; }
|
||||
public bool UseAdminSponsoredFamilies { get; set; }
|
||||
public ProviderType ProviderType { get; set; }
|
||||
}
|
||||
|
@ -141,6 +141,7 @@ public static class FeatureFlagKeys
|
||||
/* Billing Team */
|
||||
public const string AC2101UpdateTrialInitiationEmail = "AC-2101-update-trial-initiation-email";
|
||||
public const string TrialPayment = "PM-8163-trial-payment";
|
||||
public const string PM17772_AdminInitiatedSponsorships = "pm-17772-admin-initiated-sponsorships";
|
||||
public const string UsePricingService = "use-pricing-service";
|
||||
public const string P15179_AddExistingOrgsFromProviderPortal = "pm-15179-add-existing-orgs-from-provider-portal";
|
||||
public const string PM12276Breadcrumbing = "pm-12276-breadcrumbing-for-business-features";
|
||||
|
@ -20,6 +20,8 @@ public class OrganizationSponsorship : ITableObject<Guid>
|
||||
public DateTime? LastSyncDate { get; set; }
|
||||
public DateTime? ValidUntil { get; set; }
|
||||
public bool ToDelete { get; set; }
|
||||
public bool IsAdminInitiated { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
|
@ -16,6 +16,8 @@ public class OrganizationSponsorshipData
|
||||
LastSyncDate = sponsorship.LastSyncDate;
|
||||
ValidUntil = sponsorship.ValidUntil;
|
||||
ToDelete = sponsorship.ToDelete;
|
||||
IsAdminInitiated = sponsorship.IsAdminInitiated;
|
||||
Notes = sponsorship.Notes;
|
||||
}
|
||||
public Guid SponsoringOrganizationUserId { get; set; }
|
||||
public Guid? SponsoredOrganizationId { get; set; }
|
||||
@ -25,6 +27,8 @@ public class OrganizationSponsorshipData
|
||||
public DateTime? LastSyncDate { get; set; }
|
||||
public DateTime? ValidUntil { get; set; }
|
||||
public bool ToDelete { get; set; }
|
||||
public bool IsAdminInitiated { get; set; }
|
||||
public string Notes { get; set; }
|
||||
|
||||
public bool CloudSponsorshipRemoved { get; set; }
|
||||
}
|
||||
|
@ -112,6 +112,13 @@ public class ValidateSponsorshipCommand : CancelSponsorshipCommand, IValidateSpo
|
||||
return false;
|
||||
}
|
||||
|
||||
if (existingSponsorship.IsAdminInitiated && !sponsoringOrganization.UseAdminSponsoredFamilies)
|
||||
{
|
||||
_logger.LogWarning("Admin initiated sponsorship for sponsored Organization {SponsoredOrganizationId} is not allowed because sponsoring organization does not have UseAdminSponsoredFamilies enabled", sponsoredOrganizationId);
|
||||
await CancelSponsorshipAsync(sponsoredOrganization, existingSponsorship);
|
||||
return false;
|
||||
}
|
||||
|
||||
var sponsoringOrgProductTier = sponsoringOrganization.PlanType.GetProductTier();
|
||||
|
||||
if (sponsoredPlan.SponsoringProductTierType != sponsoringOrgProductTier)
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Billing.Extensions;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
@ -10,29 +11,24 @@ using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise;
|
||||
|
||||
public class CreateSponsorshipCommand : ICreateSponsorshipCommand
|
||||
public class CreateSponsorshipCommand(
|
||||
ICurrentContext currentContext,
|
||||
IOrganizationSponsorshipRepository organizationSponsorshipRepository,
|
||||
IUserService userService) : ICreateSponsorshipCommand
|
||||
{
|
||||
private readonly IOrganizationSponsorshipRepository _organizationSponsorshipRepository;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public CreateSponsorshipCommand(IOrganizationSponsorshipRepository organizationSponsorshipRepository,
|
||||
IUserService userService)
|
||||
public async Task<OrganizationSponsorship> CreateSponsorshipAsync(Organization sponsoringOrganization,
|
||||
OrganizationUser sponsoringMember, PlanSponsorshipType sponsorshipType, string sponsoredEmail,
|
||||
string friendlyName, string notes)
|
||||
{
|
||||
_organizationSponsorshipRepository = organizationSponsorshipRepository;
|
||||
_userService = userService;
|
||||
}
|
||||
var sponsoringUser = await userService.GetUserByIdAsync(sponsoringMember.UserId!.Value);
|
||||
|
||||
public async Task<OrganizationSponsorship> CreateSponsorshipAsync(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser,
|
||||
PlanSponsorshipType sponsorshipType, string sponsoredEmail, string friendlyName)
|
||||
{
|
||||
var sponsoringUser = await _userService.GetUserByIdAsync(sponsoringOrgUser.UserId.Value);
|
||||
if (sponsoringUser == null || string.Equals(sponsoringUser.Email, sponsoredEmail, System.StringComparison.InvariantCultureIgnoreCase))
|
||||
if (sponsoringUser == null || string.Equals(sponsoringUser.Email, sponsoredEmail, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
throw new BadRequestException("Cannot offer a Families Organization Sponsorship to yourself. Choose a different email.");
|
||||
}
|
||||
|
||||
var requiredSponsoringProductType = StaticStore.GetSponsoredPlan(sponsorshipType)?.SponsoringProductTierType;
|
||||
var sponsoringOrgProductTier = sponsoringOrg.PlanType.GetProductTier();
|
||||
var sponsoringOrgProductTier = sponsoringOrganization.PlanType.GetProductTier();
|
||||
|
||||
if (requiredSponsoringProductType == null ||
|
||||
sponsoringOrgProductTier != requiredSponsoringProductType.Value)
|
||||
@ -40,26 +36,24 @@ public class CreateSponsorshipCommand : ICreateSponsorshipCommand
|
||||
throw new BadRequestException("Specified Organization cannot sponsor other organizations.");
|
||||
}
|
||||
|
||||
if (sponsoringOrgUser == null || sponsoringOrgUser.Status != OrganizationUserStatusType.Confirmed)
|
||||
if (sponsoringMember.Status != OrganizationUserStatusType.Confirmed)
|
||||
{
|
||||
throw new BadRequestException("Only confirmed users can sponsor other organizations.");
|
||||
}
|
||||
|
||||
var existingOrgSponsorship = await _organizationSponsorshipRepository
|
||||
.GetBySponsoringOrganizationUserIdAsync(sponsoringOrgUser.Id);
|
||||
var existingOrgSponsorship = await organizationSponsorshipRepository
|
||||
.GetBySponsoringOrganizationUserIdAsync(sponsoringMember.Id);
|
||||
if (existingOrgSponsorship?.SponsoredOrganizationId != null)
|
||||
{
|
||||
throw new BadRequestException("Can only sponsor one organization per Organization User.");
|
||||
}
|
||||
|
||||
var sponsorship = new OrganizationSponsorship
|
||||
{
|
||||
SponsoringOrganizationId = sponsoringOrg.Id,
|
||||
SponsoringOrganizationUserId = sponsoringOrgUser.Id,
|
||||
FriendlyName = friendlyName,
|
||||
OfferedToEmail = sponsoredEmail,
|
||||
PlanSponsorshipType = sponsorshipType,
|
||||
};
|
||||
var sponsorship = new OrganizationSponsorship();
|
||||
sponsorship.SponsoringOrganizationId = sponsoringOrganization.Id;
|
||||
sponsorship.SponsoringOrganizationUserId = sponsoringMember.Id;
|
||||
sponsorship.FriendlyName = friendlyName;
|
||||
sponsorship.OfferedToEmail = sponsoredEmail;
|
||||
sponsorship.PlanSponsorshipType = sponsorshipType;
|
||||
|
||||
if (existingOrgSponsorship != null)
|
||||
{
|
||||
@ -67,16 +61,42 @@ public class CreateSponsorshipCommand : ICreateSponsorshipCommand
|
||||
sponsorship.Id = existingOrgSponsorship.Id;
|
||||
}
|
||||
|
||||
var isAdminInitiated = false;
|
||||
if (currentContext.UserId != sponsoringMember.UserId)
|
||||
{
|
||||
var organization = currentContext.Organizations.First(x => x.Id == sponsoringOrganization.Id);
|
||||
OrganizationUserType[] allowedUserTypes =
|
||||
[
|
||||
OrganizationUserType.Admin,
|
||||
OrganizationUserType.Owner
|
||||
];
|
||||
|
||||
if (!organization.Permissions.ManageUsers && allowedUserTypes.All(x => x != organization.Type))
|
||||
{
|
||||
throw new UnauthorizedAccessException("You do not have permissions to send sponsorships on behalf of the organization.");
|
||||
}
|
||||
|
||||
if (!sponsoringOrganization.UseAdminSponsoredFamilies)
|
||||
{
|
||||
throw new BadRequestException("Sponsoring organization cannot sponsor other Family organizations.");
|
||||
}
|
||||
|
||||
isAdminInitiated = true;
|
||||
}
|
||||
|
||||
sponsorship.IsAdminInitiated = isAdminInitiated;
|
||||
sponsorship.Notes = notes;
|
||||
|
||||
try
|
||||
{
|
||||
await _organizationSponsorshipRepository.UpsertAsync(sponsorship);
|
||||
await organizationSponsorshipRepository.UpsertAsync(sponsorship);
|
||||
return sponsorship;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (sponsorship.Id != default)
|
||||
if (sponsorship.Id != Guid.Empty)
|
||||
{
|
||||
await _organizationSponsorshipRepository.DeleteAsync(sponsorship);
|
||||
await organizationSponsorshipRepository.DeleteAsync(sponsorship);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ namespace Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnte
|
||||
public interface ICreateSponsorshipCommand
|
||||
{
|
||||
Task<OrganizationSponsorship> CreateSponsorshipAsync(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser,
|
||||
PlanSponsorshipType sponsorshipType, string sponsoredEmail, string friendlyName);
|
||||
PlanSponsorshipType sponsorshipType, string sponsoredEmail, string friendlyName, string notes);
|
||||
}
|
||||
|
@ -106,7 +106,8 @@ public class OrganizationRepository : Repository<Core.AdminConsole.Entities.Orga
|
||||
LimitCollectionDeletion = e.LimitCollectionDeletion,
|
||||
LimitItemDeletion = e.LimitItemDeletion,
|
||||
AllowAdminAccessToAllCollectionItems = e.AllowAdminAccessToAllCollectionItems,
|
||||
UseRiskInsights = e.UseRiskInsights
|
||||
UseRiskInsights = e.UseRiskInsights,
|
||||
UseAdminSponsoredFamilies = e.UseAdminSponsoredFamilies
|
||||
}).ToListAsync();
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ public class OrganizationUserOrganizationDetailsViewQuery : IQuery<OrganizationU
|
||||
LimitItemDeletion = o.LimitItemDeletion,
|
||||
AllowAdminAccessToAllCollectionItems = o.AllowAdminAccessToAllCollectionItems,
|
||||
UseRiskInsights = o.UseRiskInsights,
|
||||
UseAdminSponsoredFamilies = o.UseAdminSponsoredFamilies,
|
||||
};
|
||||
return query;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ public class ProviderUserOrganizationDetailsViewQuery : IQuery<ProviderUserOrgan
|
||||
LimitItemDeletion = x.o.LimitItemDeletion,
|
||||
AllowAdminAccessToAllCollectionItems = x.o.AllowAdminAccessToAllCollectionItems,
|
||||
UseRiskInsights = x.o.UseRiskInsights,
|
||||
UseAdminSponsoredFamilies = x.o.UseAdminSponsoredFamilies,
|
||||
ProviderType = x.p.Type
|
||||
});
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ CREATE PROCEDURE [dbo].[OrganizationSponsorship_Create]
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@ToDelete BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@ValidUntil DATETIME2 (7)
|
||||
@ValidUntil DATETIME2 (7),
|
||||
@IsAdminInitiated BIT = 0,
|
||||
@Notes NVARCHAR(512) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -24,7 +26,9 @@ BEGIN
|
||||
[PlanSponsorshipType],
|
||||
[ToDelete],
|
||||
[LastSyncDate],
|
||||
[ValidUntil]
|
||||
[ValidUntil],
|
||||
[IsAdminInitiated],
|
||||
[Notes]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@ -37,7 +41,9 @@ BEGIN
|
||||
@PlanSponsorshipType,
|
||||
@ToDelete,
|
||||
@LastSyncDate,
|
||||
@ValidUntil
|
||||
@ValidUntil,
|
||||
@IsAdminInitiated,
|
||||
@Notes
|
||||
)
|
||||
END
|
||||
GO
|
||||
|
@ -15,7 +15,9 @@ BEGIN
|
||||
[PlanSponsorshipType],
|
||||
[ToDelete],
|
||||
[LastSyncDate],
|
||||
[ValidUntil]
|
||||
[ValidUntil],
|
||||
[IsAdminInitiated],
|
||||
[Notes]
|
||||
)
|
||||
SELECT
|
||||
OS.[Id],
|
||||
@ -27,7 +29,9 @@ BEGIN
|
||||
OS.[PlanSponsorshipType],
|
||||
OS.[ToDelete],
|
||||
OS.[LastSyncDate],
|
||||
OS.[ValidUntil]
|
||||
OS.[ValidUntil],
|
||||
OS.[IsAdminInitiated],
|
||||
OS.[Notes]
|
||||
FROM
|
||||
@OrganizationSponsorshipsInput OS
|
||||
END
|
||||
END
|
||||
|
@ -8,7 +8,9 @@ CREATE PROCEDURE [dbo].[OrganizationSponsorship_Update]
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@ToDelete BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@ValidUntil DATETIME2 (7)
|
||||
@ValidUntil DATETIME2 (7),
|
||||
@IsAdminInitiated BIT = 0,
|
||||
@Notes NVARCHAR(512) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -24,7 +26,9 @@ BEGIN
|
||||
[PlanSponsorshipType] = @PlanSponsorshipType,
|
||||
[ToDelete] = @ToDelete,
|
||||
[LastSyncDate] = @LastSyncDate,
|
||||
[ValidUntil] = @ValidUntil
|
||||
[ValidUntil] = @ValidUntil,
|
||||
[IsAdminInitiated] = @IsAdminInitiated,
|
||||
[Notes] = @Notes
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
END
|
||||
|
@ -6,7 +6,7 @@ BEGIN
|
||||
|
||||
UPDATE
|
||||
OS
|
||||
SET
|
||||
SET
|
||||
[Id] = OSI.[Id],
|
||||
[SponsoringOrganizationId] = OSI.[SponsoringOrganizationId],
|
||||
[SponsoringOrganizationUserID] = OSI.[SponsoringOrganizationUserID],
|
||||
@ -16,10 +16,12 @@ BEGIN
|
||||
[PlanSponsorshipType] = OSI.[PlanSponsorshipType],
|
||||
[ToDelete] = OSI.[ToDelete],
|
||||
[LastSyncDate] = OSI.[LastSyncDate],
|
||||
[ValidUntil] = OSI.[ValidUntil]
|
||||
[ValidUntil] = OSI.[ValidUntil],
|
||||
[IsAdminInitiated] = OSI.[IsAdminInitiated],
|
||||
[Notes] = OSI.[Notes]
|
||||
FROM
|
||||
[dbo].[OrganizationSponsorship] OS
|
||||
INNER JOIN
|
||||
@OrganizationSponsorshipsInput OSI ON OS.Id = OSI.Id
|
||||
|
||||
END
|
||||
END
|
||||
|
@ -55,7 +55,8 @@ CREATE PROCEDURE [dbo].[Organization_Create]
|
||||
@LimitCollectionDeletion BIT = NULL,
|
||||
@AllowAdminAccessToAllCollectionItems BIT = 0,
|
||||
@UseRiskInsights BIT = 0,
|
||||
@LimitItemDeletion BIT = 0
|
||||
@LimitItemDeletion BIT = 0,
|
||||
@UseAdminSponsoredFamilies BIT = 0
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -118,7 +119,8 @@ BEGIN
|
||||
[LimitCollectionDeletion],
|
||||
[AllowAdminAccessToAllCollectionItems],
|
||||
[UseRiskInsights],
|
||||
[LimitItemDeletion]
|
||||
[LimitItemDeletion],
|
||||
[UseAdminSponsoredFamilies]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@ -178,6 +180,7 @@ BEGIN
|
||||
@LimitCollectionDeletion,
|
||||
@AllowAdminAccessToAllCollectionItems,
|
||||
@UseRiskInsights,
|
||||
@LimitItemDeletion
|
||||
@LimitItemDeletion,
|
||||
@UseAdminSponsoredFamilies
|
||||
)
|
||||
END
|
||||
|
@ -25,7 +25,8 @@ BEGIN
|
||||
[LimitCollectionDeletion],
|
||||
[AllowAdminAccessToAllCollectionItems],
|
||||
[UseRiskInsights],
|
||||
[LimitItemDeletion]
|
||||
[LimitItemDeletion],
|
||||
[UseAdminSponsoredFamilies]
|
||||
FROM
|
||||
[dbo].[Organization]
|
||||
END
|
||||
|
@ -55,7 +55,8 @@ CREATE PROCEDURE [dbo].[Organization_Update]
|
||||
@LimitCollectionDeletion BIT = null,
|
||||
@AllowAdminAccessToAllCollectionItems BIT = 0,
|
||||
@UseRiskInsights BIT = 0,
|
||||
@LimitItemDeletion BIT = 0
|
||||
@LimitItemDeletion BIT = 0,
|
||||
@UseAdminSponsoredFamilies BIT = 0
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
@ -118,7 +119,8 @@ BEGIN
|
||||
[LimitCollectionDeletion] = @LimitCollectionDeletion,
|
||||
[AllowAdminAccessToAllCollectionItems] = @AllowAdminAccessToAllCollectionItems,
|
||||
[UseRiskInsights] = @UseRiskInsights,
|
||||
[LimitItemDeletion] = @LimitItemDeletion
|
||||
[LimitItemDeletion] = @LimitItemDeletion,
|
||||
[UseAdminSponsoredFamilies] = @UseAdminSponsoredFamilies
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
END
|
||||
|
@ -56,6 +56,7 @@ CREATE TABLE [dbo].[Organization] (
|
||||
[LimitItemDeletion] BIT NOT NULL CONSTRAINT [DF_Organization_LimitItemDeletion] DEFAULT (0),
|
||||
[AllowAdminAccessToAllCollectionItems] BIT NOT NULL CONSTRAINT [DF_Organization_AllowAdminAccessToAllCollectionItems] DEFAULT (0),
|
||||
[UseRiskInsights] BIT NOT NULL CONSTRAINT [DF_Organization_UseRiskInsights] DEFAULT (0),
|
||||
[UseAdminSponsoredFamilies] BIT NOT NULL CONSTRAINT [DF_Organization_UseAdminSponsoredFamilies] DEFAULT (0),
|
||||
CONSTRAINT [PK_Organization] PRIMARY KEY CLUSTERED ([Id] ASC)
|
||||
);
|
||||
|
||||
|
@ -9,6 +9,8 @@ CREATE TABLE [dbo].[OrganizationSponsorship] (
|
||||
[ToDelete] BIT DEFAULT (0) NOT NULL,
|
||||
[LastSyncDate] DATETIME2 (7) NULL,
|
||||
[ValidUntil] DATETIME2 (7) NULL,
|
||||
[IsAdminInitiated] BIT NOT NULL CONSTRAINT [DF_OrganizationSponsorship_IsAdminInitiated] DEFAULT (0),
|
||||
[Notes] NVARCHAR(512) NULL,
|
||||
CONSTRAINT [PK_OrganizationSponsorship] PRIMARY KEY CLUSTERED ([Id] ASC),
|
||||
CONSTRAINT [FK_OrganizationSponsorship_SponsoringOrg] FOREIGN KEY ([SponsoringOrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
|
||||
CONSTRAINT [FK_OrganizationSponsorship_SponsoredOrg] FOREIGN KEY ([SponsoredOrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
|
||||
|
@ -8,5 +8,7 @@ CREATE TYPE [dbo].[OrganizationSponsorshipType] AS TABLE(
|
||||
[PlanSponsorshipType] TINYINT,
|
||||
[LastSyncDate] DATETIME2(7),
|
||||
[ValidUntil] DATETIME2(7),
|
||||
[ToDelete] BIT
|
||||
)
|
||||
[ToDelete] BIT,
|
||||
[IsAdminInitiated] BIT DEFAULT 0,
|
||||
[Notes] NVARCHAR(512) NULL
|
||||
)
|
||||
|
@ -50,6 +50,7 @@ SELECT
|
||||
O.[LimitCollectionDeletion],
|
||||
O.[AllowAdminAccessToAllCollectionItems],
|
||||
O.[UseRiskInsights],
|
||||
O.[UseAdminSponsoredFamilies],
|
||||
O.[LimitItemDeletion]
|
||||
FROM
|
||||
[dbo].[OrganizationUser] OU
|
||||
|
@ -36,6 +36,7 @@ SELECT
|
||||
O.[LimitCollectionDeletion],
|
||||
O.[AllowAdminAccessToAllCollectionItems],
|
||||
O.[UseRiskInsights],
|
||||
O.[UseAdminSponsoredFamilies],
|
||||
P.[Type] ProviderType,
|
||||
O.[LimitItemDeletion]
|
||||
FROM
|
||||
|
@ -251,4 +251,52 @@ public class ValidateSponsorshipCommandTests : CancelSponsorshipCommandTestsBase
|
||||
await AssertDidNotRemoveSponsoredPaymentAsync(sutProvider);
|
||||
await AssertDidNotDeleteSponsorshipAsync(sutProvider);
|
||||
}
|
||||
|
||||
[Theory(Skip = "Temporarily disabled")]
|
||||
[BitMemberAutoData(nameof(EnterprisePlanTypes))]
|
||||
public async Task ValidateSponsorshipAsync_AdminInitiatedButUseAdminSponsoredFamiliesFalse_IsInvalid(
|
||||
PlanType planType, Organization sponsoredOrg, OrganizationSponsorship existingSponsorship,
|
||||
Organization sponsoringOrg, SutProvider<ValidateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
sponsoringOrg.PlanType = planType;
|
||||
sponsoringOrg.UseAdminSponsoredFamilies = false;
|
||||
existingSponsorship.SponsoringOrganizationId = sponsoringOrg.Id;
|
||||
existingSponsorship.IsAdminInitiated = true;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>()
|
||||
.GetBySponsoredOrganizationIdAsync(sponsoredOrg.Id).Returns(existingSponsorship);
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(sponsoredOrg.Id).Returns(sponsoredOrg);
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(sponsoringOrg.Id).Returns(sponsoringOrg);
|
||||
|
||||
var result = await sutProvider.Sut.ValidateSponsorshipAsync(sponsoredOrg.Id);
|
||||
|
||||
Assert.False(result);
|
||||
await AssertRemovedSponsoredPaymentAsync(sponsoredOrg, existingSponsorship, sutProvider);
|
||||
await AssertDeletedSponsorshipAsync(existingSponsorship, sutProvider);
|
||||
}
|
||||
|
||||
[Theory(Skip = "Temporarily disabled")]
|
||||
[BitMemberAutoData(nameof(EnterprisePlanTypes))]
|
||||
public async Task ValidateSponsorshipAsync_AdminInitiatedAndUseAdminSponsoredFamiliesTrue_ContinuesValidation(
|
||||
PlanType planType, Organization sponsoredOrg, OrganizationSponsorship existingSponsorship,
|
||||
Organization sponsoringOrg, SutProvider<ValidateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
sponsoringOrg.PlanType = planType;
|
||||
sponsoringOrg.UseAdminSponsoredFamilies = true;
|
||||
existingSponsorship.SponsoringOrganizationId = sponsoringOrg.Id;
|
||||
existingSponsorship.IsAdminInitiated = true;
|
||||
existingSponsorship.ToDelete = false;
|
||||
existingSponsorship.LastSyncDate = null; // Not a self-hosted sponsorship
|
||||
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>()
|
||||
.GetBySponsoredOrganizationIdAsync(sponsoredOrg.Id).Returns(existingSponsorship);
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(sponsoredOrg.Id).Returns(sponsoredOrg);
|
||||
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(sponsoringOrg.Id).Returns(sponsoringOrg);
|
||||
|
||||
var result = await sutProvider.Sut.ValidateSponsorshipAsync(sponsoredOrg.Id);
|
||||
|
||||
Assert.True(result);
|
||||
await AssertDidNotRemoveSponsoredPaymentAsync(sutProvider);
|
||||
await AssertDidNotDeleteSponsorshipAsync(sutProvider);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
@ -36,28 +38,28 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
||||
[Theory, BitAutoData]
|
||||
public async Task CreateSponsorship_OfferedToNotFound_ThrowsBadRequest(OrganizationUser orgUser, SutProvider<CreateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId.Value).ReturnsNull();
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId!.Value).ReturnsNull();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateSponsorshipAsync(null, orgUser, PlanSponsorshipType.FamiliesForEnterprise, default, default));
|
||||
sutProvider.Sut.CreateSponsorshipAsync(null, orgUser, PlanSponsorshipType.FamiliesForEnterprise, default, default, null));
|
||||
|
||||
Assert.Contains("Cannot offer a Families Organization Sponsorship to yourself. Choose a different email.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateAsync(default);
|
||||
.CreateAsync(null!);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task CreateSponsorship_OfferedToSelf_ThrowsBadRequest(OrganizationUser orgUser, string sponsoredEmail, User user, SutProvider<CreateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
user.Email = sponsoredEmail;
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId.Value).Returns(user);
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId!.Value).Returns(user);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateSponsorshipAsync(null, orgUser, PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, default));
|
||||
sutProvider.Sut.CreateSponsorshipAsync(null, orgUser, PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, default, null));
|
||||
|
||||
Assert.Contains("Cannot offer a Families Organization Sponsorship to yourself. Choose a different email.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateAsync(default);
|
||||
.CreateAsync(null!);
|
||||
}
|
||||
|
||||
[Theory, BitMemberAutoData(nameof(NonEnterprisePlanTypes))]
|
||||
@ -67,14 +69,14 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
||||
org.PlanType = sponsoringOrgPlan;
|
||||
orgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId.Value).Returns(user);
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId!.Value).Returns(user);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateSponsorshipAsync(org, orgUser, PlanSponsorshipType.FamiliesForEnterprise, default, default));
|
||||
sutProvider.Sut.CreateSponsorshipAsync(org, orgUser, PlanSponsorshipType.FamiliesForEnterprise, default, default, null));
|
||||
|
||||
Assert.Contains("Specified Organization cannot sponsor other organizations.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateAsync(default);
|
||||
.CreateAsync(null!);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -86,14 +88,14 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
||||
org.PlanType = PlanType.EnterpriseAnnually;
|
||||
orgUser.Status = statusType;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId.Value).Returns(user);
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId!.Value).Returns(user);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateSponsorshipAsync(org, orgUser, PlanSponsorshipType.FamiliesForEnterprise, default, default));
|
||||
sutProvider.Sut.CreateSponsorshipAsync(org, orgUser, PlanSponsorshipType.FamiliesForEnterprise, default, default, null));
|
||||
|
||||
Assert.Contains("Only confirmed users can sponsor other organizations.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateAsync(default);
|
||||
.CreateAsync(null!);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -106,16 +108,48 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
||||
org.PlanType = PlanType.EnterpriseAnnually;
|
||||
orgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId.Value).Returns(user);
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(orgUser.UserId!.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>()
|
||||
.GetBySponsoringOrganizationUserIdAsync(orgUser.Id).Returns(sponsorship);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(orgUser.UserId.Value);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateSponsorshipAsync(org, orgUser, sponsorship.PlanSponsorshipType.Value, default, default));
|
||||
sutProvider.Sut.CreateSponsorshipAsync(org, orgUser, sponsorship.PlanSponsorshipType!.Value, null, null, null));
|
||||
|
||||
Assert.Contains("Can only sponsor one organization per Organization User.", exception.Message);
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateAsync(default);
|
||||
.CreateAsync(null!);
|
||||
}
|
||||
|
||||
public static readonly OrganizationUserStatusType[] UnconfirmedOrganizationUsersStatuses = Enum
|
||||
.GetValues<OrganizationUserStatusType>()
|
||||
.Where(x => x != OrganizationUserStatusType.Confirmed)
|
||||
.ToArray();
|
||||
|
||||
[Theory]
|
||||
[BitMemberAutoData(nameof(UnconfirmedOrganizationUsersStatuses))]
|
||||
public async Task CreateSponsorship_ThrowsBadRequestException_WhenMemberDoesNotHaveConfirmedStatusInOrganization(
|
||||
OrganizationUserStatusType status, Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, User user,
|
||||
string sponsoredEmail, string friendlyName, Guid sponsorshipId,
|
||||
SutProvider<CreateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||
sponsoringOrgUser.Status = status;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||
{
|
||||
var sponsorship = callInfo.Arg<OrganizationSponsorship>();
|
||||
sponsorship.Id = sponsorshipId;
|
||||
});
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(sponsoringOrgUser.UserId.Value);
|
||||
|
||||
|
||||
var actual = await Assert.ThrowsAsync<BadRequestException>(async () =>
|
||||
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser, PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, null));
|
||||
|
||||
Assert.Equal("Only confirmed users can sponsor other organizations.", actual.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -126,16 +160,17 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(default)).Do(callInfo =>
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||
{
|
||||
var sponsorship = callInfo.Arg<OrganizationSponsorship>();
|
||||
sponsorship.Id = sponsorshipId;
|
||||
});
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(sponsoringOrgUser.UserId.Value);
|
||||
|
||||
|
||||
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName);
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, null);
|
||||
|
||||
var expectedSponsorship = new OrganizationSponsorship
|
||||
{
|
||||
@ -145,6 +180,8 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
||||
FriendlyName = friendlyName,
|
||||
OfferedToEmail = sponsoredEmail,
|
||||
PlanSponsorshipType = PlanSponsorshipType.FamiliesForEnterprise,
|
||||
IsAdminInitiated = false,
|
||||
Notes = null
|
||||
};
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().Received(1)
|
||||
@ -161,20 +198,138 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
||||
|
||||
var expectedException = new Exception();
|
||||
OrganizationSponsorship createdSponsorship = null;
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().UpsertAsync(default).ThrowsForAnyArgs(callInfo =>
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().UpsertAsync(null!).ThrowsForAnyArgs(callInfo =>
|
||||
{
|
||||
createdSponsorship = callInfo.ArgAt<OrganizationSponsorship>(0);
|
||||
createdSponsorship.Id = Guid.NewGuid();
|
||||
return expectedException;
|
||||
});
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(sponsoringOrgUser.UserId.Value);
|
||||
|
||||
var actualException = await Assert.ThrowsAsync<Exception>(() =>
|
||||
sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName));
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, null));
|
||||
Assert.Same(expectedException, actualException);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().Received(1)
|
||||
.DeleteAsync(createdSponsorship);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CreateSponsorship_MissingManageUsersPermission_ThrowsUnauthorizedException(
|
||||
Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, User user, string sponsoredEmail,
|
||||
string friendlyName, Guid sponsorshipId, Guid currentUserId, SutProvider<CreateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||
{
|
||||
var sponsorship = callInfo.Arg<OrganizationSponsorship>();
|
||||
sponsorship.Id = sponsorshipId;
|
||||
});
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(currentUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().Organizations.Returns([
|
||||
new()
|
||||
{
|
||||
Id = sponsoringOrg.Id,
|
||||
Permissions = new Permissions(),
|
||||
Type = OrganizationUserType.Custom
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
var actual = await Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
|
||||
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, notes: null));
|
||||
|
||||
Assert.Equal("You do not have permissions to send sponsorships on behalf of the organization.", actual.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(OrganizationUserType.User)]
|
||||
[BitAutoData(OrganizationUserType.Custom)]
|
||||
public async Task CreateSponsorship_InvalidUserType_ThrowsUnauthorizedException(
|
||||
OrganizationUserType organizationUserType,
|
||||
Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, User user, string sponsoredEmail,
|
||||
string friendlyName, Guid sponsorshipId, Guid currentUserId, SutProvider<CreateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||
{
|
||||
var sponsorship = callInfo.Arg<OrganizationSponsorship>();
|
||||
sponsorship.Id = sponsorshipId;
|
||||
});
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(currentUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().Organizations.Returns([
|
||||
new()
|
||||
{
|
||||
Id = sponsoringOrg.Id,
|
||||
Permissions = new Permissions(),
|
||||
Type = organizationUserType
|
||||
}
|
||||
]);
|
||||
|
||||
var actual = await Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
|
||||
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, notes: null));
|
||||
|
||||
Assert.Equal("You do not have permissions to send sponsorships on behalf of the organization.", actual.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(OrganizationUserType.Admin)]
|
||||
[BitAutoData(OrganizationUserType.Owner)]
|
||||
public async Task CreateSponsorship_CreatesAdminInitiatedSponsorship(
|
||||
OrganizationUserType organizationUserType,
|
||||
Organization sponsoringOrg, OrganizationUser sponsoringOrgUser, User user, string sponsoredEmail,
|
||||
string friendlyName, Guid sponsorshipId, Guid currentUserId, string notes, SutProvider<CreateSponsorshipCommand> sutProvider)
|
||||
{
|
||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||
sponsoringOrg.UseAdminSponsoredFamilies = true;
|
||||
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||
|
||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||
{
|
||||
var sponsorship = callInfo.Arg<OrganizationSponsorship>();
|
||||
sponsorship.Id = sponsorshipId;
|
||||
});
|
||||
sutProvider.GetDependency<ICurrentContext>().UserId.Returns(currentUserId);
|
||||
sutProvider.GetDependency<ICurrentContext>().Organizations.Returns([
|
||||
new()
|
||||
{
|
||||
Id = sponsoringOrg.Id,
|
||||
Permissions = new Permissions { ManageUsers = true },
|
||||
Type = organizationUserType
|
||||
}
|
||||
]);
|
||||
|
||||
var actual = await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, notes);
|
||||
|
||||
|
||||
var expectedSponsorship = new OrganizationSponsorship
|
||||
{
|
||||
Id = sponsorshipId,
|
||||
SponsoringOrganizationId = sponsoringOrg.Id,
|
||||
SponsoringOrganizationUserId = sponsoringOrgUser.Id,
|
||||
FriendlyName = friendlyName,
|
||||
OfferedToEmail = sponsoredEmail,
|
||||
PlanSponsorshipType = PlanSponsorshipType.FamiliesForEnterprise,
|
||||
IsAdminInitiated = true,
|
||||
Notes = notes
|
||||
};
|
||||
|
||||
Assert.True(SponsorshipValidator(expectedSponsorship, actual));
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationSponsorshipRepository>().Received(1)
|
||||
.UpsertAsync(Arg.Is<OrganizationSponsorship>(s => SponsorshipValidator(s, expectedSponsorship)));
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +261,7 @@ public class OrganizationUserRepositoryTests
|
||||
Assert.Equal(organization.LimitCollectionDeletion, result.LimitCollectionDeletion);
|
||||
Assert.Equal(organization.AllowAdminAccessToAllCollectionItems, result.AllowAdminAccessToAllCollectionItems);
|
||||
Assert.Equal(organization.UseRiskInsights, result.UseRiskInsights);
|
||||
Assert.Equal(organization.UseAdminSponsoredFamilies, result.UseAdminSponsoredFamilies);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
|
@ -0,0 +1,532 @@
|
||||
ALTER TABLE [dbo].[Organization] ADD [UseAdminSponsoredFamilies] bit NOT NULL CONSTRAINT [DF_Organization_UseAdminSponsoredFamilies] default (0)
|
||||
GO;
|
||||
|
||||
ALTER TABLE [dbo].[OrganizationSponsorship] ADD [IsAdminInitiated] BIT CONSTRAINT [DF_OrganizationSponsorship_IsAdminInitiated] DEFAULT (0) NOT NULL
|
||||
GO;
|
||||
|
||||
ALTER TABLE [dbo].[OrganizationSponsorship] ADD [Notes] NVARCHAR(512) NULL
|
||||
GO;
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Organization_Create]
|
||||
@Id UNIQUEIDENTIFIER OUTPUT,
|
||||
@Identifier NVARCHAR(50),
|
||||
@Name NVARCHAR(50),
|
||||
@BusinessName NVARCHAR(50),
|
||||
@BusinessAddress1 NVARCHAR(50),
|
||||
@BusinessAddress2 NVARCHAR(50),
|
||||
@BusinessAddress3 NVARCHAR(50),
|
||||
@BusinessCountry VARCHAR(2),
|
||||
@BusinessTaxNumber NVARCHAR(30),
|
||||
@BillingEmail NVARCHAR(256),
|
||||
@Plan NVARCHAR(50),
|
||||
@PlanType TINYINT,
|
||||
@Seats INT,
|
||||
@MaxCollections SMALLINT,
|
||||
@UsePolicies BIT,
|
||||
@UseSso BIT,
|
||||
@UseGroups BIT,
|
||||
@UseDirectory BIT,
|
||||
@UseEvents BIT,
|
||||
@UseTotp BIT,
|
||||
@Use2fa BIT,
|
||||
@UseApi BIT,
|
||||
@UseResetPassword BIT,
|
||||
@SelfHost BIT,
|
||||
@UsersGetPremium BIT,
|
||||
@Storage BIGINT,
|
||||
@MaxStorageGb SMALLINT,
|
||||
@Gateway TINYINT,
|
||||
@GatewayCustomerId VARCHAR(50),
|
||||
@GatewaySubscriptionId VARCHAR(50),
|
||||
@ReferenceData VARCHAR(MAX),
|
||||
@Enabled BIT,
|
||||
@LicenseKey VARCHAR(100),
|
||||
@PublicKey VARCHAR(MAX),
|
||||
@PrivateKey VARCHAR(MAX),
|
||||
@TwoFactorProviders NVARCHAR(MAX),
|
||||
@ExpirationDate DATETIME2(7),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@OwnersNotifiedOfAutoscaling DATETIME2(7),
|
||||
@MaxAutoscaleSeats INT,
|
||||
@UseKeyConnector BIT = 0,
|
||||
@UseScim BIT = 0,
|
||||
@UseCustomPermissions BIT = 0,
|
||||
@UseSecretsManager BIT = 0,
|
||||
@Status TINYINT = 0,
|
||||
@UsePasswordManager BIT = 1,
|
||||
@SmSeats INT = null,
|
||||
@SmServiceAccounts INT = null,
|
||||
@MaxAutoscaleSmSeats INT= null,
|
||||
@MaxAutoscaleSmServiceAccounts INT = null,
|
||||
@SecretsManagerBeta BIT = 0,
|
||||
@LimitCollectionCreation BIT = NULL,
|
||||
@LimitCollectionDeletion BIT = NULL,
|
||||
@AllowAdminAccessToAllCollectionItems BIT = 0,
|
||||
@UseRiskInsights BIT = 0,
|
||||
@LimitItemDeletion BIT = 0,
|
||||
@UseAdminSponsoredFamilies BIT = 0
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
INSERT INTO [dbo].[Organization]
|
||||
(
|
||||
[Id],
|
||||
[Identifier],
|
||||
[Name],
|
||||
[BusinessName],
|
||||
[BusinessAddress1],
|
||||
[BusinessAddress2],
|
||||
[BusinessAddress3],
|
||||
[BusinessCountry],
|
||||
[BusinessTaxNumber],
|
||||
[BillingEmail],
|
||||
[Plan],
|
||||
[PlanType],
|
||||
[Seats],
|
||||
[MaxCollections],
|
||||
[UsePolicies],
|
||||
[UseSso],
|
||||
[UseGroups],
|
||||
[UseDirectory],
|
||||
[UseEvents],
|
||||
[UseTotp],
|
||||
[Use2fa],
|
||||
[UseApi],
|
||||
[UseResetPassword],
|
||||
[SelfHost],
|
||||
[UsersGetPremium],
|
||||
[Storage],
|
||||
[MaxStorageGb],
|
||||
[Gateway],
|
||||
[GatewayCustomerId],
|
||||
[GatewaySubscriptionId],
|
||||
[ReferenceData],
|
||||
[Enabled],
|
||||
[LicenseKey],
|
||||
[PublicKey],
|
||||
[PrivateKey],
|
||||
[TwoFactorProviders],
|
||||
[ExpirationDate],
|
||||
[CreationDate],
|
||||
[RevisionDate],
|
||||
[OwnersNotifiedOfAutoscaling],
|
||||
[MaxAutoscaleSeats],
|
||||
[UseKeyConnector],
|
||||
[UseScim],
|
||||
[UseCustomPermissions],
|
||||
[UseSecretsManager],
|
||||
[Status],
|
||||
[UsePasswordManager],
|
||||
[SmSeats],
|
||||
[SmServiceAccounts],
|
||||
[MaxAutoscaleSmSeats],
|
||||
[MaxAutoscaleSmServiceAccounts],
|
||||
[SecretsManagerBeta],
|
||||
[LimitCollectionCreation],
|
||||
[LimitCollectionDeletion],
|
||||
[AllowAdminAccessToAllCollectionItems],
|
||||
[UseRiskInsights],
|
||||
[LimitItemDeletion],
|
||||
[UseAdminSponsoredFamilies]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@Id,
|
||||
@Identifier,
|
||||
@Name,
|
||||
@BusinessName,
|
||||
@BusinessAddress1,
|
||||
@BusinessAddress2,
|
||||
@BusinessAddress3,
|
||||
@BusinessCountry,
|
||||
@BusinessTaxNumber,
|
||||
@BillingEmail,
|
||||
@Plan,
|
||||
@PlanType,
|
||||
@Seats,
|
||||
@MaxCollections,
|
||||
@UsePolicies,
|
||||
@UseSso,
|
||||
@UseGroups,
|
||||
@UseDirectory,
|
||||
@UseEvents,
|
||||
@UseTotp,
|
||||
@Use2fa,
|
||||
@UseApi,
|
||||
@UseResetPassword,
|
||||
@SelfHost,
|
||||
@UsersGetPremium,
|
||||
@Storage,
|
||||
@MaxStorageGb,
|
||||
@Gateway,
|
||||
@GatewayCustomerId,
|
||||
@GatewaySubscriptionId,
|
||||
@ReferenceData,
|
||||
@Enabled,
|
||||
@LicenseKey,
|
||||
@PublicKey,
|
||||
@PrivateKey,
|
||||
@TwoFactorProviders,
|
||||
@ExpirationDate,
|
||||
@CreationDate,
|
||||
@RevisionDate,
|
||||
@OwnersNotifiedOfAutoscaling,
|
||||
@MaxAutoscaleSeats,
|
||||
@UseKeyConnector,
|
||||
@UseScim,
|
||||
@UseCustomPermissions,
|
||||
@UseSecretsManager,
|
||||
@Status,
|
||||
@UsePasswordManager,
|
||||
@SmSeats,
|
||||
@SmServiceAccounts,
|
||||
@MaxAutoscaleSmSeats,
|
||||
@MaxAutoscaleSmServiceAccounts,
|
||||
@SecretsManagerBeta,
|
||||
@LimitCollectionCreation,
|
||||
@LimitCollectionDeletion,
|
||||
@AllowAdminAccessToAllCollectionItems,
|
||||
@UseRiskInsights,
|
||||
@LimitItemDeletion,
|
||||
@UseAdminSponsoredFamilies
|
||||
)
|
||||
END
|
||||
GO;
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Organization_ReadAbilities]
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
[Id],
|
||||
[UseEvents],
|
||||
[Use2fa],
|
||||
CASE
|
||||
WHEN [Use2fa] = 1 AND [TwoFactorProviders] IS NOT NULL AND [TwoFactorProviders] != '{}' THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END AS [Using2fa],
|
||||
[UsersGetPremium],
|
||||
[UseCustomPermissions],
|
||||
[UseSso],
|
||||
[UseKeyConnector],
|
||||
[UseScim],
|
||||
[UseResetPassword],
|
||||
[UsePolicies],
|
||||
[Enabled],
|
||||
[LimitCollectionCreation],
|
||||
[LimitCollectionDeletion],
|
||||
[AllowAdminAccessToAllCollectionItems],
|
||||
[UseRiskInsights],
|
||||
[LimitItemDeletion],
|
||||
[UseAdminSponsoredFamilies]
|
||||
FROM
|
||||
[dbo].[Organization]
|
||||
END
|
||||
GO;
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[Organization_Update]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@Identifier NVARCHAR(50),
|
||||
@Name NVARCHAR(50),
|
||||
@BusinessName NVARCHAR(50),
|
||||
@BusinessAddress1 NVARCHAR(50),
|
||||
@BusinessAddress2 NVARCHAR(50),
|
||||
@BusinessAddress3 NVARCHAR(50),
|
||||
@BusinessCountry VARCHAR(2),
|
||||
@BusinessTaxNumber NVARCHAR(30),
|
||||
@BillingEmail NVARCHAR(256),
|
||||
@Plan NVARCHAR(50),
|
||||
@PlanType TINYINT,
|
||||
@Seats INT,
|
||||
@MaxCollections SMALLINT,
|
||||
@UsePolicies BIT,
|
||||
@UseSso BIT,
|
||||
@UseGroups BIT,
|
||||
@UseDirectory BIT,
|
||||
@UseEvents BIT,
|
||||
@UseTotp BIT,
|
||||
@Use2fa BIT,
|
||||
@UseApi BIT,
|
||||
@UseResetPassword BIT,
|
||||
@SelfHost BIT,
|
||||
@UsersGetPremium BIT,
|
||||
@Storage BIGINT,
|
||||
@MaxStorageGb SMALLINT,
|
||||
@Gateway TINYINT,
|
||||
@GatewayCustomerId VARCHAR(50),
|
||||
@GatewaySubscriptionId VARCHAR(50),
|
||||
@ReferenceData VARCHAR(MAX),
|
||||
@Enabled BIT,
|
||||
@LicenseKey VARCHAR(100),
|
||||
@PublicKey VARCHAR(MAX),
|
||||
@PrivateKey VARCHAR(MAX),
|
||||
@TwoFactorProviders NVARCHAR(MAX),
|
||||
@ExpirationDate DATETIME2(7),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7),
|
||||
@OwnersNotifiedOfAutoscaling DATETIME2(7),
|
||||
@MaxAutoscaleSeats INT,
|
||||
@UseKeyConnector BIT = 0,
|
||||
@UseScim BIT = 0,
|
||||
@UseCustomPermissions BIT = 0,
|
||||
@UseSecretsManager BIT = 0,
|
||||
@Status TINYINT = 0,
|
||||
@UsePasswordManager BIT = 1,
|
||||
@SmSeats INT = null,
|
||||
@SmServiceAccounts INT = null,
|
||||
@MaxAutoscaleSmSeats INT = null,
|
||||
@MaxAutoscaleSmServiceAccounts INT = null,
|
||||
@SecretsManagerBeta BIT = 0,
|
||||
@LimitCollectionCreation BIT = null,
|
||||
@LimitCollectionDeletion BIT = null,
|
||||
@AllowAdminAccessToAllCollectionItems BIT = 0,
|
||||
@UseRiskInsights BIT = 0,
|
||||
@LimitItemDeletion BIT = 0,
|
||||
@UseAdminSponsoredFamilies BIT = 0
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
UPDATE
|
||||
[dbo].[Organization]
|
||||
SET
|
||||
[Identifier] = @Identifier,
|
||||
[Name] = @Name,
|
||||
[BusinessName] = @BusinessName,
|
||||
[BusinessAddress1] = @BusinessAddress1,
|
||||
[BusinessAddress2] = @BusinessAddress2,
|
||||
[BusinessAddress3] = @BusinessAddress3,
|
||||
[BusinessCountry] = @BusinessCountry,
|
||||
[BusinessTaxNumber] = @BusinessTaxNumber,
|
||||
[BillingEmail] = @BillingEmail,
|
||||
[Plan] = @Plan,
|
||||
[PlanType] = @PlanType,
|
||||
[Seats] = @Seats,
|
||||
[MaxCollections] = @MaxCollections,
|
||||
[UsePolicies] = @UsePolicies,
|
||||
[UseSso] = @UseSso,
|
||||
[UseGroups] = @UseGroups,
|
||||
[UseDirectory] = @UseDirectory,
|
||||
[UseEvents] = @UseEvents,
|
||||
[UseTotp] = @UseTotp,
|
||||
[Use2fa] = @Use2fa,
|
||||
[UseApi] = @UseApi,
|
||||
[UseResetPassword] = @UseResetPassword,
|
||||
[SelfHost] = @SelfHost,
|
||||
[UsersGetPremium] = @UsersGetPremium,
|
||||
[Storage] = @Storage,
|
||||
[MaxStorageGb] = @MaxStorageGb,
|
||||
[Gateway] = @Gateway,
|
||||
[GatewayCustomerId] = @GatewayCustomerId,
|
||||
[GatewaySubscriptionId] = @GatewaySubscriptionId,
|
||||
[ReferenceData] = @ReferenceData,
|
||||
[Enabled] = @Enabled,
|
||||
[LicenseKey] = @LicenseKey,
|
||||
[PublicKey] = @PublicKey,
|
||||
[PrivateKey] = @PrivateKey,
|
||||
[TwoFactorProviders] = @TwoFactorProviders,
|
||||
[ExpirationDate] = @ExpirationDate,
|
||||
[CreationDate] = @CreationDate,
|
||||
[RevisionDate] = @RevisionDate,
|
||||
[OwnersNotifiedOfAutoscaling] = @OwnersNotifiedOfAutoscaling,
|
||||
[MaxAutoscaleSeats] = @MaxAutoscaleSeats,
|
||||
[UseKeyConnector] = @UseKeyConnector,
|
||||
[UseScim] = @UseScim,
|
||||
[UseCustomPermissions] = @UseCustomPermissions,
|
||||
[UseSecretsManager] = @UseSecretsManager,
|
||||
[Status] = @Status,
|
||||
[UsePasswordManager] = @UsePasswordManager,
|
||||
[SmSeats] = @SmSeats,
|
||||
[SmServiceAccounts] = @SmServiceAccounts,
|
||||
[MaxAutoscaleSmSeats] = @MaxAutoscaleSmSeats,
|
||||
[MaxAutoscaleSmServiceAccounts] = @MaxAutoscaleSmServiceAccounts,
|
||||
[SecretsManagerBeta] = @SecretsManagerBeta,
|
||||
[LimitCollectionCreation] = @LimitCollectionCreation,
|
||||
[LimitCollectionDeletion] = @LimitCollectionDeletion,
|
||||
[AllowAdminAccessToAllCollectionItems] = @AllowAdminAccessToAllCollectionItems,
|
||||
[UseRiskInsights] = @UseRiskInsights,
|
||||
[LimitItemDeletion] = @LimitItemDeletion,
|
||||
[UseAdminSponsoredFamilies] = @UseAdminSponsoredFamilies
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
END
|
||||
GO;
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[OrganizationSponsorship_Update]
|
||||
@Id UNIQUEIDENTIFIER,
|
||||
@SponsoringOrganizationId UNIQUEIDENTIFIER,
|
||||
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
|
||||
@SponsoredOrganizationId UNIQUEIDENTIFIER,
|
||||
@FriendlyName NVARCHAR(256),
|
||||
@OfferedToEmail NVARCHAR(256),
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@ToDelete BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@ValidUntil DATETIME2 (7),
|
||||
@IsAdminInitiated BIT = 0,
|
||||
@Notes NVARCHAR(512) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
UPDATE
|
||||
[dbo].[OrganizationSponsorship]
|
||||
SET
|
||||
[SponsoringOrganizationId] = @SponsoringOrganizationId,
|
||||
[SponsoringOrganizationUserID] = @SponsoringOrganizationUserID,
|
||||
[SponsoredOrganizationId] = @SponsoredOrganizationId,
|
||||
[FriendlyName] = @FriendlyName,
|
||||
[OfferedToEmail] = @OfferedToEmail,
|
||||
[PlanSponsorshipType] = @PlanSponsorshipType,
|
||||
[ToDelete] = @ToDelete,
|
||||
[LastSyncDate] = @LastSyncDate,
|
||||
[ValidUntil] = @ValidUntil,
|
||||
[IsAdminInitiated] = @IsAdminInitiated,
|
||||
[Notes] = @Notes
|
||||
WHERE
|
||||
[Id] = @Id
|
||||
END
|
||||
GO;
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[OrganizationSponsorship_Create]
|
||||
@Id UNIQUEIDENTIFIER OUTPUT,
|
||||
@SponsoringOrganizationId UNIQUEIDENTIFIER,
|
||||
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
|
||||
@SponsoredOrganizationId UNIQUEIDENTIFIER,
|
||||
@FriendlyName NVARCHAR(256),
|
||||
@OfferedToEmail NVARCHAR(256),
|
||||
@PlanSponsorshipType TINYINT,
|
||||
@ToDelete BIT,
|
||||
@LastSyncDate DATETIME2 (7),
|
||||
@ValidUntil DATETIME2 (7),
|
||||
@IsAdminInitiated BIT = 0,
|
||||
@Notes NVARCHAR(512) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
INSERT INTO [dbo].[OrganizationSponsorship]
|
||||
(
|
||||
[Id],
|
||||
[SponsoringOrganizationId],
|
||||
[SponsoringOrganizationUserID],
|
||||
[SponsoredOrganizationId],
|
||||
[FriendlyName],
|
||||
[OfferedToEmail],
|
||||
[PlanSponsorshipType],
|
||||
[ToDelete],
|
||||
[LastSyncDate],
|
||||
[ValidUntil],
|
||||
[IsAdminInitiated],
|
||||
[Notes]
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@Id,
|
||||
@SponsoringOrganizationId,
|
||||
@SponsoringOrganizationUserID,
|
||||
@SponsoredOrganizationId,
|
||||
@FriendlyName,
|
||||
@OfferedToEmail,
|
||||
@PlanSponsorshipType,
|
||||
@ToDelete,
|
||||
@LastSyncDate,
|
||||
@ValidUntil,
|
||||
@IsAdminInitiated,
|
||||
@Notes
|
||||
)
|
||||
END
|
||||
GO;
|
||||
|
||||
DROP PROCEDURE IF EXISTS [dbo].[OrganizationSponsorship_CreateMany];
|
||||
DROP PROCEDURE IF EXISTS [dbo].[OrganizationSponsorship_UpdateMany];
|
||||
DROP TYPE IF EXISTS [dbo].[OrganizationSponsorshipType] GO;
|
||||
|
||||
CREATE TYPE [dbo].[OrganizationSponsorshipType] AS TABLE(
|
||||
[Id] UNIQUEIDENTIFIER,
|
||||
[SponsoringOrganizationId] UNIQUEIDENTIFIER,
|
||||
[SponsoringOrganizationUserID] UNIQUEIDENTIFIER,
|
||||
[SponsoredOrganizationId] UNIQUEIDENTIFIER,
|
||||
[FriendlyName] NVARCHAR(256),
|
||||
[OfferedToEmail] VARCHAR(256),
|
||||
[PlanSponsorshipType] TINYINT,
|
||||
[LastSyncDate] DATETIME2(7),
|
||||
[ValidUntil] DATETIME2(7),
|
||||
[ToDelete] BIT,
|
||||
[IsAdminInitiated] BIT DEFAULT 0,
|
||||
[Notes] NVARCHAR(512) NULL
|
||||
);
|
||||
GO;
|
||||
|
||||
CREATE PROCEDURE [dbo].[OrganizationSponsorship_CreateMany]
|
||||
@OrganizationSponsorshipsInput [dbo].[OrganizationSponsorshipType] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
INSERT INTO [dbo].[OrganizationSponsorship]
|
||||
(
|
||||
[Id],
|
||||
[SponsoringOrganizationId],
|
||||
[SponsoringOrganizationUserID],
|
||||
[SponsoredOrganizationId],
|
||||
[FriendlyName],
|
||||
[OfferedToEmail],
|
||||
[PlanSponsorshipType],
|
||||
[ToDelete],
|
||||
[LastSyncDate],
|
||||
[ValidUntil],
|
||||
[IsAdminInitiated],
|
||||
[Notes]
|
||||
)
|
||||
SELECT
|
||||
OS.[Id],
|
||||
OS.[SponsoringOrganizationId],
|
||||
OS.[SponsoringOrganizationUserID],
|
||||
OS.[SponsoredOrganizationId],
|
||||
OS.[FriendlyName],
|
||||
OS.[OfferedToEmail],
|
||||
OS.[PlanSponsorshipType],
|
||||
OS.[ToDelete],
|
||||
OS.[LastSyncDate],
|
||||
OS.[ValidUntil],
|
||||
OS.[IsAdminInitiated],
|
||||
OS.[Notes]
|
||||
FROM
|
||||
@OrganizationSponsorshipsInput OS
|
||||
END
|
||||
GO;
|
||||
|
||||
CREATE PROCEDURE [dbo].[OrganizationSponsorship_UpdateMany]
|
||||
@OrganizationSponsorshipsInput [dbo].[OrganizationSponsorshipType] READONLY
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
UPDATE
|
||||
OS
|
||||
SET
|
||||
[Id] = OSI.[Id],
|
||||
[SponsoringOrganizationId] = OSI.[SponsoringOrganizationId],
|
||||
[SponsoringOrganizationUserID] = OSI.[SponsoringOrganizationUserID],
|
||||
[SponsoredOrganizationId] = OSI.[SponsoredOrganizationId],
|
||||
[FriendlyName] = OSI.[FriendlyName],
|
||||
[OfferedToEmail] = OSI.[OfferedToEmail],
|
||||
[PlanSponsorshipType] = OSI.[PlanSponsorshipType],
|
||||
[ToDelete] = OSI.[ToDelete],
|
||||
[LastSyncDate] = OSI.[LastSyncDate],
|
||||
[ValidUntil] = OSI.[ValidUntil],
|
||||
[IsAdminInitiated] = OSI.[IsAdminInitiated],
|
||||
[Notes] = OSI.[Notes]
|
||||
FROM
|
||||
[dbo].[OrganizationSponsorship] OS
|
||||
INNER JOIN
|
||||
@OrganizationSponsorshipsInput OSI ON OS.Id = OSI.Id
|
||||
|
||||
END
|
||||
GO;
|
@ -0,0 +1,278 @@
|
||||
CREATE OR ALTER VIEW [dbo].[OrganizationUserOrganizationDetailsView]
|
||||
AS
|
||||
SELECT
|
||||
OU.[UserId],
|
||||
OU.[OrganizationId],
|
||||
OU.[Id] OrganizationUserId,
|
||||
O.[Name],
|
||||
O.[Enabled],
|
||||
O.[PlanType],
|
||||
O.[UsePolicies],
|
||||
O.[UseSso],
|
||||
O.[UseKeyConnector],
|
||||
O.[UseScim],
|
||||
O.[UseGroups],
|
||||
O.[UseDirectory],
|
||||
O.[UseEvents],
|
||||
O.[UseTotp],
|
||||
O.[Use2fa],
|
||||
O.[UseApi],
|
||||
O.[UseResetPassword],
|
||||
O.[SelfHost],
|
||||
O.[UsersGetPremium],
|
||||
O.[UseCustomPermissions],
|
||||
O.[UseSecretsManager],
|
||||
O.[Seats],
|
||||
O.[MaxCollections],
|
||||
O.[MaxStorageGb],
|
||||
O.[Identifier],
|
||||
OU.[Key],
|
||||
OU.[ResetPasswordKey],
|
||||
O.[PublicKey],
|
||||
O.[PrivateKey],
|
||||
OU.[Status],
|
||||
OU.[Type],
|
||||
SU.[ExternalId] SsoExternalId,
|
||||
OU.[Permissions],
|
||||
PO.[ProviderId],
|
||||
P.[Name] ProviderName,
|
||||
P.[Type] ProviderType,
|
||||
SS.[Data] SsoConfig,
|
||||
OS.[FriendlyName] FamilySponsorshipFriendlyName,
|
||||
OS.[LastSyncDate] FamilySponsorshipLastSyncDate,
|
||||
OS.[ToDelete] FamilySponsorshipToDelete,
|
||||
OS.[ValidUntil] FamilySponsorshipValidUntil,
|
||||
OU.[AccessSecretsManager],
|
||||
O.[UsePasswordManager],
|
||||
O.[SmSeats],
|
||||
O.[SmServiceAccounts],
|
||||
O.[LimitCollectionCreation],
|
||||
O.[LimitCollectionDeletion],
|
||||
O.[AllowAdminAccessToAllCollectionItems],
|
||||
O.[UseRiskInsights],
|
||||
O.[UseAdminSponsoredFamilies],
|
||||
O.[LimitItemDeletion]
|
||||
FROM
|
||||
[dbo].[OrganizationUser] OU
|
||||
LEFT JOIN
|
||||
[dbo].[Organization] O ON O.[Id] = OU.[OrganizationId]
|
||||
LEFT JOIN
|
||||
[dbo].[SsoUser] SU ON SU.[UserId] = OU.[UserId] AND SU.[OrganizationId] = OU.[OrganizationId]
|
||||
LEFT JOIN
|
||||
[dbo].[ProviderOrganization] PO ON PO.[OrganizationId] = O.[Id]
|
||||
LEFT JOIN
|
||||
[dbo].[Provider] P ON P.[Id] = PO.[ProviderId]
|
||||
LEFT JOIN
|
||||
[dbo].[SsoConfig] SS ON SS.[OrganizationId] = OU.[OrganizationId]
|
||||
LEFT JOIN
|
||||
[dbo].[OrganizationSponsorship] OS ON OS.[SponsoringOrganizationUserID] = OU.[Id]
|
||||
GO
|
||||
|
||||
CREATE OR ALTER VIEW [dbo].[ProviderUserProviderOrganizationDetailsView]
|
||||
AS
|
||||
SELECT
|
||||
PU.[UserId],
|
||||
PO.[OrganizationId],
|
||||
O.[Name],
|
||||
O.[Enabled],
|
||||
O.[UsePolicies],
|
||||
O.[UseSso],
|
||||
O.[UseKeyConnector],
|
||||
O.[UseScim],
|
||||
O.[UseGroups],
|
||||
O.[UseDirectory],
|
||||
O.[UseEvents],
|
||||
O.[UseTotp],
|
||||
O.[Use2fa],
|
||||
O.[UseApi],
|
||||
O.[UseResetPassword],
|
||||
O.[SelfHost],
|
||||
O.[UsersGetPremium],
|
||||
O.[UseCustomPermissions],
|
||||
O.[Seats],
|
||||
O.[MaxCollections],
|
||||
O.[MaxStorageGb],
|
||||
O.[Identifier],
|
||||
PO.[Key],
|
||||
O.[PublicKey],
|
||||
O.[PrivateKey],
|
||||
PU.[Status],
|
||||
PU.[Type],
|
||||
PO.[ProviderId],
|
||||
PU.[Id] ProviderUserId,
|
||||
P.[Name] ProviderName,
|
||||
O.[PlanType],
|
||||
O.[LimitCollectionCreation],
|
||||
O.[LimitCollectionDeletion],
|
||||
O.[AllowAdminAccessToAllCollectionItems],
|
||||
O.[UseRiskInsights],
|
||||
O.[UseAdminSponsoredFamilies],
|
||||
P.[Type] ProviderType,
|
||||
O.[LimitItemDeletion]
|
||||
FROM
|
||||
[dbo].[ProviderUser] PU
|
||||
INNER JOIN
|
||||
[dbo].[ProviderOrganization] PO ON PO.[ProviderId] = PU.[ProviderId]
|
||||
INNER JOIN
|
||||
[dbo].[Organization] O ON O.[Id] = PO.[OrganizationId]
|
||||
INNER JOIN
|
||||
[dbo].[Provider] P ON P.[Id] = PU.[ProviderId]
|
||||
GO
|
||||
|
||||
|
||||
--Manually refresh [dbo].[OrganizationUserOrganizationDetailsView]
|
||||
IF OBJECT_ID('[dbo].[OrganizationUserOrganizationDetailsView]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationUserOrganizationDetailsView]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[ProviderUserProviderOrganizationDetailsView]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[ProviderUserProviderOrganizationDetailsView]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationView]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationView]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorshipView]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorshipView]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationUserOrganizationDetailsView]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationUserOrganizationDetailsView]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_OrganizationUserDeleted]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_OrganizationUserDeleted]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_CreateMany]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_CreateMany]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_OrganizationUsersDeleted]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_OrganizationUsersDeleted]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_DeleteExpired]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_DeleteExpired]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_Update]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_Update]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_DeleteById]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_DeleteById]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_Create]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_Create]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_OrganizationDeleted]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_OrganizationDeleted]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_UpdateMany]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_UpdateMany]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_DeleteByIds]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_DeleteByIds]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadLatestBySponsoringOrganizationId]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_ReadLatestBySponsoringOrganizationId]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadByOfferedToEmail]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_ReadByOfferedToEmail]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadBySponsoredOrganizationId]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_ReadBySponsoredOrganizationId]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationId]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationId]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadById]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_ReadById]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationUserId]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationSponsorship_ReadBySponsoringOrganizationUserId]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationUserOrganizationDetails_ReadByUserIdStatus]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationUserOrganizationDetails_ReadByUserIdStatus]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationUserOrganizationDetails_ReadByUserIdStatusOrganizationId]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationUserOrganizationDetails_ReadByUserIdStatusOrganizationId]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationUser_DeleteById]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationUser_DeleteById]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[OrganizationUser_DeleteByIds]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[OrganizationUser_DeleteByIds]';
|
||||
END
|
||||
GO
|
||||
|
||||
IF OBJECT_ID('[dbo].[Organization_DeleteById]') IS NOT NULL
|
||||
BEGIN
|
||||
EXECUTE sp_refreshsqlmodule N'[dbo].[Organization_DeleteById]';
|
||||
END
|
||||
GO
|
3026
util/MySqlMigrations/Migrations/20250326092653_PM17830_AdminInitiatedSponsorships.Designer.cs
generated
Normal file
3026
util/MySqlMigrations/Migrations/20250326092653_PM17830_AdminInitiatedSponsorships.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,50 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Bit.MySqlMigrations.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class PM17830_AdminInitiatedSponsorships : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsAdminInitiated",
|
||||
table: "OrganizationSponsorship",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Notes",
|
||||
table: "OrganizationSponsorship",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "UseAdminSponsoredFamilies",
|
||||
table: "Organization",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsAdminInitiated",
|
||||
table: "OrganizationSponsorship");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Notes",
|
||||
table: "OrganizationSponsorship");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UseAdminSponsoredFamilies",
|
||||
table: "Organization");
|
||||
}
|
||||
}
|
@ -164,6 +164,9 @@ namespace Bit.MySqlMigrations.Migrations
|
||||
b.Property<bool>("Use2fa")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("UseAdminSponsoredFamilies")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("UseApi")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
@ -1311,9 +1314,15 @@ namespace Bit.MySqlMigrations.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("IsAdminInitiated")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTime?>("LastSyncDate")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("OfferedToEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
3032
util/PostgresMigrations/Migrations/20250326092700_PM17830_AdminInitiatedSponsorships.Designer.cs
generated
Normal file
3032
util/PostgresMigrations/Migrations/20250326092700_PM17830_AdminInitiatedSponsorships.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,49 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Bit.PostgresMigrations.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class PM17830_AdminInitiatedSponsorships : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsAdminInitiated",
|
||||
table: "OrganizationSponsorship",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Notes",
|
||||
table: "OrganizationSponsorship",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "UseAdminSponsoredFamilies",
|
||||
table: "Organization",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsAdminInitiated",
|
||||
table: "OrganizationSponsorship");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Notes",
|
||||
table: "OrganizationSponsorship");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UseAdminSponsoredFamilies",
|
||||
table: "Organization");
|
||||
}
|
||||
}
|
@ -166,6 +166,9 @@ namespace Bit.PostgresMigrations.Migrations
|
||||
b.Property<bool>("Use2fa")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("UseAdminSponsoredFamilies")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("UseApi")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
@ -1316,9 +1319,15 @@ namespace Bit.PostgresMigrations.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<bool>("IsAdminInitiated")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime?>("LastSyncDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("OfferedToEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
3015
util/SqliteMigrations/Migrations/20250326092645_PM17830_AdminInitiatedSponsorships.Designer.cs
generated
Normal file
3015
util/SqliteMigrations/Migrations/20250326092645_PM17830_AdminInitiatedSponsorships.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,49 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Bit.SqliteMigrations.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class PM17830_AdminInitiatedSponsorships : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsAdminInitiated",
|
||||
table: "OrganizationSponsorship",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Notes",
|
||||
table: "OrganizationSponsorship",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "UseAdminSponsoredFamilies",
|
||||
table: "Organization",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsAdminInitiated",
|
||||
table: "OrganizationSponsorship");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Notes",
|
||||
table: "OrganizationSponsorship");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UseAdminSponsoredFamilies",
|
||||
table: "Organization");
|
||||
}
|
||||
}
|
@ -159,6 +159,9 @@ namespace Bit.SqliteMigrations.Migrations
|
||||
b.Property<bool>("Use2fa")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("UseAdminSponsoredFamilies")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("UseApi")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@ -1300,9 +1303,15 @@ namespace Bit.SqliteMigrations.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsAdminInitiated")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("LastSyncDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OfferedToEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
Loading…
x
Reference in New Issue
Block a user