Browse Source

[AC-1828] [AC-1807] Aggregated admin panel pricing fixes (#3448)

* AC-1828: Allow reseller to add all teams and enterprise orgs

* AC-1807: Only show provider-eligible plans on Organization edit

* Thomas' feedback

* Matt's feedback
pull/3462/head
Alex Morask 2 years ago committed by GitHub
parent
commit
cf38ff3c19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/Admin/Views/Shared/_OrganizationForm.cshtml
  2. 15
      src/Infrastructure.EntityFramework/Repositories/OrganizationRepository.cs
  3. 4
      src/Sql/dbo/Stored Procedures/Organization_UnassignedToProviderSearch.sql
  4. 64
      util/Migrator/DbScripts/2023-11-14_00_UpdateOrganizationUnassignedToProviderSearch.sql

6
src/Admin/Views/Shared/_OrganizationForm.cshtml

@ -82,7 +82,11 @@ @@ -82,7 +82,11 @@
<label asp-for="PlanType"></label>
@{
var planTypes = Enum.GetValues<PlanType>()
.Where(p => Model.Provider == null || p is >= PlanType.TeamsMonthly and <= PlanType.TeamsStarter)
.Where(p =>
Model.Provider == null ||
(Model.Provider != null
&& p is >= PlanType.TeamsMonthly2019 and <= PlanType.EnterpriseAnnually2019 or >= PlanType.TeamsMonthly2020 and <= PlanType.EnterpriseAnnually)
)
.Select(e => new SelectListItem
{
Value = ((int)e).ToString(),

15
src/Infrastructure.EntityFramework/Repositories/OrganizationRepository.cs

@ -96,12 +96,17 @@ public class OrganizationRepository : Repository<Core.Entities.Organization, Org @@ -96,12 +96,17 @@ public class OrganizationRepository : Repository<Core.Entities.Organization, Org
public async Task<ICollection<Core.Entities.Organization>> SearchUnassignedToProviderAsync(string name, string ownerEmail, int skip, int take)
{
using var scope = ServiceScopeFactory.CreateScope();
var dbContext = GetDatabaseContext(scope);
var query = from o in dbContext.Organizations
where o.PlanType >= PlanType.TeamsMonthly2020 && o.PlanType <= PlanType.EnterpriseAnnually &&
!dbContext.ProviderOrganizations.Any(po => po.OrganizationId == o.Id) &&
(string.IsNullOrWhiteSpace(name) || EF.Functions.Like(o.Name, $"%{name}%"))
select o;
var query =
from o in dbContext.Organizations
where
((o.PlanType >= PlanType.TeamsMonthly2019 && o.PlanType <= PlanType.EnterpriseAnnually2019) ||
(o.PlanType >= PlanType.TeamsMonthly2020 && o.PlanType <= PlanType.EnterpriseAnnually)) &&
!dbContext.ProviderOrganizations.Any(po => po.OrganizationId == o.Id) &&
(string.IsNullOrWhiteSpace(name) || EF.Functions.Like(o.Name, $"%{name}%"))
select o;
if (string.IsNullOrWhiteSpace(ownerEmail))
{

4
src/Sql/dbo/Stored Procedures/Organization_UnassignedToProviderSearch.sql

@ -21,7 +21,7 @@ BEGIN @@ -21,7 +21,7 @@ BEGIN
INNER JOIN
[dbo].[User] U ON U.[Id] = OU.[UserId]
WHERE
O.[PlanType] >= 8 AND O.[PlanType] <= 11 -- Get 'Team' and 'Enterprise' Organizations
((O.[PlanType] >= 2 AND O.[PlanType] <= 5) OR (O.[PlanType] >= 8 AND O.[PlanType] <= 15)) -- All 'Teams' and 'Enterprise' organizations
AND NOT EXISTS (SELECT * FROM [dbo].[ProviderOrganizationView] PO WHERE PO.[OrganizationId] = O.[Id])
AND (@Name IS NULL OR O.[Name] LIKE @NameLikeSearch)
AND (U.[Email] LIKE @OwnerLikeSearch)
@ -36,7 +36,7 @@ BEGIN @@ -36,7 +36,7 @@ BEGIN
FROM
[dbo].[OrganizationView] O
WHERE
O.[PlanType] >= 8 AND O.[PlanType] <= 11 -- Get 'Team' and 'Enterprise' Organizations
((O.[PlanType] >= 2 AND O.[PlanType] <= 5) OR (O.[PlanType] >= 8 AND O.[PlanType] <= 15)) -- All 'Teams' and 'Enterprise' organizations
AND NOT EXISTS (SELECT * FROM [dbo].[ProviderOrganizationView] PO WHERE PO.[OrganizationId] = O.[Id])
AND (@Name IS NULL OR O.[Name] LIKE @NameLikeSearch)
ORDER BY O.[CreationDate] DESC

64
util/Migrator/DbScripts/2023-11-14_00_UpdateOrganizationUnassignedToProviderSearch.sql

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
/*
This procedure is used by the Bitwarden Admin Panel to retrieve the
Organizations a Reseller Provider is capable of adding as a client.
Currently, the procedure is only surfacing Organizations with the most
current Enterprise or Teams plans, but we actually need to surface any
Enterprise or Teams plan regardless of the version as all of them are
applicable to Resellers.
*/
-- Drop existing SPROC
IF OBJECT_ID('[dbo].[Organization_UnassignedToProviderSearch]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[Organization_UnassignedToProviderSearch]
END
GO
CREATE PROCEDURE [dbo].[Organization_UnassignedToProviderSearch]
@Name NVARCHAR(50),
@OwnerEmail NVARCHAR(256),
@Skip INT = 0,
@Take INT = 25
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON
DECLARE @NameLikeSearch NVARCHAR(55) = '%' + @Name + '%'
DECLARE @OwnerLikeSearch NVARCHAR(55) = @OwnerEmail + '%'
IF @OwnerEmail IS NOT NULL
BEGIN
SELECT
O.*
FROM
[dbo].[OrganizationView] O
INNER JOIN
[dbo].[OrganizationUser] OU ON O.[Id] = OU.[OrganizationId]
INNER JOIN
[dbo].[User] U ON U.[Id] = OU.[UserId]
WHERE
((O.[PlanType] >= 2 AND O.[PlanType] <= 5) OR (O.[PlanType] >= 8 AND O.[PlanType] <= 15)) -- All 'Teams' and 'Enterprise' organizations
AND NOT EXISTS (SELECT * FROM [dbo].[ProviderOrganizationView] PO WHERE PO.[OrganizationId] = O.[Id])
AND (@Name IS NULL OR O.[Name] LIKE @NameLikeSearch)
AND (U.[Email] LIKE @OwnerLikeSearch)
ORDER BY O.[CreationDate] DESC
OFFSET @Skip ROWS
FETCH NEXT @Take ROWS ONLY
END
ELSE
BEGIN
SELECT
O.*
FROM
[dbo].[OrganizationView] O
WHERE
((O.[PlanType] >= 2 AND O.[PlanType] <= 5) OR (O.[PlanType] >= 8 AND O.[PlanType] <= 15)) -- All 'Teams' and 'Enterprise' organizations
AND NOT EXISTS (SELECT * FROM [dbo].[ProviderOrganizationView] PO WHERE PO.[OrganizationId] = O.[Id])
AND (@Name IS NULL OR O.[Name] LIKE @NameLikeSearch)
ORDER BY O.[CreationDate] DESC
OFFSET @Skip ROWS
FETCH NEXT @Take ROWS ONLY
END
END
GO
Loading…
Cancel
Save