diff --git a/src/Admin/AdminConsole/Controllers/OrganizationsController.cs b/src/Admin/AdminConsole/Controllers/OrganizationsController.cs
index 0d992cb96a42..608940bf0c0d 100644
--- a/src/Admin/AdminConsole/Controllers/OrganizationsController.cs
+++ b/src/Admin/AdminConsole/Controllers/OrganizationsController.cs
@@ -473,6 +473,7 @@ private void UpdateOrganization(Organization organization, OrganizationEditModel
organization.UseOrganizationDomains = model.UseOrganizationDomains;
organization.UseAdminSponsoredFamilies = model.UseAdminSponsoredFamilies;
organization.UseAutomaticUserConfirmation = model.UseAutomaticUserConfirmation;
+ organization.UseDisableSmAdsForUsers = model.UseDisableSmAdsForUsers;
//secrets
organization.SmSeats = model.SmSeats;
diff --git a/src/Admin/AdminConsole/Models/OrganizationEditModel.cs b/src/Admin/AdminConsole/Models/OrganizationEditModel.cs
index 6059a003b6b0..c2483c115251 100644
--- a/src/Admin/AdminConsole/Models/OrganizationEditModel.cs
+++ b/src/Admin/AdminConsole/Models/OrganizationEditModel.cs
@@ -107,6 +107,7 @@ public OrganizationEditModel(
MaxAutoscaleSmServiceAccounts = org.MaxAutoscaleSmServiceAccounts;
UseOrganizationDomains = org.UseOrganizationDomains;
UseAutomaticUserConfirmation = org.UseAutomaticUserConfirmation;
+ UseDisableSmAdsForUsers = org.UseDisableSmAdsForUsers;
_plans = plans;
}
@@ -193,6 +194,8 @@ public OrganizationEditModel(
public int? MaxAutoscaleSmServiceAccounts { get; set; }
[Display(Name = "Use Organization Domains")]
public bool UseOrganizationDomains { get; set; }
+ [Display(Name = "Disable SM Ads For Users")]
+ public bool UseDisableSmAdsForUsers { get; set; }
[Display(Name = "Automatic User Confirmation")]
public bool UseAutomaticUserConfirmation { get; set; }
@@ -327,6 +330,7 @@ public Organization ToOrganization(Organization existingOrganization)
existingOrganization.SmServiceAccounts = SmServiceAccounts;
existingOrganization.MaxAutoscaleSmServiceAccounts = MaxAutoscaleSmServiceAccounts;
existingOrganization.UseOrganizationDomains = UseOrganizationDomains;
+ existingOrganization.UseDisableSmAdsForUsers = UseDisableSmAdsForUsers;
return existingOrganization;
}
}
diff --git a/src/Admin/AdminConsole/Views/Shared/_OrganizationForm.cshtml b/src/Admin/AdminConsole/Views/Shared/_OrganizationForm.cshtml
index cb71c0fc78ae..705a35a99c4a 100644
--- a/src/Admin/AdminConsole/Views/Shared/_OrganizationForm.cshtml
+++ b/src/Admin/AdminConsole/Views/Shared/_OrganizationForm.cshtml
@@ -181,6 +181,10 @@
+
+
+
+
Access Intelligence
diff --git a/src/Api/AdminConsole/Models/Response/Organizations/OrganizationResponseModel.cs b/src/Api/AdminConsole/Models/Response/Organizations/OrganizationResponseModel.cs
index 8006a85734d7..85f5fa39b307 100644
--- a/src/Api/AdminConsole/Models/Response/Organizations/OrganizationResponseModel.cs
+++ b/src/Api/AdminConsole/Models/Response/Organizations/OrganizationResponseModel.cs
@@ -71,6 +71,7 @@ public OrganizationResponseModel(
UseOrganizationDomains = organization.UseOrganizationDomains;
UseAdminSponsoredFamilies = organization.UseAdminSponsoredFamilies;
UseAutomaticUserConfirmation = organization.UseAutomaticUserConfirmation;
+ UseDisableSmAdsForUsers = organization.UseDisableSmAdsForUsers;
}
public Guid Id { get; set; }
@@ -120,6 +121,7 @@ public OrganizationResponseModel(
public bool UseOrganizationDomains { get; set; }
public bool UseAdminSponsoredFamilies { get; set; }
public bool UseAutomaticUserConfirmation { get; set; }
+ public bool UseDisableSmAdsForUsers { get; set; }
}
public class OrganizationSubscriptionResponseModel : OrganizationResponseModel
diff --git a/src/Core/AdminConsole/Entities/Organization.cs b/src/Core/AdminConsole/Entities/Organization.cs
index 73aa162f223f..71041939c461 100644
--- a/src/Core/AdminConsole/Entities/Organization.cs
+++ b/src/Core/AdminConsole/Entities/Organization.cs
@@ -134,6 +134,11 @@ public class Organization : ITableObject
, IStorableSubscriber, IRevisable
///
public bool UseAutomaticUserConfirmation { get; set; }
+ ///
+ /// If set to true, disables Secrets Manager ads for users in the organization
+ ///
+ public bool UseDisableSmAdsForUsers { get; set; }
+
public void SetNewId()
{
if (Id == default(Guid))
@@ -333,6 +338,7 @@ public void UpdateFromLicense(OrganizationLicense license, IFeatureService featu
UseRiskInsights = license.UseRiskInsights;
UseOrganizationDomains = license.UseOrganizationDomains;
UseAdminSponsoredFamilies = license.UseAdminSponsoredFamilies;
+ UseDisableSmAdsForUsers = license.UseDisableSmAdsForUsers;
UseAutomaticUserConfirmation = license.UseAutomaticUserConfirmation;
}
}
diff --git a/src/Core/AdminConsole/Models/Data/Organizations/OrganizationAbility.cs b/src/Core/AdminConsole/Models/Data/Organizations/OrganizationAbility.cs
index 3c02a4f50b4d..298b18c01bb9 100644
--- a/src/Core/AdminConsole/Models/Data/Organizations/OrganizationAbility.cs
+++ b/src/Core/AdminConsole/Models/Data/Organizations/OrganizationAbility.cs
@@ -29,6 +29,7 @@ public OrganizationAbility(Organization organization)
UseOrganizationDomains = organization.UseOrganizationDomains;
UseAdminSponsoredFamilies = organization.UseAdminSponsoredFamilies;
UseAutomaticUserConfirmation = organization.UseAutomaticUserConfirmation;
+ UseDisableSmAdsForUsers = organization.UseDisableSmAdsForUsers;
}
public Guid Id { get; set; }
@@ -51,4 +52,5 @@ public OrganizationAbility(Organization organization)
public bool UseOrganizationDomains { get; set; }
public bool UseAdminSponsoredFamilies { get; set; }
public bool UseAutomaticUserConfirmation { get; set; }
+ public bool UseDisableSmAdsForUsers { get; set; }
}
diff --git a/src/Core/AdminConsole/Models/Data/Organizations/SelfHostedOrganizationDetails.cs b/src/Core/AdminConsole/Models/Data/Organizations/SelfHostedOrganizationDetails.cs
index 84ff16494362..a0f8020357ee 100644
--- a/src/Core/AdminConsole/Models/Data/Organizations/SelfHostedOrganizationDetails.cs
+++ b/src/Core/AdminConsole/Models/Data/Organizations/SelfHostedOrganizationDetails.cs
@@ -154,6 +154,7 @@ public Organization ToOrganization()
Status = Status,
UseRiskInsights = UseRiskInsights,
UseAdminSponsoredFamilies = UseAdminSponsoredFamilies,
+ UseDisableSmAdsForUsers = UseDisableSmAdsForUsers,
};
}
}
diff --git a/src/Core/AdminConsole/Services/OrganizationFactory.cs b/src/Core/AdminConsole/Services/OrganizationFactory.cs
index f5df3327b1ba..fc51d30c1d6d 100644
--- a/src/Core/AdminConsole/Services/OrganizationFactory.cs
+++ b/src/Core/AdminConsole/Services/OrganizationFactory.cs
@@ -62,6 +62,8 @@ public static Organization Create(
UseAdminSponsoredFamilies =
claimsPrincipal.GetValue(OrganizationLicenseConstants.UseAdminSponsoredFamilies),
UseAutomaticUserConfirmation = claimsPrincipal.GetValue(OrganizationLicenseConstants.UseAutomaticUserConfirmation),
+ UseDisableSmAdsForUsers =
+ claimsPrincipal.GetValue(OrganizationLicenseConstants.UseDisableSmAdsForUsers),
};
public static Organization Create(
diff --git a/src/Core/Billing/Licenses/LicenseConstants.cs b/src/Core/Billing/Licenses/LicenseConstants.cs
index 79ac94be62df..5b631620385f 100644
--- a/src/Core/Billing/Licenses/LicenseConstants.cs
+++ b/src/Core/Billing/Licenses/LicenseConstants.cs
@@ -44,6 +44,7 @@ public static class OrganizationLicenseConstants
public const string UseAdminSponsoredFamilies = nameof(UseAdminSponsoredFamilies);
public const string UseOrganizationDomains = nameof(UseOrganizationDomains);
public const string UseAutomaticUserConfirmation = nameof(UseAutomaticUserConfirmation);
+ public const string UseDisableSmAdsForUsers = nameof(UseDisableSmAdsForUsers);
}
public static class UserLicenseConstants
diff --git a/src/Core/Billing/Licenses/Services/Implementations/OrganizationLicenseClaimsFactory.cs b/src/Core/Billing/Licenses/Services/Implementations/OrganizationLicenseClaimsFactory.cs
index e9aadbe7587f..92de1985e18b 100644
--- a/src/Core/Billing/Licenses/Services/Implementations/OrganizationLicenseClaimsFactory.cs
+++ b/src/Core/Billing/Licenses/Services/Implementations/OrganizationLicenseClaimsFactory.cs
@@ -57,6 +57,7 @@ public Task> GenerateClaims(Organization entity, LicenseContext lice
new(nameof(OrganizationLicenseConstants.UseAdminSponsoredFamilies), entity.UseAdminSponsoredFamilies.ToString()),
new(nameof(OrganizationLicenseConstants.UseOrganizationDomains), entity.UseOrganizationDomains.ToString()),
new(nameof(OrganizationLicenseConstants.UseAutomaticUserConfirmation), entity.UseAutomaticUserConfirmation.ToString()),
+ new(nameof(OrganizationLicenseConstants.UseDisableSmAdsForUsers), entity.UseDisableSmAdsForUsers.ToString()),
};
if (entity.Name is not null)
diff --git a/src/Core/Billing/Organizations/Models/OrganizationLicense.cs b/src/Core/Billing/Organizations/Models/OrganizationLicense.cs
index 7ccbacc938f6..4c2bb03b6e5a 100644
--- a/src/Core/Billing/Organizations/Models/OrganizationLicense.cs
+++ b/src/Core/Billing/Organizations/Models/OrganizationLicense.cs
@@ -154,6 +154,7 @@ public OrganizationLicense(Organization org, SubscriptionInfo subscriptionInfo,
public bool UseOrganizationDomains { get; set; }
public bool UseAdminSponsoredFamilies { get; set; }
public bool UseAutomaticUserConfirmation { get; set; }
+ public bool UseDisableSmAdsForUsers { get; set; }
public string Hash { get; set; }
public string Signature { get; set; }
public string Token { get; set; }
@@ -228,7 +229,8 @@ public byte[] GetDataBytes(bool forHash = false)
!p.Name.Equals(nameof(UseRiskInsights)) &&
!p.Name.Equals(nameof(UseAdminSponsoredFamilies)) &&
!p.Name.Equals(nameof(UseOrganizationDomains)) &&
- !p.Name.Equals(nameof(UseAutomaticUserConfirmation)))
+ !p.Name.Equals(nameof(UseAutomaticUserConfirmation)) &&
+ !p.Name.Equals(nameof(UseDisableSmAdsForUsers)))
.OrderBy(p => p.Name)
.Select(p => $"{p.Name}:{Core.Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}")
.Aggregate((c, n) => $"{c}|{n}");
@@ -424,6 +426,7 @@ public bool VerifyData(
var useAdminSponsoredFamilies = claimsPrincipal.GetValue(nameof(UseAdminSponsoredFamilies));
var useOrganizationDomains = claimsPrincipal.GetValue(nameof(UseOrganizationDomains));
var useAutomaticUserConfirmation = claimsPrincipal.GetValue(nameof(UseAutomaticUserConfirmation));
+ var useDisableSmAdsForUsers = claimsPrincipal.GetValue(nameof(UseDisableSmAdsForUsers));
return issued <= DateTime.UtcNow &&
expires >= DateTime.UtcNow &&
@@ -454,7 +457,8 @@ public bool VerifyData(
smServiceAccounts == organization.SmServiceAccounts &&
useAdminSponsoredFamilies == organization.UseAdminSponsoredFamilies &&
useOrganizationDomains == organization.UseOrganizationDomains &&
- useAutomaticUserConfirmation == organization.UseAutomaticUserConfirmation;
+ useAutomaticUserConfirmation == organization.UseAutomaticUserConfirmation &&
+ useDisableSmAdsForUsers == organization.UseDisableSmAdsForUsers;
}
diff --git a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs
index 2238bfca76cf..1c910ae5086d 100644
--- a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs
+++ b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs
@@ -113,7 +113,8 @@ public async Task> GetManyAbilitiesAsync()
UseRiskInsights = e.UseRiskInsights,
UseOrganizationDomains = e.UseOrganizationDomains,
UseAdminSponsoredFamilies = e.UseAdminSponsoredFamilies,
- UseAutomaticUserConfirmation = e.UseAutomaticUserConfirmation
+ UseAutomaticUserConfirmation = e.UseAutomaticUserConfirmation,
+ UseDisableSmAdsForUsers = e.UseDisableSmAdsForUsers
}).ToListAsync();
}
}
diff --git a/src/Sql/dbo/Stored Procedures/Organization_Create.sql b/src/Sql/dbo/Stored Procedures/Organization_Create.sql
index e37fa0e94029..621123809dcc 100644
--- a/src/Sql/dbo/Stored Procedures/Organization_Create.sql
+++ b/src/Sql/dbo/Stored Procedures/Organization_Create.sql
@@ -59,7 +59,8 @@ CREATE PROCEDURE [dbo].[Organization_Create]
@UseOrganizationDomains BIT = 0,
@UseAdminSponsoredFamilies BIT = 0,
@SyncSeats BIT = 0,
- @UseAutomaticUserConfirmation BIT = 0
+ @UseAutomaticUserConfirmation BIT = 0,
+ @UseDisableSmAdsForUsers BIT = 0
AS
BEGIN
SET NOCOUNT ON
@@ -126,70 +127,72 @@ BEGIN
[UseOrganizationDomains],
[UseAdminSponsoredFamilies],
[SyncSeats],
- [UseAutomaticUserConfirmation]
+ [UseAutomaticUserConfirmation],
+ [UseDisableSmAdsForUsers]
)
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,
- @UseOrganizationDomains,
- @UseAdminSponsoredFamilies,
- @SyncSeats,
- @UseAutomaticUserConfirmation
- );
+ (
+ @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,
+ @UseOrganizationDomains,
+ @UseAdminSponsoredFamilies,
+ @SyncSeats,
+ @UseAutomaticUserConfirmation,
+ @UseDisableSmAdsForUsers
+ );
END
diff --git a/src/Sql/dbo/Stored Procedures/Organization_ReadAbilities.sql b/src/Sql/dbo/Stored Procedures/Organization_ReadAbilities.sql
index 59226e59db96..8a877afcaf89 100644
--- a/src/Sql/dbo/Stored Procedures/Organization_ReadAbilities.sql
+++ b/src/Sql/dbo/Stored Procedures/Organization_ReadAbilities.sql
@@ -28,7 +28,8 @@ BEGIN
[LimitItemDeletion],
[UseOrganizationDomains],
[UseAdminSponsoredFamilies],
- [UseAutomaticUserConfirmation]
+ [UseAutomaticUserConfirmation],
+ [UseDisableSmAdsForUsers]
FROM
[dbo].[Organization]
END
diff --git a/src/Sql/dbo/Stored Procedures/Organization_Update.sql b/src/Sql/dbo/Stored Procedures/Organization_Update.sql
index 4807c7bb5061..42b4adeef664 100644
--- a/src/Sql/dbo/Stored Procedures/Organization_Update.sql
+++ b/src/Sql/dbo/Stored Procedures/Organization_Update.sql
@@ -59,7 +59,8 @@ CREATE PROCEDURE [dbo].[Organization_Update]
@UseOrganizationDomains BIT = 0,
@UseAdminSponsoredFamilies BIT = 0,
@SyncSeats BIT = 0,
- @UseAutomaticUserConfirmation BIT = 0
+ @UseAutomaticUserConfirmation BIT = 0,
+ @UseDisableSmAdsForUsers BIT = 0
AS
BEGIN
SET NOCOUNT ON
@@ -126,7 +127,8 @@ BEGIN
[UseOrganizationDomains] = @UseOrganizationDomains,
[UseAdminSponsoredFamilies] = @UseAdminSponsoredFamilies,
[SyncSeats] = @SyncSeats,
- [UseAutomaticUserConfirmation] = @UseAutomaticUserConfirmation
+ [UseAutomaticUserConfirmation] = @UseAutomaticUserConfirmation,
+ [UseDisableSmAdsForUsers] = @UseDisableSmAdsForUsers
WHERE
[Id] = @Id;
END
diff --git a/src/Sql/dbo/Tables/Organization.sql b/src/Sql/dbo/Tables/Organization.sql
index e1ad6863af2f..988f3d8b59bf 100644
--- a/src/Sql/dbo/Tables/Organization.sql
+++ b/src/Sql/dbo/Tables/Organization.sql
@@ -60,6 +60,7 @@ CREATE TABLE [dbo].[Organization] (
[UseAdminSponsoredFamilies] BIT NOT NULL CONSTRAINT [DF_Organization_UseAdminSponsoredFamilies] DEFAULT (0),
[SyncSeats] BIT NOT NULL CONSTRAINT [DF_Organization_SyncSeats] DEFAULT (0),
[UseAutomaticUserConfirmation] BIT NOT NULL CONSTRAINT [DF_Organization_UseAutomaticUserConfirmation] DEFAULT (0),
+ [UseDisableSmAdsForUsers] BIT NOT NULL CONSTRAINT [DF_Organization_UseDisableSmAdsForUsers] DEFAULT (0),
CONSTRAINT [PK_Organization] PRIMARY KEY CLUSTERED ([Id] ASC)
);
diff --git a/test/Core.Test/AdminConsole/Entities/OrganizationTests.cs b/test/Core.Test/AdminConsole/Entities/OrganizationTests.cs
index fed38fb182eb..7fcda324d94d 100644
--- a/test/Core.Test/AdminConsole/Entities/OrganizationTests.cs
+++ b/test/Core.Test/AdminConsole/Entities/OrganizationTests.cs
@@ -96,4 +96,23 @@ public void GetTwoFactorProviders_SavedWithName_Success()
var host = Assert.Contains("Host", (IDictionary)duo.MetaData);
Assert.Equal("Host_value", host);
}
+
+ [Fact]
+ public void UseDisableSmAdsForUsers_DefaultValue_IsFalse()
+ {
+ var organization = new Organization();
+
+ Assert.False(organization.UseDisableSmAdsForUsers);
+ }
+
+ [Fact]
+ public void UseDisableSmAdsForUsers_CanBeSetToTrue()
+ {
+ var organization = new Organization
+ {
+ UseDisableSmAdsForUsers = true
+ };
+
+ Assert.True(organization.UseDisableSmAdsForUsers);
+ }
}
diff --git a/test/Core.Test/Billing/Models/Business/OrganizationLicenseTests.cs b/test/Core.Test/Billing/Models/Business/OrganizationLicenseTests.cs
index 04b579add346..456547f14cdc 100644
--- a/test/Core.Test/Billing/Models/Business/OrganizationLicenseTests.cs
+++ b/test/Core.Test/Billing/Models/Business/OrganizationLicenseTests.cs
@@ -213,7 +213,8 @@ private static Organization CreateDeterministicOrganization()
LimitCollectionDeletion = true,
AllowAdminAccessToAllCollectionItems = true,
UseOrganizationDomains = true,
- UseAdminSponsoredFamilies = false
+ UseAdminSponsoredFamilies = false,
+ UseDisableSmAdsForUsers = false
};
}
@@ -259,4 +260,34 @@ private static ILicensingService CreateMockLicensingService()
.Returns([0x00, 0x01, 0x02, 0x03]); // Dummy signature for hash testing
return mockService;
}
+
+ ///
+ /// Verifies that UseDisableSmAdsForUsers claim is properly generated in the license Token
+ /// and that VerifyData correctly validates the claim.
+ ///
+ [Theory]
+ [BitAutoData(true)]
+ [BitAutoData(false)]
+ public void OrganizationLicense_UseDisableSmAdsForUsers_ClaimGenerationAndValidation(bool useDisableSmAdsForUsers, ClaimsPrincipal claimsPrincipal)
+ {
+ // Arrange
+ var organization = CreateDeterministicOrganization();
+ organization.UseDisableSmAdsForUsers = useDisableSmAdsForUsers;
+
+ var subscriptionInfo = CreateDeterministicSubscriptionInfo();
+ var installationId = new Guid("78900000-0000-0000-0000-000000000123");
+ var mockLicensingService = CreateMockLicensingService();
+
+ var license = new OrganizationLicense(organization, subscriptionInfo, installationId, mockLicensingService);
+ license.Expires = DateTime.MaxValue; // Prevent expiration during test
+
+ var globalSettings = Substitute.For();
+ globalSettings.Installation.Returns(new GlobalSettings.InstallationSettings
+ {
+ Id = installationId
+ });
+
+ // Act & Assert - Verify VerifyData passes with the UseDisableSmAdsForUsers value
+ Assert.True(license.VerifyData(organization, claimsPrincipal, globalSettings));
+ }
}
diff --git a/util/Migrator/DbScripts/2025-10-15_00_AddDisableSMAdsForUsersToOrganization.sql b/util/Migrator/DbScripts/2025-10-15_00_AddDisableSMAdsForUsersToOrganization.sql
new file mode 100644
index 000000000000..b87fa62aa3c7
--- /dev/null
+++ b/util/Migrator/DbScripts/2025-10-15_00_AddDisableSMAdsForUsersToOrganization.sql
@@ -0,0 +1,391 @@
+-- Add the new column if it doesn't exist
+IF NOT EXISTS (SELECT 1
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE TABLE_NAME = 'Organization'
+ AND COLUMN_NAME = 'UseDisableSmAdsForUsers')
+ BEGIN
+ ALTER TABLE [dbo].[Organization]
+ ADD [UseDisableSmAdsForUsers] BIT NOT NULL CONSTRAINT [DF_Organization_UseDisableSmAdsForUsers] DEFAULT 0;
+ END
+GO
+
+-- Refresh views
+EXEC sp_refreshview N'[dbo].[OrganizationCipherDetailsCollectionsView]';
+EXEC sp_refreshview N'[dbo].[OrganizationUserOrganizationDetailsView]';
+EXEC sp_refreshsqlmodule N'[dbo].[OrganizationView]';
+EXEC sp_refreshview N'[dbo].[ProviderOrganizationOrganizationDetailsView]';
+EXEC sp_refreshview N'[dbo].[ProviderUserProviderOrganizationDetailsView]';
+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,
+ @UseOrganizationDomains BIT = 0,
+ @UseAdminSponsoredFamilies BIT = 0,
+ @SyncSeats BIT = 0,
+ @UseAutomaticUserConfirmation BIT = 0,
+ @UseDisableSmAdsForUsers 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],
+ [UseOrganizationDomains],
+ [UseAdminSponsoredFamilies],
+ [SyncSeats],
+ [UseAutomaticUserConfirmation],
+ [UseDisableSmAdsForUsers]
+ )
+ 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,
+ @UseOrganizationDomains,
+ @UseAdminSponsoredFamilies,
+ @SyncSeats,
+ @UseAutomaticUserConfirmation,
+ @UseDisableSmAdsForUsers
+ )
+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,
+ @UseOrganizationDomains BIT = 0,
+ @UseAdminSponsoredFamilies BIT = 0,
+ @SyncSeats BIT = 0,
+ @UseAutomaticUserConfirmation BIT = 0,
+ @UseDisableSmAdsForUsers 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,
+ [UseOrganizationDomains] = @UseOrganizationDomains,
+ [UseAdminSponsoredFamilies] = @UseAdminSponsoredFamilies,
+ [SyncSeats] = @SyncSeats,
+ [UseAutomaticUserConfirmation] = @UseAutomaticUserConfirmation,
+ [UseDisableSmAdsForUsers] = @UseDisableSmAdsForUsers
+ WHERE
+ [Id] = @Id
+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],
+ [UseOrganizationDomains],
+ [UseAdminSponsoredFamilies],
+ [UseAutomaticUserConfirmation],
+ [UseDisableSmAdsForUsers]
+ FROM
+ [dbo].[Organization]
+END
+GO
diff --git a/util/MySqlMigrations/Migrations/20251015172830_AddingNewFlagToLicenseForDisableSMAdsForUser.Designer.cs b/util/MySqlMigrations/Migrations/20251015172830_AddingNewFlagToLicenseForDisableSMAdsForUser.Designer.cs
new file mode 100644
index 000000000000..eef454b35ebc
--- /dev/null
+++ b/util/MySqlMigrations/Migrations/20251015172830_AddingNewFlagToLicenseForDisableSMAdsForUser.Designer.cs
@@ -0,0 +1,3287 @@
+//
+using System;
+using Bit.Infrastructure.EntityFramework.Repositories;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace Bit.MySqlMigrations.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20251015172830_AddingNewFlagToLicenseForDisableSMAdsForUser")]
+ partial class AddingNewFlagToLicenseForDisableSMAdsForUser
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.8")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
+
+ modelBuilder.Entity("Bit.Core.Dirt.Reports.Models.Data.OrganizationMemberBaseDetail", b =>
+ {
+ b.Property("CipherId")
+ .HasColumnType("char(36)");
+
+ b.Property("CollectionId")
+ .HasColumnType("char(36)");
+
+ b.Property("CollectionName")
+ .HasColumnType("longtext");
+
+ b.Property("Email")
+ .HasColumnType("longtext");
+
+ b.Property("GroupId")
+ .HasColumnType("char(36)");
+
+ b.Property("GroupName")
+ .HasColumnType("longtext");
+
+ b.Property("HidePasswords")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Manage")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ReadOnly")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ResetPasswordKey")
+ .HasColumnType("longtext");
+
+ b.Property("TwoFactorProviders")
+ .HasColumnType("longtext");
+
+ b.Property("UserGuid")
+ .HasColumnType("char(36)");
+
+ b.Property("UserName")
+ .HasColumnType("longtext");
+
+ b.Property("UsesKeyConnector")
+ .HasColumnType("tinyint(1)");
+
+ b.ToTable("OrganizationMemberBaseDetails");
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("AllowAdminAccessToAllCollectionItems")
+ .HasColumnType("tinyint(1)")
+ .HasDefaultValue(true);
+
+ b.Property("BillingEmail")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("BusinessAddress1")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("BusinessAddress2")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("BusinessAddress3")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("BusinessCountry")
+ .HasMaxLength(2)
+ .HasColumnType("varchar(2)");
+
+ b.Property("BusinessName")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("BusinessTaxNumber")
+ .HasMaxLength(30)
+ .HasColumnType("varchar(30)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("UseDisableSmAdsForUsers")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Enabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ExpirationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Gateway")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("GatewayCustomerId")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("GatewaySubscriptionId")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("Identifier")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("LicenseKey")
+ .HasMaxLength(100)
+ .HasColumnType("varchar(100)");
+
+ b.Property("LimitCollectionCreation")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LimitCollectionDeletion")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LimitItemDeletion")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("MaxAutoscaleSeats")
+ .HasColumnType("int");
+
+ b.Property("MaxAutoscaleSmSeats")
+ .HasColumnType("int");
+
+ b.Property("MaxAutoscaleSmServiceAccounts")
+ .HasColumnType("int");
+
+ b.Property("MaxCollections")
+ .HasColumnType("smallint");
+
+ b.Property("MaxStorageGb")
+ .HasColumnType("smallint");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("OwnersNotifiedOfAutoscaling")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Plan")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("PlanType")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("PrivateKey")
+ .HasColumnType("longtext");
+
+ b.Property("PublicKey")
+ .HasColumnType("longtext");
+
+ b.Property("ReferenceData")
+ .HasColumnType("longtext");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Seats")
+ .HasColumnType("int");
+
+ b.Property("SelfHost")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SmSeats")
+ .HasColumnType("int");
+
+ b.Property("SmServiceAccounts")
+ .HasColumnType("int");
+
+ b.Property("Status")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("Storage")
+ .HasColumnType("bigint");
+
+ b.Property("SyncSeats")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("TwoFactorProviders")
+ .HasColumnType("longtext");
+
+ b.Property("Use2fa")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseAdminSponsoredFamilies")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseApi")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseCustomPermissions")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseDirectory")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseEvents")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseGroups")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseKeyConnector")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseOrganizationDomains")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UsePasswordManager")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UsePolicies")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseResetPassword")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseRiskInsights")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseScim")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseSecretsManager")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseSso")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseTotp")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UsersGetPremium")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Id", "Enabled")
+ .HasAnnotation("Npgsql:IndexInclude", new[] { "UseTotp" });
+
+ b.ToTable("Organization", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("Configuration")
+ .HasColumnType("longtext");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Type")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrganizationId")
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.HasIndex("OrganizationId", "Type")
+ .IsUnique()
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.ToTable("OrganizationIntegration", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegrationConfiguration", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("Configuration")
+ .HasColumnType("longtext");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("EventType")
+ .HasColumnType("int");
+
+ b.Property("Filters")
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationIntegrationId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Template")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrganizationIntegrationId");
+
+ b.ToTable("OrganizationIntegrationConfiguration", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Policy", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Data")
+ .HasColumnType("longtext");
+
+ b.Property("Enabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Type")
+ .HasColumnType("tinyint unsigned");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrganizationId")
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.HasIndex("OrganizationId", "Type")
+ .IsUnique()
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.ToTable("Policy", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("BillingEmail")
+ .HasColumnType("longtext");
+
+ b.Property("BillingPhone")
+ .HasColumnType("longtext");
+
+ b.Property("BusinessAddress1")
+ .HasColumnType("longtext");
+
+ b.Property("BusinessAddress2")
+ .HasColumnType("longtext");
+
+ b.Property("BusinessAddress3")
+ .HasColumnType("longtext");
+
+ b.Property("BusinessCountry")
+ .HasColumnType("longtext");
+
+ b.Property("BusinessName")
+ .HasColumnType("longtext");
+
+ b.Property("BusinessTaxNumber")
+ .HasColumnType("longtext");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DiscountId")
+ .HasColumnType("longtext");
+
+ b.Property("Enabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Gateway")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("GatewayCustomerId")
+ .HasColumnType("longtext");
+
+ b.Property("GatewaySubscriptionId")
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("Type")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("UseEvents")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Provider", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderOrganization", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Key")
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("ProviderId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Settings")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrganizationId");
+
+ b.HasIndex("ProviderId");
+
+ b.ToTable("ProviderOrganization", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Email")
+ .HasColumnType("longtext");
+
+ b.Property("Key")
+ .HasColumnType("longtext");
+
+ b.Property("Permissions")
+ .HasColumnType("longtext");
+
+ b.Property("ProviderId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("Type")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("UserId")
+ .HasColumnType("char(36)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProviderId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("ProviderUser", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("AccessCode")
+ .HasMaxLength(25)
+ .HasColumnType("varchar(25)");
+
+ b.Property("Approved")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AuthenticationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Key")
+ .HasColumnType("longtext");
+
+ b.Property("MasterPasswordHash")
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("PublicKey")
+ .HasColumnType("longtext");
+
+ b.Property("RequestCountryName")
+ .HasMaxLength(200)
+ .HasColumnType("varchar(200)");
+
+ b.Property("RequestDeviceIdentifier")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("RequestDeviceType")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("RequestIpAddress")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("ResponseDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ResponseDeviceId")
+ .HasColumnType("char(36)");
+
+ b.Property("Type")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("UserId")
+ .HasColumnType("char(36)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrganizationId");
+
+ b.HasIndex("ResponseDeviceId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AuthRequest", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.EmergencyAccess", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Email")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("GranteeId")
+ .HasColumnType("char(36)");
+
+ b.Property("GrantorId")
+ .HasColumnType("char(36)");
+
+ b.Property("KeyEncrypted")
+ .HasColumnType("longtext");
+
+ b.Property("LastNotificationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("RecoveryInitiatedDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Status")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("Type")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("WaitTimeDays")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GranteeId");
+
+ b.HasIndex("GrantorId");
+
+ b.ToTable("EmergencyAccess", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.Grant", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("ClientId")
+ .IsRequired()
+ .HasMaxLength(200)
+ .HasColumnType("varchar(200)");
+
+ b.Property("ConsumedDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Data")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Description")
+ .HasMaxLength(200)
+ .HasColumnType("varchar(200)");
+
+ b.Property("ExpirationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Key")
+ .IsRequired()
+ .HasMaxLength(200)
+ .HasColumnType("varchar(200)");
+
+ b.Property("SessionId")
+ .HasMaxLength(100)
+ .HasColumnType("varchar(100)");
+
+ b.Property("SubjectId")
+ .HasMaxLength(200)
+ .HasColumnType("varchar(200)");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.HasKey("Id")
+ .HasName("PK_Grant")
+ .HasAnnotation("SqlServer:Clustered", true);
+
+ b.HasIndex("ExpirationDate")
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.HasIndex("Key")
+ .IsUnique();
+
+ b.ToTable("Grant", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoConfig", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Data")
+ .HasColumnType("longtext");
+
+ b.Property("Enabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrganizationId");
+
+ b.ToTable("SsoConfig", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ExternalId")
+ .HasMaxLength(300)
+ .HasColumnType("varchar(300)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("UserId")
+ .HasColumnType("char(36)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrganizationId")
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("OrganizationId", "ExternalId")
+ .IsUnique()
+ .HasAnnotation("Npgsql:IndexInclude", new[] { "UserId" })
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.HasIndex("OrganizationId", "UserId")
+ .IsUnique()
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.ToTable("SsoUser", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.WebAuthnCredential", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("AaGuid")
+ .HasColumnType("char(36)");
+
+ b.Property("Counter")
+ .HasColumnType("int");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CredentialId")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("EncryptedPrivateKey")
+ .HasMaxLength(2000)
+ .HasColumnType("varchar(2000)");
+
+ b.Property("EncryptedPublicKey")
+ .HasMaxLength(2000)
+ .HasColumnType("varchar(2000)");
+
+ b.Property("EncryptedUserKey")
+ .HasMaxLength(2000)
+ .HasColumnType("varchar(2000)");
+
+ b.Property("Name")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("PublicKey")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("SupportsPrf")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Type")
+ .HasMaxLength(20)
+ .HasColumnType("varchar(20)");
+
+ b.Property("UserId")
+ .HasColumnType("char(36)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("WebAuthnCredential", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ClientOrganizationMigrationRecord", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("ExpirationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("GatewayCustomerId")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("GatewaySubscriptionId")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("MaxAutoscaleSeats")
+ .HasColumnType("int");
+
+ b.Property("MaxStorageGb")
+ .HasColumnType("smallint");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("PlanType")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("ProviderId")
+ .HasColumnType("char(36)");
+
+ b.Property("Seats")
+ .HasColumnType("int");
+
+ b.Property("Status")
+ .HasColumnType("tinyint unsigned");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProviderId", "OrganizationId")
+ .IsUnique();
+
+ b.ToTable("ClientOrganizationMigrationRecord", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.OrganizationInstallation", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("InstallationId")
+ .HasColumnType("char(36)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("Id")
+ .HasAnnotation("SqlServer:Clustered", true);
+
+ b.HasIndex("InstallationId")
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.HasIndex("OrganizationId")
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.ToTable("OrganizationInstallation", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderInvoiceItem", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("AssignedSeats")
+ .HasColumnType("int");
+
+ b.Property("ClientId")
+ .HasColumnType("char(36)");
+
+ b.Property("ClientName")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("Created")
+ .HasColumnType("datetime(6)");
+
+ b.Property("InvoiceId")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("InvoiceNumber")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("PlanName")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("ProviderId")
+ .HasColumnType("char(36)");
+
+ b.Property("Total")
+ .HasColumnType("decimal(65,30)");
+
+ b.Property("UsedSeats")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProviderId");
+
+ b.ToTable("ProviderInvoiceItem", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderPlan", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("AllocatedSeats")
+ .HasColumnType("int");
+
+ b.Property("PlanType")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("ProviderId")
+ .HasColumnType("char(36)");
+
+ b.Property("PurchasedSeats")
+ .HasColumnType("int");
+
+ b.Property("SeatMinimum")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProviderId");
+
+ b.HasIndex("Id", "PlanType")
+ .IsUnique();
+
+ b.ToTable("ProviderPlan", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Dirt.Models.OrganizationApplication", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property("Applications")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ContentEncryptionKey")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("CreationDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("char(36)");
+
+ b.Property("RevisionDate")
+ .HasColumnType("datetime(6)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Id")
+ .HasAnnotation("SqlServer:Clustered", true);
+
+ b.HasIndex("OrganizationId")
+ .HasAnnotation("SqlServer:Clustered", false);
+
+ b.ToTable("OrganizationApplication", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Dirt.Models.OrganizationReport", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("char(36)");
+
+ b.Property