From 769313abbf290c8bf8d1fddb3ebb5ef85318c051 Mon Sep 17 00:00:00 2001 From: Alex Morask <144709477+amorask-bitwarden@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:31:17 -0500 Subject: [PATCH 01/19] Only set automatic tax to true w/ reverse charge flag if customer has billing location (#5917) --- .../Services/Implementations/OrganizationBillingService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs index c647e825b6..1a89d2a7e2 100644 --- a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs +++ b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs @@ -420,7 +420,7 @@ public class OrganizationBillingService( var setNonUSBusinessUseToReverseCharge = featureService.IsEnabled(FeatureFlagKeys.PM21092_SetNonUSBusinessUseToReverseCharge); - if (setNonUSBusinessUseToReverseCharge) + if (setNonUSBusinessUseToReverseCharge && customer.HasBillingLocation()) { subscriptionCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }; } From ed780d45d3f5e839bd1e390aecb2447ac33b006f Mon Sep 17 00:00:00 2001 From: SmithThe4th Date: Wed, 4 Jun 2025 15:25:21 -0400 Subject: [PATCH 02/19] replace fallback icon default with response (#5878) --- src/Icons/Controllers/IconsController.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Icons/Controllers/IconsController.cs b/src/Icons/Controllers/IconsController.cs index 871219b366..b0d9306f94 100644 --- a/src/Icons/Controllers/IconsController.cs +++ b/src/Icons/Controllers/IconsController.cs @@ -8,16 +8,6 @@ namespace Bit.Icons.Controllers; [Route("")] public class IconsController : Controller { - // Basic bwi-globe icon - private static readonly byte[] _notFoundImage = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUg" + - "AAABMAAAATCAQAAADYWf5HAAABu0lEQVR42nXSvWuTURTH8R+t0heI9Y04aJycdBLNJNrBFBU7OFgUER3q21I0bXK+JwZ" + - "pXISm/QdcRB3EgqBBsNihsUbbgODQQSKCuKSDOApJuuhj8tCYQj/jvYfD795z1MZ+nBKrNKhSwrMxbZTrtRnqlEjZkB/x" + - "C/xmhZrlc71qS0Up8yVzTCGucFNKD1JhORVd70SZNU4okNx5d4+U2UXRIpJFWLClsR79YzN88wQvLWNzzPKEeS/wkQGpW" + - "VhhqhW8TtDJD3Mm1x/23zLSrZCdpBY8BueTNjHSbc+8wC9HlHgU5Aj5AW5zPdcVdpq0UcknWBSr/pjixO4gfp899Kd23p" + - "M2qQCH7LkCnqAqGh73OK/8NPOcaibr90LrW/yWAnaUhqjaOSl9nFR2r5rsqo22ypn1B5IN8VOUMHVgOnNQIX+d62plcz6" + - "rg1/jskK8CMb4we4pG6OWHtR/LBJkC2E4a7ZPkuX5ntumAOM2xxveclEhLvGH6XCmLPs735Eetrw63NnOgr9P9q1viC3x" + - "lRUGOjImqFDuOBvrYYoaZU9z1uPpYae5NfdvbNVG2ZjDIlXq/oMi46lo++4vjjPBl2Dlg00AAAAASUVORK5CYII="); - private readonly IMemoryCache _memoryCache; private readonly IDomainMappingService _domainMappingService; private readonly IIconFetchingService _iconFetchingService; @@ -99,7 +89,7 @@ public class IconsController : Controller if (icon == null) { - return new FileContentResult(_notFoundImage, "image/png"); + return new NotFoundResult(); } return new FileContentResult(icon.Image, icon.Format); From 5c4c06baa04637a35830f0a95e64ede923796da4 Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:06:52 -0700 Subject: [PATCH 03/19] add restricted item type policy (#5914) --- src/Core/AdminConsole/Enums/PolicyType.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Core/AdminConsole/Enums/PolicyType.cs b/src/Core/AdminConsole/Enums/PolicyType.cs index 6f3bcd0102..f72637f862 100644 --- a/src/Core/AdminConsole/Enums/PolicyType.cs +++ b/src/Core/AdminConsole/Enums/PolicyType.cs @@ -17,6 +17,7 @@ public enum PolicyType : byte AutomaticAppLogIn = 12, FreeFamiliesSponsorshipPolicy = 13, RemoveUnlockWithPin = 14, + RestrictedItemTypesPolicy = 15, } public static class PolicyTypeExtensions @@ -43,7 +44,8 @@ public static class PolicyTypeExtensions PolicyType.ActivateAutofill => "Active auto-fill", PolicyType.AutomaticAppLogIn => "Automatically log in users for allowed applications", PolicyType.FreeFamiliesSponsorshipPolicy => "Remove Free Bitwarden Families sponsorship", - PolicyType.RemoveUnlockWithPin => "Remove unlock with PIN" + PolicyType.RemoveUnlockWithPin => "Remove unlock with PIN", + PolicyType.RestrictedItemTypesPolicy => "Restricted item types", }; } } From 66301bb4dc1ec7ea99d55301b14cfaeac216f1a4 Mon Sep 17 00:00:00 2001 From: SmithThe4th Date: Wed, 4 Jun 2025 16:37:42 -0400 Subject: [PATCH 04/19] [PM-19632] Remove security task flag - step 1 (#5856) * step 1- remove flag on security task controller * Fixed lint issues --- src/Api/Vault/Controllers/SecurityTaskController.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Api/Vault/Controllers/SecurityTaskController.cs b/src/Api/Vault/Controllers/SecurityTaskController.cs index 2fe1025ba7..d94c9a9a92 100644 --- a/src/Api/Vault/Controllers/SecurityTaskController.cs +++ b/src/Api/Vault/Controllers/SecurityTaskController.cs @@ -1,9 +1,7 @@ using Bit.Api.Models.Response; using Bit.Api.Vault.Models.Request; using Bit.Api.Vault.Models.Response; -using Bit.Core; using Bit.Core.Services; -using Bit.Core.Utilities; using Bit.Core.Vault.Commands.Interfaces; using Bit.Core.Vault.Entities; using Bit.Core.Vault.Enums; @@ -15,7 +13,6 @@ namespace Bit.Api.Vault.Controllers; [Route("tasks")] [Authorize("Application")] -[RequireFeature(FeatureFlagKeys.SecurityTasks)] public class SecurityTaskController : Controller { private readonly IUserService _userService; From 2435063ac887cc636842d0718418fa33d106e4d2 Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Thu, 5 Jun 2025 12:58:46 -0400 Subject: [PATCH 05/19] Move team SQL underneath dbo (#5923) --- .../dbo => dbo/Auth}/Stored Procedures/AuthRequest_Create.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/AuthRequest_DeleteById.sql | 0 .../Auth}/Stored Procedures/AuthRequest_DeleteIfExpired.sql | 0 .../Stored Procedures/AuthRequest_ReadAdminApprovalsByIds.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/AuthRequest_ReadById.sql | 0 .../Auth}/Stored Procedures/AuthRequest_ReadByUserId.sql | 0 .../Stored Procedures/AuthRequest_ReadPendingByOrganizationId.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/AuthRequest_Update.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/AuthRequest_UpdateMany.sql | 0 .../Device_ReadActiveWithPendingAuthRequestsByUserId.sql | 0 .../Stored Procedures/EmergencyAccessDetails_ReadByGranteeId.sql | 0 .../Stored Procedures/EmergencyAccessDetails_ReadByGrantorId.sql | 0 .../EmergencyAccessDetails_ReadByIdGrantorId.sql | 0 .../EmergencyAccessDetails_ReadExpiredRecoveries.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_Create.sql | 0 .../Auth}/Stored Procedures/EmergencyAccess_DeleteById.sql | 0 .../Auth}/Stored Procedures/EmergencyAccess_ReadById.sql | 0 .../EmergencyAccess_ReadCountByGrantorIdEmail.sql | 0 .../Auth}/Stored Procedures/EmergencyAccess_ReadToNotify.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_Update.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_Delete.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/Grant_DeleteByKey.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/Grant_DeleteExpired.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_Read.sql | 0 .../{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_ReadByKey.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_Save.sql | 0 .../{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_Create.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/SsoConfig_DeleteById.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/SsoConfig_ReadById.sql | 0 .../Auth}/Stored Procedures/SsoConfig_ReadByIdentifier.sql | 0 .../Auth}/Stored Procedures/SsoConfig_ReadByOrganizationId.sql | 0 .../SsoConfig_ReadManyByNotBeforeRevisionDate.sql | 0 .../{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_Update.sql | 0 .../{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_Create.sql | 0 .../{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_Delete.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/SsoUser_DeleteById.sql | 0 .../dbo => dbo/Auth}/Stored Procedures/SsoUser_DeleteMany.sql | 0 .../{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_ReadById.sql | 0 .../Stored Procedures/SsoUser_ReadByUserIdOrganizationId.sql | 0 .../{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_Update.sql | 0 .../User_BumpAccountRevisionDateByEmergencyAccessGranteeId.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Tables/AuthRequest.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Tables/EmergencyAccess.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Tables/Grant.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Tables/SsoConfig.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Tables/SsoUser.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Views/AuthRequestView.sql | 0 .../{Auth/dbo => dbo/Auth}/Views/EmergencyAccessDetailsView.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Views/GrantView.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Views/SsoConfigView.sql | 0 src/Sql/{Auth/dbo => dbo/Auth}/Views/SsoUserView.sql | 0 .../ClientOrganizationMigrationRecord_Create.sql | 0 .../ClientOrganizationMigrationRecord_DeleteById.sql | 0 .../ClientOrganizationMigrationRecord_ReadById.sql | 0 .../ClientOrganizationMigrationRecord_ReadByOrganizationId.sql | 0 .../ClientOrganizationMigrationRecord_ReadByProviderId.sql | 0 .../ClientOrganizationMigrationRecord_Update.sql | 0 .../Stored Procedures/OrganizationInstallation_Create.sql | 0 .../Stored Procedures/OrganizationInstallation_DeleteById.sql | 0 .../Stored Procedures/OrganizationInstallation_ReadById.sql | 0 .../OrganizationInstallation_ReadByInstallationId.sql | 0 .../OrganizationInstallation_ReadByOrganizationId.sql | 0 .../Stored Procedures/OrganizationInstallation_Update.sql | 0 .../Billing}/Stored Procedures/ProviderInvoiceItem_Create.sql | 0 .../Billing}/Stored Procedures/ProviderInvoiceItem_DeleteById.sql | 0 .../Billing}/Stored Procedures/ProviderInvoiceItem_ReadById.sql | 0 .../Stored Procedures/ProviderInvoiceItem_ReadByInvoiceId.sql | 0 .../Stored Procedures/ProviderInvoiceItem_ReadByProviderId.sql | 0 .../Billing}/Stored Procedures/ProviderInvoiceItem_Update.sql | 0 .../dbo => dbo/Billing}/Stored Procedures/ProviderPlan_Create.sql | 0 .../Billing}/Stored Procedures/ProviderPlan_DeleteById.sql | 0 .../Billing}/Stored Procedures/ProviderPlan_ReadById.sql | 0 .../Billing}/Stored Procedures/ProviderPlan_ReadByProviderId.sql | 0 .../dbo => dbo/Billing}/Stored Procedures/ProviderPlan_Update.sql | 0 .../Billing}/Tables/ClientOrganizationMigrationRecord.sql | 0 .../dbo => dbo/Billing}/Tables/OrganizationInstallation.sql | 0 .../{Billing/dbo => dbo/Billing}/Tables/ProviderInvoiceItem.sql | 0 src/Sql/{Billing/dbo => dbo/Billing}/Tables/ProviderPlan.sql | 0 .../Billing}/Views/ClientOrganizationMigrationRecordView.sql | 0 .../dbo => dbo/Billing}/Views/OrganizationInstallationView.sql | 0 .../dbo => dbo/Billing}/Views/ProviderInvoiceItemView.sql | 0 src/Sql/{Billing/dbo => dbo/Billing}/Views/ProviderPlanView.sql | 0 .../Stored Procedures/UserAsymmetricKeys_Regenerate.sql | 0 .../Platform}/Stored Procedures/Installation_Create.sql | 0 .../Platform}/Stored Procedures/Installation_DeleteById.sql | 0 .../Platform}/Stored Procedures/Installation_ReadById.sql | 0 .../Platform}/Stored Procedures/Installation_Update.sql | 0 src/Sql/{Platform/dbo => dbo/Platform}/Tables/Installation.sql | 0 src/Sql/{Platform/dbo => dbo/Platform}/Views/InstallationView.sql | 0 .../Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql | 0 .../SecretsManager}/Stored Procedures/ApiKey/ApiKey_Create.sql | 0 .../Stored Procedures/ApiKey/ApiKey_DeleteByIds.sql | 0 .../Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql | 0 .../Event/Event_ReadPageByOrganizationIdServiceAccountId.sql | 0 .../dbo => dbo/SecretsManager}/Tables/AccessPolicy.sql | 0 .../{SecretsManager/dbo => dbo/SecretsManager}/Tables/ApiKey.sql | 0 .../{SecretsManager/dbo => dbo/SecretsManager}/Tables/Project.sql | 0 .../dbo => dbo/SecretsManager}/Tables/ProjectSecret.sql | 0 .../{SecretsManager/dbo => dbo/SecretsManager}/Tables/Secret.sql | 0 .../dbo => dbo/SecretsManager}/Tables/ServiceAccount.sql | 0 .../dbo => dbo/SecretsManager}/Views/ApiKeyDetailsView.sql | 0 .../dbo => dbo/SecretsManager}/Views/ApiKeyView.sql | 0 .../dbo/Stored Procedures/NotificationStatus_Create.sql | 0 .../NotificationStatus_ReadByNotificationIdAndUserId.sql | 0 .../dbo/Stored Procedures/NotificationStatus_Update.sql | 0 .../dbo/Stored Procedures/Notification_Create.sql | 0 .../dbo/Stored Procedures/Notification_ReadById.sql | 0 .../dbo/Stored Procedures/Notification_ReadByUserIdAndStatus.sql | 0 .../dbo/Stored Procedures/Notification_Update.sql | 0 src/Sql/{NotificationCenter => }/dbo/Tables/Notification.sql | 0 .../{NotificationCenter => }/dbo/Tables/NotificationStatus.sql | 0 .../{Tools/dbo => dbo/Tools}/Stored Procedures/Send_Create.sql | 0 .../dbo => dbo/Tools}/Stored Procedures/Send_DeleteById.sql | 0 .../Tools}/Stored Procedures/Send_ReadByDeletionDateBefore.sql | 0 .../{Tools/dbo => dbo/Tools}/Stored Procedures/Send_ReadById.sql | 0 .../dbo => dbo/Tools}/Stored Procedures/Send_ReadByUserId.sql | 0 .../{Tools/dbo => dbo/Tools}/Stored Procedures/Send_Update.sql | 0 src/Sql/{Tools/dbo => dbo/Tools}/Tables/Send.sql | 0 src/Sql/{Tools/dbo => dbo/Tools}/Views/SendView.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Functions/CipherDetails.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Functions/UserCipherDetails.sql | 0 .../Vault}/Stored Procedures/Cipher/CipherDetails_Create.sql | 0 .../Cipher/CipherDetails_CreateWithCollections.sql | 0 .../Stored Procedures/Cipher/CipherDetails_ReadByIdUserId.sql | 0 .../Stored Procedures/Cipher/CipherDetails_ReadByUserId.sql | 0 .../Cipher/CipherDetails_ReadWithoutOrganizationsByUserId.sql | 0 .../Vault}/Stored Procedures/Cipher/CipherDetails_Update.sql | 0 .../Cipher/CipherOrganizationDetails_ReadById.sql | 0 .../Cipher/CipherOrganizationDetails_ReadByOrganizationId.sql | 0 .../CipherOrganizationDetails_ReadUnassignedByOrganizationId.sql | 0 .../CipherOrganizationPermissions_GetManyByOrganizationId.sql | 0 .../dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Create.sql | 0 .../Stored Procedures/Cipher/Cipher_CreateWithCollections.sql | 0 .../dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Delete.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_DeleteAttachment.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_DeleteById.sql | 0 .../Stored Procedures/Cipher/Cipher_DeleteByIdsOrganizationId.sql | 0 .../Stored Procedures/Cipher/Cipher_DeleteByOrganizationId.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_DeleteByUserId.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_DeleteDeleted.sql | 0 .../dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Move.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_ReadById.sql | 0 .../Stored Procedures/Cipher/Cipher_ReadByOrganizationId.sql | 0 .../Stored Procedures/Cipher/Cipher_ReadCanEditByIdUserId.sql | 0 .../dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Restore.sql | 0 .../Cipher/Cipher_RestoreByIdsOrganizationId.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_SoftDelete.sql | 0 .../Cipher/Cipher_SoftDeleteByIdsOrganizationId.sql | 0 .../dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Update.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_UpdateAttachment.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_UpdateCollections.sql | 0 .../Vault}/Stored Procedures/Cipher/Cipher_UpdatePartial.sql | 0 .../Stored Procedures/Cipher/Cipher_UpdateWithCollections.sql | 0 .../Cipher/UserSecurityTasks_GetManyByCipherIds.sql | 0 .../CollectionCipher_AddCollectionsForManyCiphers.sql | 0 .../CollectionCipher_RemoveCollectionsFromManyCiphers.sql | 0 .../Collections/Collection_ReadByIdWithPermissions.sql | 0 .../Collection_ReadByOrganizationIdWithPermissions.sql | 0 .../dbo => dbo/Vault}/Stored Procedures/Folder/Folder_Create.sql | 0 .../Vault}/Stored Procedures/Folder/Folder_DeleteById.sql | 0 .../Vault}/Stored Procedures/Folder/Folder_ReadById.sql | 0 .../Vault}/Stored Procedures/Folder/Folder_ReadByUserId.sql | 0 .../dbo => dbo/Vault}/Stored Procedures/Folder/Folder_Update.sql | 0 .../Vault}/Stored Procedures/SecurityTask/SecurityTask_Create.sql | 0 .../Stored Procedures/SecurityTask/SecurityTask_CreateMany.sql | 0 .../Stored Procedures/SecurityTask/SecurityTask_ReadById.sql | 0 .../SecurityTask/SecurityTask_ReadByOrganizationIdStatus.sql | 0 .../SecurityTask/SecurityTask_ReadByUserIdStatus.sql | 0 .../Vault}/Stored Procedures/SecurityTask/SecurityTask_Update.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Tables/Cipher.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Tables/Folder.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Tables/SecurityTask.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Views/CipherView.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Views/FolderView.sql | 0 src/Sql/{Vault/dbo => dbo/Vault}/Views/SecurityTaskView.sql | 0 .../dbo/Views/NotificationStatusDetailsView.sql | 0 .../{NotificationCenter => }/dbo/Views/NotificationStatusView.sql | 0 src/Sql/{NotificationCenter => }/dbo/Views/NotificationView.sql | 0 178 files changed, 0 insertions(+), 0 deletions(-) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_Create.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_DeleteById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_DeleteIfExpired.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_ReadAdminApprovalsByIds.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_ReadById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_ReadByUserId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_ReadPendingByOrganizationId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_Update.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/AuthRequest_UpdateMany.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Device_ReadActiveWithPendingAuthRequestsByUserId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccessDetails_ReadByGranteeId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccessDetails_ReadByGrantorId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccessDetails_ReadByIdGrantorId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccessDetails_ReadExpiredRecoveries.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_Create.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_DeleteById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_ReadById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_ReadCountByGrantorIdEmail.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_ReadToNotify.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/EmergencyAccess_Update.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_Delete.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_DeleteByKey.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_DeleteExpired.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_Read.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_ReadByKey.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/Grant_Save.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_Create.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_DeleteById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_ReadById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_ReadByIdentifier.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_ReadByOrganizationId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_ReadManyByNotBeforeRevisionDate.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoConfig_Update.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_Create.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_Delete.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_DeleteById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_DeleteMany.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_ReadById.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_ReadByUserIdOrganizationId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/SsoUser_Update.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Stored Procedures/User_BumpAccountRevisionDateByEmergencyAccessGranteeId.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Tables/AuthRequest.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Tables/EmergencyAccess.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Tables/Grant.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Tables/SsoConfig.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Tables/SsoUser.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Views/AuthRequestView.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Views/EmergencyAccessDetailsView.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Views/GrantView.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Views/SsoConfigView.sql (100%) rename src/Sql/{Auth/dbo => dbo/Auth}/Views/SsoUserView.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ClientOrganizationMigrationRecord_Create.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ClientOrganizationMigrationRecord_DeleteById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ClientOrganizationMigrationRecord_ReadById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ClientOrganizationMigrationRecord_ReadByOrganizationId.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ClientOrganizationMigrationRecord_ReadByProviderId.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ClientOrganizationMigrationRecord_Update.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/OrganizationInstallation_Create.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/OrganizationInstallation_DeleteById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/OrganizationInstallation_ReadById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/OrganizationInstallation_ReadByInstallationId.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/OrganizationInstallation_ReadByOrganizationId.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/OrganizationInstallation_Update.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderInvoiceItem_Create.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderInvoiceItem_DeleteById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderInvoiceItem_ReadById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderInvoiceItem_ReadByInvoiceId.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderInvoiceItem_ReadByProviderId.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderInvoiceItem_Update.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderPlan_Create.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderPlan_DeleteById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderPlan_ReadById.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderPlan_ReadByProviderId.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Stored Procedures/ProviderPlan_Update.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Tables/ClientOrganizationMigrationRecord.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Tables/OrganizationInstallation.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Tables/ProviderInvoiceItem.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Tables/ProviderPlan.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Views/ClientOrganizationMigrationRecordView.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Views/OrganizationInstallationView.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Views/ProviderInvoiceItemView.sql (100%) rename src/Sql/{Billing/dbo => dbo/Billing}/Views/ProviderPlanView.sql (100%) rename src/Sql/{KeyManagement/dbo => dbo/KeyManagement}/Stored Procedures/UserAsymmetricKeys_Regenerate.sql (100%) rename src/Sql/{Platform/dbo => dbo/Platform}/Stored Procedures/Installation_Create.sql (100%) rename src/Sql/{Platform/dbo => dbo/Platform}/Stored Procedures/Installation_DeleteById.sql (100%) rename src/Sql/{Platform/dbo => dbo/Platform}/Stored Procedures/Installation_ReadById.sql (100%) rename src/Sql/{Platform/dbo => dbo/Platform}/Stored Procedures/Installation_Update.sql (100%) rename src/Sql/{Platform/dbo => dbo/Platform}/Tables/Installation.sql (100%) rename src/Sql/{Platform/dbo => dbo/Platform}/Views/InstallationView.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Stored Procedures/ApiKey/ApiKey_Create.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Stored Procedures/ApiKey/ApiKey_DeleteByIds.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Stored Procedures/Event/Event_ReadPageByOrganizationIdServiceAccountId.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Tables/AccessPolicy.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Tables/ApiKey.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Tables/Project.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Tables/ProjectSecret.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Tables/Secret.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Tables/ServiceAccount.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Views/ApiKeyDetailsView.sql (100%) rename src/Sql/{SecretsManager/dbo => dbo/SecretsManager}/Views/ApiKeyView.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Stored Procedures/NotificationStatus_Create.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Stored Procedures/NotificationStatus_ReadByNotificationIdAndUserId.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Stored Procedures/NotificationStatus_Update.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Stored Procedures/Notification_Create.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Stored Procedures/Notification_ReadById.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Stored Procedures/Notification_ReadByUserIdAndStatus.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Stored Procedures/Notification_Update.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Tables/Notification.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Tables/NotificationStatus.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Stored Procedures/Send_Create.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Stored Procedures/Send_DeleteById.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Stored Procedures/Send_ReadByDeletionDateBefore.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Stored Procedures/Send_ReadById.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Stored Procedures/Send_ReadByUserId.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Stored Procedures/Send_Update.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Tables/Send.sql (100%) rename src/Sql/{Tools/dbo => dbo/Tools}/Views/SendView.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Functions/CipherDetails.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Functions/UserCipherDetails.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherDetails_Create.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherDetails_CreateWithCollections.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherDetails_ReadByIdUserId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherDetails_ReadByUserId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherDetails_ReadWithoutOrganizationsByUserId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherDetails_Update.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherOrganizationDetails_ReadById.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherOrganizationDetails_ReadByOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherOrganizationDetails_ReadUnassignedByOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/CipherOrganizationPermissions_GetManyByOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Create.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_CreateWithCollections.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Delete.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_DeleteAttachment.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_DeleteById.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_DeleteByIdsOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_DeleteByOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_DeleteByUserId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_DeleteDeleted.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Move.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_ReadById.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_ReadByOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_ReadCanEditByIdUserId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Restore.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_RestoreByIdsOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_SoftDelete.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_SoftDeleteByIdsOrganizationId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_Update.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_UpdateAttachment.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_UpdateCollections.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_UpdatePartial.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/Cipher_UpdateWithCollections.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Cipher/UserSecurityTasks_GetManyByCipherIds.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/CollectionCipher/CollectionCipher_AddCollectionsForManyCiphers.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/CollectionCipher/CollectionCipher_RemoveCollectionsFromManyCiphers.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Folder/Folder_Create.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Folder/Folder_DeleteById.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Folder/Folder_ReadById.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Folder/Folder_ReadByUserId.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/Folder/Folder_Update.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/SecurityTask/SecurityTask_Create.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/SecurityTask/SecurityTask_CreateMany.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/SecurityTask/SecurityTask_ReadById.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/SecurityTask/SecurityTask_ReadByOrganizationIdStatus.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/SecurityTask/SecurityTask_ReadByUserIdStatus.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Stored Procedures/SecurityTask/SecurityTask_Update.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Tables/Cipher.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Tables/Folder.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Tables/SecurityTask.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Views/CipherView.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Views/FolderView.sql (100%) rename src/Sql/{Vault/dbo => dbo/Vault}/Views/SecurityTaskView.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Views/NotificationStatusDetailsView.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Views/NotificationStatusView.sql (100%) rename src/Sql/{NotificationCenter => }/dbo/Views/NotificationView.sql (100%) diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_Create.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_Create.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_Create.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_Create.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_DeleteById.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_DeleteById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_DeleteById.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_DeleteById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_DeleteIfExpired.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_DeleteIfExpired.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_DeleteIfExpired.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_DeleteIfExpired.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadAdminApprovalsByIds.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadAdminApprovalsByIds.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadAdminApprovalsByIds.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadAdminApprovalsByIds.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadById.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadById.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadByUserId.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadByUserId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadByUserId.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadByUserId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadPendingByOrganizationId.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadPendingByOrganizationId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_ReadPendingByOrganizationId.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_ReadPendingByOrganizationId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_Update.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_Update.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_Update.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_Update.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/AuthRequest_UpdateMany.sql b/src/Sql/dbo/Auth/Stored Procedures/AuthRequest_UpdateMany.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/AuthRequest_UpdateMany.sql rename to src/Sql/dbo/Auth/Stored Procedures/AuthRequest_UpdateMany.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/Device_ReadActiveWithPendingAuthRequestsByUserId.sql b/src/Sql/dbo/Auth/Stored Procedures/Device_ReadActiveWithPendingAuthRequestsByUserId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/Device_ReadActiveWithPendingAuthRequestsByUserId.sql rename to src/Sql/dbo/Auth/Stored Procedures/Device_ReadActiveWithPendingAuthRequestsByUserId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadByGranteeId.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadByGranteeId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadByGranteeId.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadByGranteeId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadByGrantorId.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadByGrantorId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadByGrantorId.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadByGrantorId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadByIdGrantorId.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadByIdGrantorId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadByIdGrantorId.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadByIdGrantorId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadExpiredRecoveries.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadExpiredRecoveries.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccessDetails_ReadExpiredRecoveries.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccessDetails_ReadExpiredRecoveries.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_Create.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_Create.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_Create.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_Create.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_DeleteById.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_DeleteById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_DeleteById.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_DeleteById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_ReadById.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_ReadById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_ReadById.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_ReadById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_ReadCountByGrantorIdEmail.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_ReadCountByGrantorIdEmail.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_ReadCountByGrantorIdEmail.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_ReadCountByGrantorIdEmail.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_ReadToNotify.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_ReadToNotify.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_ReadToNotify.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_ReadToNotify.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_Update.sql b/src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_Update.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/EmergencyAccess_Update.sql rename to src/Sql/dbo/Auth/Stored Procedures/EmergencyAccess_Update.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/Grant_Delete.sql b/src/Sql/dbo/Auth/Stored Procedures/Grant_Delete.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/Grant_Delete.sql rename to src/Sql/dbo/Auth/Stored Procedures/Grant_Delete.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/Grant_DeleteByKey.sql b/src/Sql/dbo/Auth/Stored Procedures/Grant_DeleteByKey.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/Grant_DeleteByKey.sql rename to src/Sql/dbo/Auth/Stored Procedures/Grant_DeleteByKey.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/Grant_DeleteExpired.sql b/src/Sql/dbo/Auth/Stored Procedures/Grant_DeleteExpired.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/Grant_DeleteExpired.sql rename to src/Sql/dbo/Auth/Stored Procedures/Grant_DeleteExpired.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/Grant_Read.sql b/src/Sql/dbo/Auth/Stored Procedures/Grant_Read.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/Grant_Read.sql rename to src/Sql/dbo/Auth/Stored Procedures/Grant_Read.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/Grant_ReadByKey.sql b/src/Sql/dbo/Auth/Stored Procedures/Grant_ReadByKey.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/Grant_ReadByKey.sql rename to src/Sql/dbo/Auth/Stored Procedures/Grant_ReadByKey.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/Grant_Save.sql b/src/Sql/dbo/Auth/Stored Procedures/Grant_Save.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/Grant_Save.sql rename to src/Sql/dbo/Auth/Stored Procedures/Grant_Save.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoConfig_Create.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoConfig_Create.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoConfig_Create.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoConfig_Create.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoConfig_DeleteById.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoConfig_DeleteById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoConfig_DeleteById.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoConfig_DeleteById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadById.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadById.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadByIdentifier.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadByIdentifier.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadByIdentifier.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadByIdentifier.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadByOrganizationId.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadByOrganizationId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadByOrganizationId.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadByOrganizationId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadManyByNotBeforeRevisionDate.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadManyByNotBeforeRevisionDate.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoConfig_ReadManyByNotBeforeRevisionDate.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoConfig_ReadManyByNotBeforeRevisionDate.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoConfig_Update.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoConfig_Update.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoConfig_Update.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoConfig_Update.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoUser_Create.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoUser_Create.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoUser_Create.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoUser_Create.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoUser_Delete.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoUser_Delete.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoUser_Delete.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoUser_Delete.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoUser_DeleteById.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoUser_DeleteById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoUser_DeleteById.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoUser_DeleteById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoUser_DeleteMany.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoUser_DeleteMany.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoUser_DeleteMany.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoUser_DeleteMany.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoUser_ReadById.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoUser_ReadById.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoUser_ReadById.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoUser_ReadById.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoUser_ReadByUserIdOrganizationId.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoUser_ReadByUserIdOrganizationId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoUser_ReadByUserIdOrganizationId.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoUser_ReadByUserIdOrganizationId.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/SsoUser_Update.sql b/src/Sql/dbo/Auth/Stored Procedures/SsoUser_Update.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/SsoUser_Update.sql rename to src/Sql/dbo/Auth/Stored Procedures/SsoUser_Update.sql diff --git a/src/Sql/Auth/dbo/Stored Procedures/User_BumpAccountRevisionDateByEmergencyAccessGranteeId.sql b/src/Sql/dbo/Auth/Stored Procedures/User_BumpAccountRevisionDateByEmergencyAccessGranteeId.sql similarity index 100% rename from src/Sql/Auth/dbo/Stored Procedures/User_BumpAccountRevisionDateByEmergencyAccessGranteeId.sql rename to src/Sql/dbo/Auth/Stored Procedures/User_BumpAccountRevisionDateByEmergencyAccessGranteeId.sql diff --git a/src/Sql/Auth/dbo/Tables/AuthRequest.sql b/src/Sql/dbo/Auth/Tables/AuthRequest.sql similarity index 100% rename from src/Sql/Auth/dbo/Tables/AuthRequest.sql rename to src/Sql/dbo/Auth/Tables/AuthRequest.sql diff --git a/src/Sql/Auth/dbo/Tables/EmergencyAccess.sql b/src/Sql/dbo/Auth/Tables/EmergencyAccess.sql similarity index 100% rename from src/Sql/Auth/dbo/Tables/EmergencyAccess.sql rename to src/Sql/dbo/Auth/Tables/EmergencyAccess.sql diff --git a/src/Sql/Auth/dbo/Tables/Grant.sql b/src/Sql/dbo/Auth/Tables/Grant.sql similarity index 100% rename from src/Sql/Auth/dbo/Tables/Grant.sql rename to src/Sql/dbo/Auth/Tables/Grant.sql diff --git a/src/Sql/Auth/dbo/Tables/SsoConfig.sql b/src/Sql/dbo/Auth/Tables/SsoConfig.sql similarity index 100% rename from src/Sql/Auth/dbo/Tables/SsoConfig.sql rename to src/Sql/dbo/Auth/Tables/SsoConfig.sql diff --git a/src/Sql/Auth/dbo/Tables/SsoUser.sql b/src/Sql/dbo/Auth/Tables/SsoUser.sql similarity index 100% rename from src/Sql/Auth/dbo/Tables/SsoUser.sql rename to src/Sql/dbo/Auth/Tables/SsoUser.sql diff --git a/src/Sql/Auth/dbo/Views/AuthRequestView.sql b/src/Sql/dbo/Auth/Views/AuthRequestView.sql similarity index 100% rename from src/Sql/Auth/dbo/Views/AuthRequestView.sql rename to src/Sql/dbo/Auth/Views/AuthRequestView.sql diff --git a/src/Sql/Auth/dbo/Views/EmergencyAccessDetailsView.sql b/src/Sql/dbo/Auth/Views/EmergencyAccessDetailsView.sql similarity index 100% rename from src/Sql/Auth/dbo/Views/EmergencyAccessDetailsView.sql rename to src/Sql/dbo/Auth/Views/EmergencyAccessDetailsView.sql diff --git a/src/Sql/Auth/dbo/Views/GrantView.sql b/src/Sql/dbo/Auth/Views/GrantView.sql similarity index 100% rename from src/Sql/Auth/dbo/Views/GrantView.sql rename to src/Sql/dbo/Auth/Views/GrantView.sql diff --git a/src/Sql/Auth/dbo/Views/SsoConfigView.sql b/src/Sql/dbo/Auth/Views/SsoConfigView.sql similarity index 100% rename from src/Sql/Auth/dbo/Views/SsoConfigView.sql rename to src/Sql/dbo/Auth/Views/SsoConfigView.sql diff --git a/src/Sql/Auth/dbo/Views/SsoUserView.sql b/src/Sql/dbo/Auth/Views/SsoUserView.sql similarity index 100% rename from src/Sql/Auth/dbo/Views/SsoUserView.sql rename to src/Sql/dbo/Auth/Views/SsoUserView.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_Create.sql b/src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_Create.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_Create.sql rename to src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_Create.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_DeleteById.sql b/src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_DeleteById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_DeleteById.sql rename to src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_DeleteById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_ReadById.sql b/src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_ReadById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_ReadById.sql rename to src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_ReadById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_ReadByOrganizationId.sql b/src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_ReadByOrganizationId.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_ReadByOrganizationId.sql rename to src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_ReadByOrganizationId.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_ReadByProviderId.sql b/src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_ReadByProviderId.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_ReadByProviderId.sql rename to src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_ReadByProviderId.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_Update.sql b/src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_Update.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ClientOrganizationMigrationRecord_Update.sql rename to src/Sql/dbo/Billing/Stored Procedures/ClientOrganizationMigrationRecord_Update.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_Create.sql b/src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_Create.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_Create.sql rename to src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_Create.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_DeleteById.sql b/src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_DeleteById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_DeleteById.sql rename to src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_DeleteById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_ReadById.sql b/src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_ReadById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_ReadById.sql rename to src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_ReadById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_ReadByInstallationId.sql b/src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_ReadByInstallationId.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_ReadByInstallationId.sql rename to src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_ReadByInstallationId.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_ReadByOrganizationId.sql b/src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_ReadByOrganizationId.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_ReadByOrganizationId.sql rename to src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_ReadByOrganizationId.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_Update.sql b/src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_Update.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/OrganizationInstallation_Update.sql rename to src/Sql/dbo/Billing/Stored Procedures/OrganizationInstallation_Update.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_Create.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_Create.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_Create.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_Create.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_DeleteById.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_DeleteById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_DeleteById.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_DeleteById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_ReadById.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_ReadById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_ReadById.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_ReadById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_ReadByInvoiceId.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_ReadByInvoiceId.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_ReadByInvoiceId.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_ReadByInvoiceId.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_ReadByProviderId.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_ReadByProviderId.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_ReadByProviderId.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_ReadByProviderId.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_Update.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_Update.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderInvoiceItem_Update.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderInvoiceItem_Update.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_Create.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_Create.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_Create.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_Create.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_DeleteById.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_DeleteById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_DeleteById.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_DeleteById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_ReadById.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_ReadById.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_ReadById.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_ReadById.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_ReadByProviderId.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_ReadByProviderId.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_ReadByProviderId.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_ReadByProviderId.sql diff --git a/src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_Update.sql b/src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_Update.sql similarity index 100% rename from src/Sql/Billing/dbo/Stored Procedures/ProviderPlan_Update.sql rename to src/Sql/dbo/Billing/Stored Procedures/ProviderPlan_Update.sql diff --git a/src/Sql/Billing/dbo/Tables/ClientOrganizationMigrationRecord.sql b/src/Sql/dbo/Billing/Tables/ClientOrganizationMigrationRecord.sql similarity index 100% rename from src/Sql/Billing/dbo/Tables/ClientOrganizationMigrationRecord.sql rename to src/Sql/dbo/Billing/Tables/ClientOrganizationMigrationRecord.sql diff --git a/src/Sql/Billing/dbo/Tables/OrganizationInstallation.sql b/src/Sql/dbo/Billing/Tables/OrganizationInstallation.sql similarity index 100% rename from src/Sql/Billing/dbo/Tables/OrganizationInstallation.sql rename to src/Sql/dbo/Billing/Tables/OrganizationInstallation.sql diff --git a/src/Sql/Billing/dbo/Tables/ProviderInvoiceItem.sql b/src/Sql/dbo/Billing/Tables/ProviderInvoiceItem.sql similarity index 100% rename from src/Sql/Billing/dbo/Tables/ProviderInvoiceItem.sql rename to src/Sql/dbo/Billing/Tables/ProviderInvoiceItem.sql diff --git a/src/Sql/Billing/dbo/Tables/ProviderPlan.sql b/src/Sql/dbo/Billing/Tables/ProviderPlan.sql similarity index 100% rename from src/Sql/Billing/dbo/Tables/ProviderPlan.sql rename to src/Sql/dbo/Billing/Tables/ProviderPlan.sql diff --git a/src/Sql/Billing/dbo/Views/ClientOrganizationMigrationRecordView.sql b/src/Sql/dbo/Billing/Views/ClientOrganizationMigrationRecordView.sql similarity index 100% rename from src/Sql/Billing/dbo/Views/ClientOrganizationMigrationRecordView.sql rename to src/Sql/dbo/Billing/Views/ClientOrganizationMigrationRecordView.sql diff --git a/src/Sql/Billing/dbo/Views/OrganizationInstallationView.sql b/src/Sql/dbo/Billing/Views/OrganizationInstallationView.sql similarity index 100% rename from src/Sql/Billing/dbo/Views/OrganizationInstallationView.sql rename to src/Sql/dbo/Billing/Views/OrganizationInstallationView.sql diff --git a/src/Sql/Billing/dbo/Views/ProviderInvoiceItemView.sql b/src/Sql/dbo/Billing/Views/ProviderInvoiceItemView.sql similarity index 100% rename from src/Sql/Billing/dbo/Views/ProviderInvoiceItemView.sql rename to src/Sql/dbo/Billing/Views/ProviderInvoiceItemView.sql diff --git a/src/Sql/Billing/dbo/Views/ProviderPlanView.sql b/src/Sql/dbo/Billing/Views/ProviderPlanView.sql similarity index 100% rename from src/Sql/Billing/dbo/Views/ProviderPlanView.sql rename to src/Sql/dbo/Billing/Views/ProviderPlanView.sql diff --git a/src/Sql/KeyManagement/dbo/Stored Procedures/UserAsymmetricKeys_Regenerate.sql b/src/Sql/dbo/KeyManagement/Stored Procedures/UserAsymmetricKeys_Regenerate.sql similarity index 100% rename from src/Sql/KeyManagement/dbo/Stored Procedures/UserAsymmetricKeys_Regenerate.sql rename to src/Sql/dbo/KeyManagement/Stored Procedures/UserAsymmetricKeys_Regenerate.sql diff --git a/src/Sql/Platform/dbo/Stored Procedures/Installation_Create.sql b/src/Sql/dbo/Platform/Stored Procedures/Installation_Create.sql similarity index 100% rename from src/Sql/Platform/dbo/Stored Procedures/Installation_Create.sql rename to src/Sql/dbo/Platform/Stored Procedures/Installation_Create.sql diff --git a/src/Sql/Platform/dbo/Stored Procedures/Installation_DeleteById.sql b/src/Sql/dbo/Platform/Stored Procedures/Installation_DeleteById.sql similarity index 100% rename from src/Sql/Platform/dbo/Stored Procedures/Installation_DeleteById.sql rename to src/Sql/dbo/Platform/Stored Procedures/Installation_DeleteById.sql diff --git a/src/Sql/Platform/dbo/Stored Procedures/Installation_ReadById.sql b/src/Sql/dbo/Platform/Stored Procedures/Installation_ReadById.sql similarity index 100% rename from src/Sql/Platform/dbo/Stored Procedures/Installation_ReadById.sql rename to src/Sql/dbo/Platform/Stored Procedures/Installation_ReadById.sql diff --git a/src/Sql/Platform/dbo/Stored Procedures/Installation_Update.sql b/src/Sql/dbo/Platform/Stored Procedures/Installation_Update.sql similarity index 100% rename from src/Sql/Platform/dbo/Stored Procedures/Installation_Update.sql rename to src/Sql/dbo/Platform/Stored Procedures/Installation_Update.sql diff --git a/src/Sql/Platform/dbo/Tables/Installation.sql b/src/Sql/dbo/Platform/Tables/Installation.sql similarity index 100% rename from src/Sql/Platform/dbo/Tables/Installation.sql rename to src/Sql/dbo/Platform/Tables/Installation.sql diff --git a/src/Sql/Platform/dbo/Views/InstallationView.sql b/src/Sql/dbo/Platform/Views/InstallationView.sql similarity index 100% rename from src/Sql/Platform/dbo/Views/InstallationView.sql rename to src/Sql/dbo/Platform/Views/InstallationView.sql diff --git a/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql b/src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql rename to src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql diff --git a/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql b/src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKey_Create.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql rename to src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKey_Create.sql diff --git a/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_DeleteByIds.sql b/src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKey_DeleteByIds.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_DeleteByIds.sql rename to src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKey_DeleteByIds.sql diff --git a/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql b/src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql rename to src/Sql/dbo/SecretsManager/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql diff --git a/src/Sql/SecretsManager/dbo/Stored Procedures/Event/Event_ReadPageByOrganizationIdServiceAccountId.sql b/src/Sql/dbo/SecretsManager/Stored Procedures/Event/Event_ReadPageByOrganizationIdServiceAccountId.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Stored Procedures/Event/Event_ReadPageByOrganizationIdServiceAccountId.sql rename to src/Sql/dbo/SecretsManager/Stored Procedures/Event/Event_ReadPageByOrganizationIdServiceAccountId.sql diff --git a/src/Sql/SecretsManager/dbo/Tables/AccessPolicy.sql b/src/Sql/dbo/SecretsManager/Tables/AccessPolicy.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Tables/AccessPolicy.sql rename to src/Sql/dbo/SecretsManager/Tables/AccessPolicy.sql diff --git a/src/Sql/SecretsManager/dbo/Tables/ApiKey.sql b/src/Sql/dbo/SecretsManager/Tables/ApiKey.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Tables/ApiKey.sql rename to src/Sql/dbo/SecretsManager/Tables/ApiKey.sql diff --git a/src/Sql/SecretsManager/dbo/Tables/Project.sql b/src/Sql/dbo/SecretsManager/Tables/Project.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Tables/Project.sql rename to src/Sql/dbo/SecretsManager/Tables/Project.sql diff --git a/src/Sql/SecretsManager/dbo/Tables/ProjectSecret.sql b/src/Sql/dbo/SecretsManager/Tables/ProjectSecret.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Tables/ProjectSecret.sql rename to src/Sql/dbo/SecretsManager/Tables/ProjectSecret.sql diff --git a/src/Sql/SecretsManager/dbo/Tables/Secret.sql b/src/Sql/dbo/SecretsManager/Tables/Secret.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Tables/Secret.sql rename to src/Sql/dbo/SecretsManager/Tables/Secret.sql diff --git a/src/Sql/SecretsManager/dbo/Tables/ServiceAccount.sql b/src/Sql/dbo/SecretsManager/Tables/ServiceAccount.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Tables/ServiceAccount.sql rename to src/Sql/dbo/SecretsManager/Tables/ServiceAccount.sql diff --git a/src/Sql/SecretsManager/dbo/Views/ApiKeyDetailsView.sql b/src/Sql/dbo/SecretsManager/Views/ApiKeyDetailsView.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Views/ApiKeyDetailsView.sql rename to src/Sql/dbo/SecretsManager/Views/ApiKeyDetailsView.sql diff --git a/src/Sql/SecretsManager/dbo/Views/ApiKeyView.sql b/src/Sql/dbo/SecretsManager/Views/ApiKeyView.sql similarity index 100% rename from src/Sql/SecretsManager/dbo/Views/ApiKeyView.sql rename to src/Sql/dbo/SecretsManager/Views/ApiKeyView.sql diff --git a/src/Sql/NotificationCenter/dbo/Stored Procedures/NotificationStatus_Create.sql b/src/Sql/dbo/Stored Procedures/NotificationStatus_Create.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Stored Procedures/NotificationStatus_Create.sql rename to src/Sql/dbo/Stored Procedures/NotificationStatus_Create.sql diff --git a/src/Sql/NotificationCenter/dbo/Stored Procedures/NotificationStatus_ReadByNotificationIdAndUserId.sql b/src/Sql/dbo/Stored Procedures/NotificationStatus_ReadByNotificationIdAndUserId.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Stored Procedures/NotificationStatus_ReadByNotificationIdAndUserId.sql rename to src/Sql/dbo/Stored Procedures/NotificationStatus_ReadByNotificationIdAndUserId.sql diff --git a/src/Sql/NotificationCenter/dbo/Stored Procedures/NotificationStatus_Update.sql b/src/Sql/dbo/Stored Procedures/NotificationStatus_Update.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Stored Procedures/NotificationStatus_Update.sql rename to src/Sql/dbo/Stored Procedures/NotificationStatus_Update.sql diff --git a/src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_Create.sql b/src/Sql/dbo/Stored Procedures/Notification_Create.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_Create.sql rename to src/Sql/dbo/Stored Procedures/Notification_Create.sql diff --git a/src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_ReadById.sql b/src/Sql/dbo/Stored Procedures/Notification_ReadById.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_ReadById.sql rename to src/Sql/dbo/Stored Procedures/Notification_ReadById.sql diff --git a/src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_ReadByUserIdAndStatus.sql b/src/Sql/dbo/Stored Procedures/Notification_ReadByUserIdAndStatus.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_ReadByUserIdAndStatus.sql rename to src/Sql/dbo/Stored Procedures/Notification_ReadByUserIdAndStatus.sql diff --git a/src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_Update.sql b/src/Sql/dbo/Stored Procedures/Notification_Update.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Stored Procedures/Notification_Update.sql rename to src/Sql/dbo/Stored Procedures/Notification_Update.sql diff --git a/src/Sql/NotificationCenter/dbo/Tables/Notification.sql b/src/Sql/dbo/Tables/Notification.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Tables/Notification.sql rename to src/Sql/dbo/Tables/Notification.sql diff --git a/src/Sql/NotificationCenter/dbo/Tables/NotificationStatus.sql b/src/Sql/dbo/Tables/NotificationStatus.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Tables/NotificationStatus.sql rename to src/Sql/dbo/Tables/NotificationStatus.sql diff --git a/src/Sql/Tools/dbo/Stored Procedures/Send_Create.sql b/src/Sql/dbo/Tools/Stored Procedures/Send_Create.sql similarity index 100% rename from src/Sql/Tools/dbo/Stored Procedures/Send_Create.sql rename to src/Sql/dbo/Tools/Stored Procedures/Send_Create.sql diff --git a/src/Sql/Tools/dbo/Stored Procedures/Send_DeleteById.sql b/src/Sql/dbo/Tools/Stored Procedures/Send_DeleteById.sql similarity index 100% rename from src/Sql/Tools/dbo/Stored Procedures/Send_DeleteById.sql rename to src/Sql/dbo/Tools/Stored Procedures/Send_DeleteById.sql diff --git a/src/Sql/Tools/dbo/Stored Procedures/Send_ReadByDeletionDateBefore.sql b/src/Sql/dbo/Tools/Stored Procedures/Send_ReadByDeletionDateBefore.sql similarity index 100% rename from src/Sql/Tools/dbo/Stored Procedures/Send_ReadByDeletionDateBefore.sql rename to src/Sql/dbo/Tools/Stored Procedures/Send_ReadByDeletionDateBefore.sql diff --git a/src/Sql/Tools/dbo/Stored Procedures/Send_ReadById.sql b/src/Sql/dbo/Tools/Stored Procedures/Send_ReadById.sql similarity index 100% rename from src/Sql/Tools/dbo/Stored Procedures/Send_ReadById.sql rename to src/Sql/dbo/Tools/Stored Procedures/Send_ReadById.sql diff --git a/src/Sql/Tools/dbo/Stored Procedures/Send_ReadByUserId.sql b/src/Sql/dbo/Tools/Stored Procedures/Send_ReadByUserId.sql similarity index 100% rename from src/Sql/Tools/dbo/Stored Procedures/Send_ReadByUserId.sql rename to src/Sql/dbo/Tools/Stored Procedures/Send_ReadByUserId.sql diff --git a/src/Sql/Tools/dbo/Stored Procedures/Send_Update.sql b/src/Sql/dbo/Tools/Stored Procedures/Send_Update.sql similarity index 100% rename from src/Sql/Tools/dbo/Stored Procedures/Send_Update.sql rename to src/Sql/dbo/Tools/Stored Procedures/Send_Update.sql diff --git a/src/Sql/Tools/dbo/Tables/Send.sql b/src/Sql/dbo/Tools/Tables/Send.sql similarity index 100% rename from src/Sql/Tools/dbo/Tables/Send.sql rename to src/Sql/dbo/Tools/Tables/Send.sql diff --git a/src/Sql/Tools/dbo/Views/SendView.sql b/src/Sql/dbo/Tools/Views/SendView.sql similarity index 100% rename from src/Sql/Tools/dbo/Views/SendView.sql rename to src/Sql/dbo/Tools/Views/SendView.sql diff --git a/src/Sql/Vault/dbo/Functions/CipherDetails.sql b/src/Sql/dbo/Vault/Functions/CipherDetails.sql similarity index 100% rename from src/Sql/Vault/dbo/Functions/CipherDetails.sql rename to src/Sql/dbo/Vault/Functions/CipherDetails.sql diff --git a/src/Sql/Vault/dbo/Functions/UserCipherDetails.sql b/src/Sql/dbo/Vault/Functions/UserCipherDetails.sql similarity index 100% rename from src/Sql/Vault/dbo/Functions/UserCipherDetails.sql rename to src/Sql/dbo/Vault/Functions/UserCipherDetails.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_Create.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_Create.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_Create.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_Create.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_CreateWithCollections.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_CreateWithCollections.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_CreateWithCollections.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_CreateWithCollections.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_ReadByIdUserId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_ReadByIdUserId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_ReadByIdUserId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_ReadByIdUserId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_ReadByUserId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_ReadByUserId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_ReadByUserId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_ReadByUserId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_ReadWithoutOrganizationsByUserId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_ReadWithoutOrganizationsByUserId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_ReadWithoutOrganizationsByUserId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_ReadWithoutOrganizationsByUserId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_Update.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_Update.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherDetails_Update.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherDetails_Update.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationDetails_ReadById.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationDetails_ReadById.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationDetails_ReadById.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationDetails_ReadById.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationDetails_ReadByOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationDetails_ReadByOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationDetails_ReadByOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationDetails_ReadByOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationDetails_ReadUnassignedByOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationDetails_ReadUnassignedByOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationDetails_ReadUnassignedByOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationDetails_ReadUnassignedByOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationPermissions_GetManyByOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationPermissions_GetManyByOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/CipherOrganizationPermissions_GetManyByOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/CipherOrganizationPermissions_GetManyByOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Create.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Create.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Create.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Create.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_CreateWithCollections.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_CreateWithCollections.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_CreateWithCollections.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_CreateWithCollections.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Delete.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Delete.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Delete.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Delete.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteAttachment.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteAttachment.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteAttachment.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteAttachment.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteById.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteById.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteById.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteById.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteByIdsOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteByIdsOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteByIdsOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteByIdsOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteByOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteByOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteByOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteByOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteByUserId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteByUserId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteByUserId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteByUserId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteDeleted.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteDeleted.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_DeleteDeleted.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_DeleteDeleted.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Move.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Move.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Move.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Move.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_ReadById.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_ReadById.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_ReadById.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_ReadById.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_ReadByOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_ReadByOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_ReadByOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_ReadByOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_ReadCanEditByIdUserId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_ReadCanEditByIdUserId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_ReadCanEditByIdUserId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_ReadCanEditByIdUserId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Restore.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Restore.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Restore.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Restore.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_RestoreByIdsOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_RestoreByIdsOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_RestoreByIdsOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_RestoreByIdsOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_SoftDelete.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_SoftDelete.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_SoftDelete.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_SoftDelete.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_SoftDeleteByIdsOrganizationId.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_SoftDeleteByIdsOrganizationId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_SoftDeleteByIdsOrganizationId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_SoftDeleteByIdsOrganizationId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Update.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Update.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_Update.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_Update.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdateAttachment.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdateAttachment.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdateAttachment.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdateAttachment.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdateCollections.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdateCollections.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdateCollections.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdateCollections.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdatePartial.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdatePartial.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdatePartial.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdatePartial.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdateWithCollections.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdateWithCollections.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/Cipher_UpdateWithCollections.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/Cipher_UpdateWithCollections.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Cipher/UserSecurityTasks_GetManyByCipherIds.sql b/src/Sql/dbo/Vault/Stored Procedures/Cipher/UserSecurityTasks_GetManyByCipherIds.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Cipher/UserSecurityTasks_GetManyByCipherIds.sql rename to src/Sql/dbo/Vault/Stored Procedures/Cipher/UserSecurityTasks_GetManyByCipherIds.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/CollectionCipher/CollectionCipher_AddCollectionsForManyCiphers.sql b/src/Sql/dbo/Vault/Stored Procedures/CollectionCipher/CollectionCipher_AddCollectionsForManyCiphers.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/CollectionCipher/CollectionCipher_AddCollectionsForManyCiphers.sql rename to src/Sql/dbo/Vault/Stored Procedures/CollectionCipher/CollectionCipher_AddCollectionsForManyCiphers.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/CollectionCipher/CollectionCipher_RemoveCollectionsFromManyCiphers.sql b/src/Sql/dbo/Vault/Stored Procedures/CollectionCipher/CollectionCipher_RemoveCollectionsFromManyCiphers.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/CollectionCipher/CollectionCipher_RemoveCollectionsFromManyCiphers.sql rename to src/Sql/dbo/Vault/Stored Procedures/CollectionCipher/CollectionCipher_RemoveCollectionsFromManyCiphers.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql b/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql rename to src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql b/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql rename to src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_Create.sql b/src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_Create.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_Create.sql rename to src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_Create.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_DeleteById.sql b/src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_DeleteById.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_DeleteById.sql rename to src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_DeleteById.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_ReadById.sql b/src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_ReadById.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_ReadById.sql rename to src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_ReadById.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_ReadByUserId.sql b/src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_ReadByUserId.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_ReadByUserId.sql rename to src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_ReadByUserId.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_Update.sql b/src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_Update.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/Folder/Folder_Update.sql rename to src/Sql/dbo/Vault/Stored Procedures/Folder/Folder_Update.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_Create.sql b/src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_Create.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_Create.sql rename to src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_Create.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_CreateMany.sql b/src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_CreateMany.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_CreateMany.sql rename to src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_CreateMany.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_ReadById.sql b/src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_ReadById.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_ReadById.sql rename to src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_ReadById.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_ReadByOrganizationIdStatus.sql b/src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_ReadByOrganizationIdStatus.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_ReadByOrganizationIdStatus.sql rename to src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_ReadByOrganizationIdStatus.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_ReadByUserIdStatus.sql b/src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_ReadByUserIdStatus.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_ReadByUserIdStatus.sql rename to src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_ReadByUserIdStatus.sql diff --git a/src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_Update.sql b/src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_Update.sql similarity index 100% rename from src/Sql/Vault/dbo/Stored Procedures/SecurityTask/SecurityTask_Update.sql rename to src/Sql/dbo/Vault/Stored Procedures/SecurityTask/SecurityTask_Update.sql diff --git a/src/Sql/Vault/dbo/Tables/Cipher.sql b/src/Sql/dbo/Vault/Tables/Cipher.sql similarity index 100% rename from src/Sql/Vault/dbo/Tables/Cipher.sql rename to src/Sql/dbo/Vault/Tables/Cipher.sql diff --git a/src/Sql/Vault/dbo/Tables/Folder.sql b/src/Sql/dbo/Vault/Tables/Folder.sql similarity index 100% rename from src/Sql/Vault/dbo/Tables/Folder.sql rename to src/Sql/dbo/Vault/Tables/Folder.sql diff --git a/src/Sql/Vault/dbo/Tables/SecurityTask.sql b/src/Sql/dbo/Vault/Tables/SecurityTask.sql similarity index 100% rename from src/Sql/Vault/dbo/Tables/SecurityTask.sql rename to src/Sql/dbo/Vault/Tables/SecurityTask.sql diff --git a/src/Sql/Vault/dbo/Views/CipherView.sql b/src/Sql/dbo/Vault/Views/CipherView.sql similarity index 100% rename from src/Sql/Vault/dbo/Views/CipherView.sql rename to src/Sql/dbo/Vault/Views/CipherView.sql diff --git a/src/Sql/Vault/dbo/Views/FolderView.sql b/src/Sql/dbo/Vault/Views/FolderView.sql similarity index 100% rename from src/Sql/Vault/dbo/Views/FolderView.sql rename to src/Sql/dbo/Vault/Views/FolderView.sql diff --git a/src/Sql/Vault/dbo/Views/SecurityTaskView.sql b/src/Sql/dbo/Vault/Views/SecurityTaskView.sql similarity index 100% rename from src/Sql/Vault/dbo/Views/SecurityTaskView.sql rename to src/Sql/dbo/Vault/Views/SecurityTaskView.sql diff --git a/src/Sql/NotificationCenter/dbo/Views/NotificationStatusDetailsView.sql b/src/Sql/dbo/Views/NotificationStatusDetailsView.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Views/NotificationStatusDetailsView.sql rename to src/Sql/dbo/Views/NotificationStatusDetailsView.sql diff --git a/src/Sql/NotificationCenter/dbo/Views/NotificationStatusView.sql b/src/Sql/dbo/Views/NotificationStatusView.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Views/NotificationStatusView.sql rename to src/Sql/dbo/Views/NotificationStatusView.sql diff --git a/src/Sql/NotificationCenter/dbo/Views/NotificationView.sql b/src/Sql/dbo/Views/NotificationView.sql similarity index 100% rename from src/Sql/NotificationCenter/dbo/Views/NotificationView.sql rename to src/Sql/dbo/Views/NotificationView.sql From acb18c55b31d421d969edd5a0bf06267ff0efdef Mon Sep 17 00:00:00 2001 From: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com> Date: Thu, 5 Jun 2025 18:48:02 +0100 Subject: [PATCH 06/19] Resolve the error and consider the free org (#5920) --- .../Services/Implementations/OrganizationBillingService.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs index 1a89d2a7e2..0fd997fd10 100644 --- a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs +++ b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs @@ -78,13 +78,14 @@ public class OrganizationBillingService( var isEligibleForSelfHost = await IsEligibleForSelfHostAsync(organization); var isManaged = organization.Status == OrganizationStatusType.Managed; - + var orgOccupiedSeats = await organizationUserRepository.GetOccupiedSeatCountByOrganizationIdAsync(organization.Id); if (string.IsNullOrWhiteSpace(organization.GatewaySubscriptionId)) { return OrganizationMetadata.Default with { IsEligibleForSelfHost = isEligibleForSelfHost, - IsManaged = isManaged + IsManaged = isManaged, + OrganizationOccupiedSeats = orgOccupiedSeats }; } @@ -108,8 +109,6 @@ public class OrganizationBillingService( ? await stripeAdapter.InvoiceGetAsync(subscription.LatestInvoiceId, new InvoiceGetOptions()) : null; - var orgOccupiedSeats = await organizationUserRepository.GetOccupiedSeatCountByOrganizationIdAsync(organization.Id); - return new OrganizationMetadata( isEligibleForSelfHost, isManaged, From ce61a01f29c59fc3385cf1a600851653013f8d31 Mon Sep 17 00:00:00 2001 From: sneakernuts <671942+sneakernuts@users.noreply.github.com> Date: Thu, 5 Jun 2025 12:23:01 -0600 Subject: [PATCH 07/19] SRE-2299 cleanup (#5926) --- dev/setup_azurite.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/setup_azurite.ps1 b/dev/setup_azurite.ps1 index ad9808f6c3..03b92d4465 100755 --- a/dev/setup_azurite.ps1 +++ b/dev/setup_azurite.ps1 @@ -11,7 +11,7 @@ $corsRules = (@{ AllowedMethods = @("Get", "PUT"); }); $containers = "attachments", "sendfiles", "misc"; -$queues = "event", "notifications", "reference-events", "mail"; +$queues = "event", "notifications", "mail"; $tables = "event", "metadata", "installationdevice"; # End configuration From 25d5efacd8de37f3afe68ddf591bb1e910262069 Mon Sep 17 00:00:00 2001 From: aj-bw <81774843+aj-bw@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:32:40 -0400 Subject: [PATCH 08/19] set 0 when workflow is not ran (#5910) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c6b0ecd9d0..e5c5d0e7a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -598,7 +598,7 @@ jobs: uses: bitwarden/gh-actions/.github/workflows/_ephemeral_environment_manager.yml@main with: project: server - pull_request_number: ${{ github.event.number }} + pull_request_number: ${{ github.event.number || 0 }} secrets: inherit permissions: read-all From 20d3911b8015fbe9b447bcfb2a82cea3661bea16 Mon Sep 17 00:00:00 2001 From: Ben Bryant <30258875+benbryant0@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:59:57 +0100 Subject: [PATCH 09/19] [PM-22380] Enable NRT for some Core project files (#5912) * Enable NRT for Core/Jobs files * Enable NRT for Core/HostedServices files * Enable NRT for Core/Exceptions files * Enable NRT for Core/NotificationHub files --------- Co-authored-by: Bernd Schoolmann --- src/Core/Exceptions/BadRequestException.cs | 4 ++- src/Core/Exceptions/ConflictException.cs | 2 ++ src/Core/Exceptions/DnsQueryException.cs | 2 ++ src/Core/Exceptions/DomainClaimedException.cs | 2 ++ .../Exceptions/DomainVerifiedException.cs | 2 ++ .../Exceptions/DuplicateDomainException.cs | 2 ++ .../Exceptions/FeatureUnavailableException.cs | 2 ++ src/Core/Exceptions/GatewayException.cs | 4 ++- src/Core/Exceptions/InvalidEmailException.cs | 2 ++ .../InvalidGatewayCustomerIdException.cs | 2 ++ src/Core/Exceptions/NotFoundException.cs | 2 ++ .../ApplicationCacheHostedService.cs | 16 ++++++---- .../IpRateLimitSeedStartupService.cs | 2 ++ src/Core/Jobs/BaseJob.cs | 2 ++ src/Core/Jobs/BaseJobsHostedService.cs | 30 +++++++++++-------- src/Core/Jobs/JobFactory.cs | 4 ++- src/Core/Jobs/JobListener.cs | 4 ++- .../INotificationHubClientProxy.cs | 2 ++ .../NotificationHub/INotificationHubPool.cs | 2 ++ .../NotificationHubClientProxy.cs | 2 ++ .../NotificationHubConnection.cs | 22 ++++++++------ .../NotificationHub/NotificationHubPool.cs | 2 ++ .../NotificationHubPushNotificationService.cs | 2 ++ .../NotificationHubPushRegistrationService.cs | 10 ++++--- .../NotificationHub/PushRegistrationData.cs | 6 ++-- .../AccountsKeyManagementControllerTests.cs | 6 ++-- 26 files changed, 99 insertions(+), 39 deletions(-) diff --git a/src/Core/Exceptions/BadRequestException.cs b/src/Core/Exceptions/BadRequestException.cs index 042f853a57..b27bc7510f 100644 --- a/src/Core/Exceptions/BadRequestException.cs +++ b/src/Core/Exceptions/BadRequestException.cs @@ -3,6 +3,8 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; namespace Bit.Core.Exceptions; +#nullable enable + public class BadRequestException : Exception { public BadRequestException() : base() @@ -41,5 +43,5 @@ public class BadRequestException : Exception } } - public ModelStateDictionary ModelState { get; set; } + public ModelStateDictionary? ModelState { get; set; } } diff --git a/src/Core/Exceptions/ConflictException.cs b/src/Core/Exceptions/ConflictException.cs index 27b90a657f..92fcc52d7f 100644 --- a/src/Core/Exceptions/ConflictException.cs +++ b/src/Core/Exceptions/ConflictException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class ConflictException : Exception { public ConflictException() : base("Conflict.") { } diff --git a/src/Core/Exceptions/DnsQueryException.cs b/src/Core/Exceptions/DnsQueryException.cs index 57b2c56daa..e3f605dec4 100644 --- a/src/Core/Exceptions/DnsQueryException.cs +++ b/src/Core/Exceptions/DnsQueryException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class DnsQueryException : Exception { public DnsQueryException(string message) diff --git a/src/Core/Exceptions/DomainClaimedException.cs b/src/Core/Exceptions/DomainClaimedException.cs index 09ccb3d0d8..9ac6972fa1 100644 --- a/src/Core/Exceptions/DomainClaimedException.cs +++ b/src/Core/Exceptions/DomainClaimedException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class DomainClaimedException : Exception { public DomainClaimedException() diff --git a/src/Core/Exceptions/DomainVerifiedException.cs b/src/Core/Exceptions/DomainVerifiedException.cs index d3a3fd4de4..1fb704bd55 100644 --- a/src/Core/Exceptions/DomainVerifiedException.cs +++ b/src/Core/Exceptions/DomainVerifiedException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class DomainVerifiedException : Exception { public DomainVerifiedException() diff --git a/src/Core/Exceptions/DuplicateDomainException.cs b/src/Core/Exceptions/DuplicateDomainException.cs index 8d347dda55..4f61f333f5 100644 --- a/src/Core/Exceptions/DuplicateDomainException.cs +++ b/src/Core/Exceptions/DuplicateDomainException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class DuplicateDomainException : Exception { public DuplicateDomainException() diff --git a/src/Core/Exceptions/FeatureUnavailableException.cs b/src/Core/Exceptions/FeatureUnavailableException.cs index 7bea350956..80fd7d0635 100644 --- a/src/Core/Exceptions/FeatureUnavailableException.cs +++ b/src/Core/Exceptions/FeatureUnavailableException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + /// /// Exception to throw when a requested feature is not yet enabled/available for the requesting context. /// diff --git a/src/Core/Exceptions/GatewayException.cs b/src/Core/Exceptions/GatewayException.cs index 73e8cd7613..4b24c8d107 100644 --- a/src/Core/Exceptions/GatewayException.cs +++ b/src/Core/Exceptions/GatewayException.cs @@ -1,8 +1,10 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class GatewayException : Exception { - public GatewayException(string message, Exception innerException = null) + public GatewayException(string message, Exception? innerException = null) : base(message, innerException) { } } diff --git a/src/Core/Exceptions/InvalidEmailException.cs b/src/Core/Exceptions/InvalidEmailException.cs index 1f17acf62e..c38ec0ac38 100644 --- a/src/Core/Exceptions/InvalidEmailException.cs +++ b/src/Core/Exceptions/InvalidEmailException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class InvalidEmailException : Exception { public InvalidEmailException() diff --git a/src/Core/Exceptions/InvalidGatewayCustomerIdException.cs b/src/Core/Exceptions/InvalidGatewayCustomerIdException.cs index cfc7c56c1c..6ec15da308 100644 --- a/src/Core/Exceptions/InvalidGatewayCustomerIdException.cs +++ b/src/Core/Exceptions/InvalidGatewayCustomerIdException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class InvalidGatewayCustomerIdException : Exception { public InvalidGatewayCustomerIdException() diff --git a/src/Core/Exceptions/NotFoundException.cs b/src/Core/Exceptions/NotFoundException.cs index 70769d41ed..6a61e35868 100644 --- a/src/Core/Exceptions/NotFoundException.cs +++ b/src/Core/Exceptions/NotFoundException.cs @@ -1,5 +1,7 @@ namespace Bit.Core.Exceptions; +#nullable enable + public class NotFoundException : Exception { public NotFoundException() : base() diff --git a/src/Core/HostedServices/ApplicationCacheHostedService.cs b/src/Core/HostedServices/ApplicationCacheHostedService.cs index 9021782d20..a699a26fcc 100644 --- a/src/Core/HostedServices/ApplicationCacheHostedService.cs +++ b/src/Core/HostedServices/ApplicationCacheHostedService.cs @@ -10,9 +10,11 @@ using Microsoft.Extensions.Logging; namespace Bit.Core.HostedServices; +#nullable enable + public class ApplicationCacheHostedService : IHostedService, IDisposable { - private readonly InMemoryServiceBusApplicationCacheService _applicationCacheService; + private readonly InMemoryServiceBusApplicationCacheService? _applicationCacheService; private readonly IOrganizationRepository _organizationRepository; protected readonly ILogger _logger; private readonly ServiceBusClient _serviceBusClient; @@ -20,8 +22,8 @@ public class ApplicationCacheHostedService : IHostedService, IDisposable private readonly ServiceBusAdministrationClient _serviceBusAdministrationClient; private readonly string _subName; private readonly string _topicName; - private CancellationTokenSource _cts; - private Task _executingTask; + private CancellationTokenSource? _cts; + private Task? _executingTask; public ApplicationCacheHostedService( @@ -67,13 +69,17 @@ public class ApplicationCacheHostedService : IHostedService, IDisposable { await _subscriptionReceiver.CloseAsync(cancellationToken); await _serviceBusClient.DisposeAsync(); - _cts.Cancel(); + _cts?.Cancel(); try { await _serviceBusAdministrationClient.DeleteSubscriptionAsync(_topicName, _subName, cancellationToken); } catch { } - await _executingTask; + + if (_executingTask != null) + { + await _executingTask; + } } public virtual void Dispose() diff --git a/src/Core/HostedServices/IpRateLimitSeedStartupService.cs b/src/Core/HostedServices/IpRateLimitSeedStartupService.cs index a6869d929c..827dd94806 100644 --- a/src/Core/HostedServices/IpRateLimitSeedStartupService.cs +++ b/src/Core/HostedServices/IpRateLimitSeedStartupService.cs @@ -3,6 +3,8 @@ using Microsoft.Extensions.Hosting; namespace Bit.Core.HostedServices; +#nullable enable + /// /// A startup service that will seed the IP rate limiting stores with any values in the /// GlobalSettings configuration. diff --git a/src/Core/Jobs/BaseJob.cs b/src/Core/Jobs/BaseJob.cs index 56c39014a7..a56045f659 100644 --- a/src/Core/Jobs/BaseJob.cs +++ b/src/Core/Jobs/BaseJob.cs @@ -3,6 +3,8 @@ using Quartz; namespace Bit.Core.Jobs; +#nullable enable + public abstract class BaseJob : IJob { protected readonly ILogger _logger; diff --git a/src/Core/Jobs/BaseJobsHostedService.cs b/src/Core/Jobs/BaseJobsHostedService.cs index 897a382a2b..2ade53c6bb 100644 --- a/src/Core/Jobs/BaseJobsHostedService.cs +++ b/src/Core/Jobs/BaseJobsHostedService.cs @@ -8,6 +8,8 @@ using Quartz.Impl.Matchers; namespace Bit.Core.Jobs; +#nullable enable + public abstract class BaseJobsHostedService : IHostedService, IDisposable { private const int MaximumJobRetries = 10; @@ -16,7 +18,7 @@ public abstract class BaseJobsHostedService : IHostedService, IDisposable private readonly ILogger _listenerLogger; protected readonly ILogger _logger; - private IScheduler _scheduler; + private IScheduler? _scheduler; protected GlobalSettings _globalSettings; public BaseJobsHostedService( @@ -31,7 +33,7 @@ public abstract class BaseJobsHostedService : IHostedService, IDisposable _globalSettings = globalSettings; } - public IEnumerable> Jobs { get; protected set; } + public IEnumerable>? Jobs { get; protected set; } public virtual async Task StartAsync(CancellationToken cancellationToken) { @@ -61,10 +63,19 @@ public abstract class BaseJobsHostedService : IHostedService, IDisposable _scheduler.ListenerManager.AddJobListener(new JobListener(_listenerLogger), GroupMatcher.AnyGroup()); await _scheduler.Start(cancellationToken); + + var jobKeys = new List(); + var triggerKeys = new List(); + if (Jobs != null) { foreach (var (job, trigger) in Jobs) { + jobKeys.Add(JobBuilder.Create(job) + .WithIdentity(job.FullName!) + .Build().Key); + triggerKeys.Add(trigger.Key); + for (var retry = 0; retry < MaximumJobRetries; retry++) { // There's a race condition when starting multiple containers simultaneously, retry until it succeeds.. @@ -77,7 +88,7 @@ public abstract class BaseJobsHostedService : IHostedService, IDisposable } var jobDetail = JobBuilder.Create(job) - .WithIdentity(job.FullName) + .WithIdentity(job.FullName!) .Build(); var dupeJ = await _scheduler.GetJobDetail(jobDetail.Key); @@ -106,13 +117,6 @@ public abstract class BaseJobsHostedService : IHostedService, IDisposable // Delete old Jobs and Triggers var existingJobKeys = await _scheduler.GetJobKeys(GroupMatcher.AnyGroup()); - var jobKeys = Jobs.Select(j => - { - var job = j.Item1; - return JobBuilder.Create(job) - .WithIdentity(job.FullName) - .Build().Key; - }); foreach (var key in existingJobKeys) { @@ -126,7 +130,6 @@ public abstract class BaseJobsHostedService : IHostedService, IDisposable } var existingTriggerKeys = await _scheduler.GetTriggerKeys(GroupMatcher.AnyGroup()); - var triggerKeys = Jobs.Select(j => j.Item2.Key); foreach (var key in existingTriggerKeys) { @@ -142,7 +145,10 @@ public abstract class BaseJobsHostedService : IHostedService, IDisposable public virtual async Task StopAsync(CancellationToken cancellationToken) { - await _scheduler?.Shutdown(cancellationToken); + if (_scheduler is not null) + { + await _scheduler.Shutdown(cancellationToken); + } } public virtual void Dispose() diff --git a/src/Core/Jobs/JobFactory.cs b/src/Core/Jobs/JobFactory.cs index 6529443d97..8289a90322 100644 --- a/src/Core/Jobs/JobFactory.cs +++ b/src/Core/Jobs/JobFactory.cs @@ -4,6 +4,8 @@ using Quartz.Spi; namespace Bit.Core.Jobs; +#nullable enable + public class JobFactory : IJobFactory { private readonly IServiceProvider _container; @@ -16,7 +18,7 @@ public class JobFactory : IJobFactory public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { var scope = _container.CreateScope(); - return scope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob; + return (scope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob)!; } public void ReturnJob(IJob job) diff --git a/src/Core/Jobs/JobListener.cs b/src/Core/Jobs/JobListener.cs index e5e05e4b6b..0dc865655d 100644 --- a/src/Core/Jobs/JobListener.cs +++ b/src/Core/Jobs/JobListener.cs @@ -3,6 +3,8 @@ using Quartz; namespace Bit.Core.Jobs; +#nullable enable + public class JobListener : IJobListener { private readonly ILogger _logger; @@ -28,7 +30,7 @@ public class JobListener : IJobListener return Task.FromResult(0); } - public Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, + public Task JobWasExecuted(IJobExecutionContext context, JobExecutionException? jobException, CancellationToken cancellationToken = default(CancellationToken)) { _logger.LogInformation(Constants.BypassFiltersEventId, null, "Finished job {0} at {1}.", diff --git a/src/Core/NotificationHub/INotificationHubClientProxy.cs b/src/Core/NotificationHub/INotificationHubClientProxy.cs index 82b4d39591..78eb0206d6 100644 --- a/src/Core/NotificationHub/INotificationHubClientProxy.cs +++ b/src/Core/NotificationHub/INotificationHubClientProxy.cs @@ -2,6 +2,8 @@ namespace Bit.Core.NotificationHub; +#nullable enable + public interface INotificationHubProxy { Task<(INotificationHubClient Client, NotificationOutcome Outcome)[]> SendTemplateNotificationAsync(IDictionary properties, string tagExpression); diff --git a/src/Core/NotificationHub/INotificationHubPool.cs b/src/Core/NotificationHub/INotificationHubPool.cs index 3981598118..25a31d62f4 100644 --- a/src/Core/NotificationHub/INotificationHubPool.cs +++ b/src/Core/NotificationHub/INotificationHubPool.cs @@ -2,6 +2,8 @@ namespace Bit.Core.NotificationHub; +#nullable enable + public interface INotificationHubPool { NotificationHubConnection ConnectionFor(Guid comb); diff --git a/src/Core/NotificationHub/NotificationHubClientProxy.cs b/src/Core/NotificationHub/NotificationHubClientProxy.cs index 815ac88363..b47069fe21 100644 --- a/src/Core/NotificationHub/NotificationHubClientProxy.cs +++ b/src/Core/NotificationHub/NotificationHubClientProxy.cs @@ -2,6 +2,8 @@ namespace Bit.Core.NotificationHub; +#nullable enable + public class NotificationHubClientProxy : INotificationHubProxy { private readonly IEnumerable _clients; diff --git a/src/Core/NotificationHub/NotificationHubConnection.cs b/src/Core/NotificationHub/NotificationHubConnection.cs index a68134450e..a61f2ded8f 100644 --- a/src/Core/NotificationHub/NotificationHubConnection.cs +++ b/src/Core/NotificationHub/NotificationHubConnection.cs @@ -1,4 +1,5 @@ -using System.Security.Cryptography; +using System.Diagnostics.CodeAnalysis; +using System.Security.Cryptography; using System.Text; using System.Web; using Bit.Core.Settings; @@ -7,21 +8,23 @@ using Microsoft.Azure.NotificationHubs; namespace Bit.Core.NotificationHub; +#nullable enable + public class NotificationHubConnection { - public string HubName { get; init; } - public string ConnectionString { get; init; } + public string? HubName { get; init; } + public string? ConnectionString { get; init; } private Lazy _parsedConnectionString; public Uri Endpoint => _parsedConnectionString.Value.Endpoint; private string SasKey => _parsedConnectionString.Value.SharedAccessKey; private string SasKeyName => _parsedConnectionString.Value.SharedAccessKeyName; public bool EnableSendTracing { get; init; } - private NotificationHubClient _hubClient; + private NotificationHubClient? _hubClient; /// /// Gets the NotificationHubClient for this connection. - /// + /// /// If the client is null, it will be initialized. - /// + /// /// Exception if the connection is invalid. /// public NotificationHubClient HubClient @@ -45,13 +48,13 @@ public class NotificationHubConnection } /// /// Gets the start date for registration. - /// + /// /// If null, registration is always disabled. /// public DateTime? RegistrationStartDate { get; init; } /// /// Gets the end date for registration. - /// + /// /// If null, registration has no end date. /// public DateTime? RegistrationEndDate { get; init; } @@ -155,9 +158,10 @@ public class NotificationHubConnection }; } + [MemberNotNull(nameof(_hubClient))] private NotificationHubConnection Init() { - HubClient = NotificationHubClient.CreateClientFromConnectionString(ConnectionString, HubName, EnableSendTracing); + _hubClient = NotificationHubClient.CreateClientFromConnectionString(ConnectionString, HubName, EnableSendTracing); return this; } diff --git a/src/Core/NotificationHub/NotificationHubPool.cs b/src/Core/NotificationHub/NotificationHubPool.cs index 6b48e82f88..38192c11fc 100644 --- a/src/Core/NotificationHub/NotificationHubPool.cs +++ b/src/Core/NotificationHub/NotificationHubPool.cs @@ -5,6 +5,8 @@ using Microsoft.Extensions.Logging; namespace Bit.Core.NotificationHub; +#nullable enable + public class NotificationHubPool : INotificationHubPool { private List _connections { get; } diff --git a/src/Core/NotificationHub/NotificationHubPushNotificationService.cs b/src/Core/NotificationHub/NotificationHubPushNotificationService.cs index bb3de80977..368c0f731b 100644 --- a/src/Core/NotificationHub/NotificationHubPushNotificationService.cs +++ b/src/Core/NotificationHub/NotificationHubPushNotificationService.cs @@ -19,6 +19,8 @@ using Notification = Bit.Core.NotificationCenter.Entities.Notification; namespace Bit.Core.NotificationHub; +#nullable enable + /// /// Sends mobile push notifications to the Azure Notification Hub. /// Used by Cloud-Hosted environments. diff --git a/src/Core/NotificationHub/NotificationHubPushRegistrationService.cs b/src/Core/NotificationHub/NotificationHubPushRegistrationService.cs index f44fcf91a0..dc494eecd6 100644 --- a/src/Core/NotificationHub/NotificationHubPushRegistrationService.cs +++ b/src/Core/NotificationHub/NotificationHubPushRegistrationService.cs @@ -13,6 +13,8 @@ using Microsoft.Extensions.Logging; namespace Bit.Core.NotificationHub; +#nullable enable + public class NotificationHubPushRegistrationService : IPushRegistrationService { private static readonly JsonSerializerOptions webPushSerializationOptions = new() @@ -37,7 +39,7 @@ public class NotificationHubPushRegistrationService : IPushRegistrationService } public async Task CreateOrUpdateRegistrationAsync(PushRegistrationData data, string deviceId, string userId, - string identifier, DeviceType type, IEnumerable organizationIds, Guid installationId) + string? identifier, DeviceType type, IEnumerable organizationIds, Guid installationId) { var orgIds = organizationIds.ToList(); var clientType = DeviceTypes.ToClientType(type); @@ -79,7 +81,7 @@ public class NotificationHubPushRegistrationService : IPushRegistrationService } private async Task CreateOrUpdateMobileRegistrationAsync(Installation installation, string userId, - string identifier, ClientType clientType, List organizationIds, DeviceType type, Guid installationId) + string? identifier, ClientType clientType, List organizationIds, DeviceType type, Guid installationId) { if (string.IsNullOrWhiteSpace(installation.PushChannel)) { @@ -137,7 +139,7 @@ public class NotificationHubPushRegistrationService : IPushRegistrationService } private async Task CreateOrUpdateWebRegistrationAsync(string endpoint, string p256dh, string auth, Installation installation, string userId, - string identifier, ClientType clientType, List organizationIds, Guid installationId) + string? identifier, ClientType clientType, List organizationIds, Guid installationId) { // The Azure SDK is currently lacking support for web push registrations. // We need to use the REST API directly. @@ -187,7 +189,7 @@ public class NotificationHubPushRegistrationService : IPushRegistrationService } private static KeyValuePair BuildInstallationTemplate(string templateId, [StringSyntax(StringSyntaxAttribute.Json)] string templateBody, - string userId, string identifier, ClientType clientType, List organizationIds, Guid installationId) + string userId, string? identifier, ClientType clientType, List organizationIds, Guid installationId) { var fullTemplateId = $"template:{templateId}"; diff --git a/src/Core/NotificationHub/PushRegistrationData.cs b/src/Core/NotificationHub/PushRegistrationData.cs index 20e1cf0936..c11ee7be23 100644 --- a/src/Core/NotificationHub/PushRegistrationData.cs +++ b/src/Core/NotificationHub/PushRegistrationData.cs @@ -1,5 +1,7 @@ namespace Bit.Core.NotificationHub; +#nullable enable + public record struct WebPushRegistrationData { public string Endpoint { get; init; } @@ -9,9 +11,9 @@ public record struct WebPushRegistrationData public record class PushRegistrationData { - public string Token { get; set; } + public string? Token { get; set; } public WebPushRegistrationData? WebPush { get; set; } - public PushRegistrationData(string token) + public PushRegistrationData(string? token) { Token = token; } diff --git a/test/Api.Test/KeyManagement/Controllers/AccountsKeyManagementControllerTests.cs b/test/Api.Test/KeyManagement/Controllers/AccountsKeyManagementControllerTests.cs index d2775762e8..05b1aa5a4d 100644 --- a/test/Api.Test/KeyManagement/Controllers/AccountsKeyManagementControllerTests.cs +++ b/test/Api.Test/KeyManagement/Controllers/AccountsKeyManagementControllerTests.cs @@ -175,7 +175,7 @@ public class AccountsKeyManagementControllerTests } catch (BadRequestException ex) { - Assert.NotEmpty(ex.ModelState.Values); + Assert.NotEmpty(ex.ModelState!.Values); } } @@ -210,7 +210,7 @@ public class AccountsKeyManagementControllerTests var badRequestException = await Assert.ThrowsAsync(() => sutProvider.Sut.PostSetKeyConnectorKeyAsync(data)); - Assert.Equal(1, badRequestException.ModelState.ErrorCount); + Assert.Equal(1, badRequestException.ModelState!.ErrorCount); Assert.Equal("set key connector key error", badRequestException.ModelState.Root.Errors[0].ErrorMessage); await sutProvider.GetDependency().Received(1) .SetKeyConnectorKeyAsync(Arg.Do(user => @@ -284,7 +284,7 @@ public class AccountsKeyManagementControllerTests var badRequestException = await Assert.ThrowsAsync(() => sutProvider.Sut.PostConvertToKeyConnectorAsync()); - Assert.Equal(1, badRequestException.ModelState.ErrorCount); + Assert.Equal(1, badRequestException.ModelState!.ErrorCount); Assert.Equal("convert to key connector error", badRequestException.ModelState.Root.Errors[0].ErrorMessage); await sutProvider.GetDependency().Received(1) .ConvertToKeyConnectorAsync(Arg.Is(expectedUser)); From dcf97a577236d3db5bb8dc5965462f64f4fb258f Mon Sep 17 00:00:00 2001 From: Alex Morask <144709477+amorask-bitwarden@users.noreply.github.com> Date: Fri, 6 Jun 2025 08:04:10 -0500 Subject: [PATCH 10/19] [PM-20485] [PM-20486] Add missing mappings to PlanAdapter (#5791) * Add missing mappings to PlanAdapter * PM-20485: Fix SM base seats --- src/Core/Billing/Pricing/PlanAdapter.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Core/Billing/Pricing/PlanAdapter.cs b/src/Core/Billing/Pricing/PlanAdapter.cs index f719fd1e87..45a48c3f80 100644 --- a/src/Core/Billing/Pricing/PlanAdapter.cs +++ b/src/Core/Billing/Pricing/PlanAdapter.cs @@ -31,6 +31,7 @@ public record PlanAdapter : Plan HasScim = HasFeature("scim"); HasResetPassword = HasFeature("resetPassword"); UsersGetPremium = HasFeature("usersGetPremium"); + HasCustomPermissions = HasFeature("customPermissions"); UpgradeSortOrder = plan.AdditionalData.TryGetValue("upgradeSortOrder", out var upgradeSortOrder) ? int.Parse(upgradeSortOrder) : 0; @@ -141,6 +142,7 @@ public record PlanAdapter : Plan var stripeSeatPlanId = GetStripeSeatPlanId(seats); var hasAdditionalSeatsOption = seats.IsScalable; var seatPrice = GetSeatPrice(seats); + var baseSeats = GetBaseSeats(seats); var maxSeats = GetMaxSeats(seats); var allowSeatAutoscale = seats.IsScalable; var maxProjects = plan.AdditionalData.TryGetValue("secretsManager.maxProjects", out var value) ? short.Parse(value) : 0; @@ -156,6 +158,7 @@ public record PlanAdapter : Plan StripeSeatPlanId = stripeSeatPlanId, HasAdditionalSeatsOption = hasAdditionalSeatsOption, SeatPrice = seatPrice, + BaseSeats = baseSeats, MaxSeats = maxSeats, AllowSeatAutoscale = allowSeatAutoscale, MaxProjects = maxProjects @@ -168,8 +171,16 @@ public record PlanAdapter : Plan private static decimal GetBasePrice(PurchasableDTO purchasable) => purchasable.FromPackaged(x => x.Price); + private static int GetBaseSeats(FreeOrScalableDTO freeOrScalable) + => freeOrScalable.Match( + free => free.Quantity, + scalable => scalable.Provided); + private static int GetBaseSeats(PurchasableDTO purchasable) - => purchasable.FromPackaged(x => x.Quantity); + => purchasable.Match( + free => free.Quantity, + packaged => packaged.Quantity, + scalable => scalable.Provided); private static short GetBaseServiceAccount(FreeOrScalableDTO freeOrScalable) => freeOrScalable.Match( From 87b6606bc2cb31dba45edb52d078c06979484333 Mon Sep 17 00:00:00 2001 From: Alex Morask <144709477+amorask-bitwarden@users.noreply.github.com> Date: Mon, 9 Jun 2025 09:30:26 -0500 Subject: [PATCH 11/19] Append EUVAT to Spanish NIF tax ID types (#5843) --- .../Services/ProviderBillingService.cs | 9 +++++++ src/Core/Billing/Constants/StripeConstants.cs | 6 +++++ .../OrganizationBillingService.cs | 11 ++++++++ .../Implementations/SubscriberService.cs | 6 +++++ .../Tax/Commands/PreviewTaxAmountCommand.cs | 9 +++++++ .../Implementations/StripePaymentService.cs | 26 ++++++++++++++++++- 6 files changed, 66 insertions(+), 1 deletion(-) diff --git a/bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs b/bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs index 8c90d778bc..2b337fb4bb 100644 --- a/bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs +++ b/bitwarden_license/src/Commercial.Core/Billing/Providers/Services/ProviderBillingService.cs @@ -550,6 +550,15 @@ public class ProviderBillingService( [ new CustomerTaxIdDataOptions { Type = taxIdType, Value = taxInfo.TaxIdNumber } ]; + + if (taxIdType == StripeConstants.TaxIdType.SpanishNIF) + { + options.TaxIdData.Add(new CustomerTaxIdDataOptions + { + Type = StripeConstants.TaxIdType.EUVAT, + Value = $"ES{taxInfo.TaxIdNumber}" + }); + } } if (!string.IsNullOrEmpty(provider.DiscountId)) diff --git a/src/Core/Billing/Constants/StripeConstants.cs b/src/Core/Billing/Constants/StripeConstants.cs index 28f4dea4b2..0cffad72d3 100644 --- a/src/Core/Billing/Constants/StripeConstants.cs +++ b/src/Core/Billing/Constants/StripeConstants.cs @@ -96,6 +96,12 @@ public static class StripeConstants public const string Reverse = "reverse"; } + public static class TaxIdType + { + public const string EUVAT = "eu_vat"; + public const string SpanishNIF = "es_cif"; + } + public static class ValidateTaxLocationTiming { public const string Deferred = "deferred"; diff --git a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs index 0fd997fd10..5e59d0d108 100644 --- a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs +++ b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs @@ -247,12 +247,23 @@ public class OrganizationBillingService( organization.Id, customerSetup.TaxInformation.Country, customerSetup.TaxInformation.TaxId); + + throw new BadRequestException("billingTaxIdTypeInferenceError"); } customerCreateOptions.TaxIdData = [ new() { Type = taxIdType, Value = customerSetup.TaxInformation.TaxId } ]; + + if (taxIdType == StripeConstants.TaxIdType.SpanishNIF) + { + customerCreateOptions.TaxIdData.Add(new CustomerTaxIdDataOptions + { + Type = StripeConstants.TaxIdType.EUVAT, + Value = $"ES{customerSetup.TaxInformation.TaxId}" + }); + } } var (paymentMethodType, paymentMethodToken) = customerSetup.TokenizedPaymentSource; diff --git a/src/Core/Billing/Services/Implementations/SubscriberService.cs b/src/Core/Billing/Services/Implementations/SubscriberService.cs index 75a1bf76ec..796f700e9f 100644 --- a/src/Core/Billing/Services/Implementations/SubscriberService.cs +++ b/src/Core/Billing/Services/Implementations/SubscriberService.cs @@ -648,6 +648,12 @@ public class SubscriberService( { await stripeAdapter.TaxIdCreateAsync(customer.Id, new TaxIdCreateOptions { Type = taxIdType, Value = taxInformation.TaxId }); + + if (taxIdType == StripeConstants.TaxIdType.SpanishNIF) + { + await stripeAdapter.TaxIdCreateAsync(customer.Id, + new TaxIdCreateOptions { Type = StripeConstants.TaxIdType.EUVAT, Value = $"ES{taxInformation.TaxId}" }); + } } catch (StripeException e) { diff --git a/src/Core/Billing/Tax/Commands/PreviewTaxAmountCommand.cs b/src/Core/Billing/Tax/Commands/PreviewTaxAmountCommand.cs index 304abbaae0..c777d0c0d1 100644 --- a/src/Core/Billing/Tax/Commands/PreviewTaxAmountCommand.cs +++ b/src/Core/Billing/Tax/Commands/PreviewTaxAmountCommand.cs @@ -80,6 +80,15 @@ public class PreviewTaxAmountCommand( Value = taxInformation.TaxId } ]; + + if (taxIdType == StripeConstants.TaxIdType.SpanishNIF) + { + options.CustomerDetails.TaxIds.Add(new InvoiceCustomerDetailsTaxIdOptions + { + Type = StripeConstants.TaxIdType.EUVAT, + Value = $"ES{parameters.TaxInformation.TaxId}" + }); + } } if (planType.GetProductTier() == ProductTierType.Families) diff --git a/src/Core/Services/Implementations/StripePaymentService.cs b/src/Core/Services/Implementations/StripePaymentService.cs index 23d06bed2b..bdd558df52 100644 --- a/src/Core/Services/Implementations/StripePaymentService.cs +++ b/src/Core/Services/Implementations/StripePaymentService.cs @@ -842,7 +842,13 @@ public class StripePaymentService : IPaymentService try { await _stripeAdapter.TaxIdCreateAsync(customer.Id, - new TaxIdCreateOptions { Type = taxInfo.TaxIdType, Value = taxInfo.TaxIdNumber, }); + new TaxIdCreateOptions { Type = taxInfo.TaxIdType, Value = taxInfo.TaxIdNumber }); + + if (taxInfo.TaxIdType == StripeConstants.TaxIdType.SpanishNIF) + { + await _stripeAdapter.TaxIdCreateAsync(customer.Id, + new TaxIdCreateOptions { Type = StripeConstants.TaxIdType.EUVAT, Value = $"ES{taxInfo.TaxIdNumber}" }); + } } catch (StripeException e) { @@ -1000,6 +1006,15 @@ public class StripePaymentService : IPaymentService Value = parameters.TaxInformation.TaxId } ]; + + if (taxIdType == StripeConstants.TaxIdType.SpanishNIF) + { + options.CustomerDetails.TaxIds.Add(new InvoiceCustomerDetailsTaxIdOptions + { + Type = StripeConstants.TaxIdType.EUVAT, + Value = $"ES{parameters.TaxInformation.TaxId}" + }); + } } if (!string.IsNullOrWhiteSpace(gatewayCustomerId)) @@ -1154,6 +1169,15 @@ public class StripePaymentService : IPaymentService Value = parameters.TaxInformation.TaxId } ]; + + if (taxIdType == StripeConstants.TaxIdType.SpanishNIF) + { + options.CustomerDetails.TaxIds.Add(new InvoiceCustomerDetailsTaxIdOptions + { + Type = StripeConstants.TaxIdType.EUVAT, + Value = $"ES{parameters.TaxInformation.TaxId}" + }); + } } Customer gatewayCustomer = null; From 88ffc91b99341fb1562f2a80602cb26b93d47948 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 10:49:41 -0500 Subject: [PATCH 12/19] [deps] Billing: Update coverlet.collector to 6.0.4 (#5720) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- test/Core.IntegrationTest/Core.IntegrationTest.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Core.IntegrationTest/Core.IntegrationTest.csproj b/test/Core.IntegrationTest/Core.IntegrationTest.csproj index 6094209f23..21b746c2fb 100644 --- a/test/Core.IntegrationTest/Core.IntegrationTest.csproj +++ b/test/Core.IntegrationTest/Core.IntegrationTest.csproj @@ -10,7 +10,7 @@ - + From 52c392d66887cc3612b81ee53de4a84256bd97ea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 10:53:17 -0500 Subject: [PATCH 13/19] [deps] Billing: Update swashbuckle-aspnetcore monorepo to 7.3.2 (#5731) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- src/Api/Api.csproj | 2 +- src/Billing/Billing.csproj | 2 +- src/SharedWeb/SharedWeb.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index f42f226153..d7814849c6 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "swashbuckle.aspnetcore.cli": { - "version": "7.2.0", + "version": "7.3.2", "commands": ["swagger"] }, "dotnet-ef": { diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj index c490e90150..11af4d5e0a 100644 --- a/src/Api/Api.csproj +++ b/src/Api/Api.csproj @@ -34,7 +34,7 @@ - + diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj index 01a8bbdd9b..116efdb68c 100644 --- a/src/Billing/Billing.csproj +++ b/src/Billing/Billing.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/SharedWeb/SharedWeb.csproj b/src/SharedWeb/SharedWeb.csproj index 6df65b2310..1951e4d509 100644 --- a/src/SharedWeb/SharedWeb.csproj +++ b/src/SharedWeb/SharedWeb.csproj @@ -7,7 +7,7 @@ - + From 84e5ea12652275694c7e83bae0fe568371637234 Mon Sep 17 00:00:00 2001 From: Jared McCannon Date: Mon, 9 Jun 2025 14:50:15 -0400 Subject: [PATCH 14/19] [PM-22097] Add Columns to Collections for Org User Default Collection (#5908) * Adding columns and database migrations for organization DefaultUserCollection. --- src/Core/Entities/Collection.cs | 3 + src/Core/Enums/CollectionType.cs | 7 + .../Stored Procedures/Collection_Create.sql | 12 +- .../Collection_CreateWithGroupsAndUsers.sql | 6 +- .../Collection_ReadByUserId.sql | 8 +- .../Stored Procedures/Collection_Update.sql | 10 +- .../Collection_UpdateWithGroupsAndUsers.sql | 6 +- src/Sql/dbo/Tables/Collection.sql | 14 +- .../Collection_ReadByIdWithPermissions.sql | 4 +- ...on_ReadByOrganizationIdWithPermissions.sql | 4 +- ...5-06-02_00_AddOrgUserDefaultCollection.sql | 55 + ...5-06-02_01_AddOrgUserDefaultCollection.sql | 456 +++ ...13_AddOrgUserDefaultCollection.Designer.cs | 3125 ++++++++++++++++ ...50603133713_AddOrgUserDefaultCollection.cs | 39 + .../DatabaseContextModelSnapshot.cs | 6 + ...04_AddOrgUserDefaultCollection.Designer.cs | 3131 +++++++++++++++++ ...50603133704_AddOrgUserDefaultCollection.cs | 38 + .../DatabaseContextModelSnapshot.cs | 6 + ...08_AddOrgUserDefaultCollection.Designer.cs | 3114 ++++++++++++++++ ...50603133708_AddOrgUserDefaultCollection.cs | 38 + .../DatabaseContextModelSnapshot.cs | 6 + 21 files changed, 10068 insertions(+), 20 deletions(-) create mode 100644 src/Core/Enums/CollectionType.cs create mode 100644 util/Migrator/DbScripts/2025-06-02_00_AddOrgUserDefaultCollection.sql create mode 100644 util/Migrator/DbScripts/2025-06-02_01_AddOrgUserDefaultCollection.sql create mode 100644 util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.Designer.cs create mode 100644 util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.cs create mode 100644 util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.Designer.cs create mode 100644 util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.cs create mode 100644 util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.Designer.cs create mode 100644 util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.cs diff --git a/src/Core/Entities/Collection.cs b/src/Core/Entities/Collection.cs index 8babe10e4c..275cd80d2f 100644 --- a/src/Core/Entities/Collection.cs +++ b/src/Core/Entities/Collection.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using Bit.Core.Enums; using Bit.Core.Utilities; #nullable enable @@ -14,6 +15,8 @@ public class Collection : ITableObject public string? ExternalId { get; set; } public DateTime CreationDate { get; set; } = DateTime.UtcNow; public DateTime RevisionDate { get; set; } = DateTime.UtcNow; + public CollectionType Type { get; set; } = CollectionType.SharedCollection; + public string? DefaultUserCollectionEmail { get; set; } public void SetNewId() { diff --git a/src/Core/Enums/CollectionType.cs b/src/Core/Enums/CollectionType.cs new file mode 100644 index 0000000000..9bc4fcc9c2 --- /dev/null +++ b/src/Core/Enums/CollectionType.cs @@ -0,0 +1,7 @@ +namespace Bit.Core.Enums; + +public enum CollectionType +{ + SharedCollection = 0, + DefaultUserCollection = 1, +} diff --git a/src/Sql/dbo/Stored Procedures/Collection_Create.sql b/src/Sql/dbo/Stored Procedures/Collection_Create.sql index 2e442c6a28..2b3b14fd6b 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_Create.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_Create.sql @@ -4,7 +4,9 @@ @Name VARCHAR(MAX), @ExternalId NVARCHAR(300), @CreationDate DATETIME2(7), - @RevisionDate DATETIME2(7) + @RevisionDate DATETIME2(7), + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 AS BEGIN SET NOCOUNT ON @@ -16,7 +18,9 @@ BEGIN [Name], [ExternalId], [CreationDate], - [RevisionDate] + [RevisionDate], + [DefaultUserCollectionEmail], + [Type] ) VALUES ( @@ -25,7 +29,9 @@ BEGIN @Name, @ExternalId, @CreationDate, - @RevisionDate + @RevisionDate, + @DefaultUserCollectionEmail, + @Type ) EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId diff --git a/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroupsAndUsers.sql b/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroupsAndUsers.sql index 87bac3b385..92ffd366e6 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroupsAndUsers.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroupsAndUsers.sql @@ -6,12 +6,14 @@ CREATE PROCEDURE [dbo].[Collection_CreateWithGroupsAndUsers] @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7), @Groups AS [dbo].[CollectionAccessSelectionType] READONLY, - @Users AS [dbo].[CollectionAccessSelectionType] READONLY + @Users AS [dbo].[CollectionAccessSelectionType] READONLY, + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 AS BEGIN SET NOCOUNT ON - EXEC [dbo].[Collection_Create] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate + EXEC [dbo].[Collection_Create] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate, @DefaultUserCollectionEmail, @Type -- Groups ;WITH [AvailableGroupsCTE] AS( diff --git a/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql index f0eab509ac..4180dc6909 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql @@ -13,7 +13,9 @@ BEGIN ExternalId, MIN([ReadOnly]) AS [ReadOnly], MIN([HidePasswords]) AS [HidePasswords], - MAX([Manage]) AS [Manage] + MAX([Manage]) AS [Manage], + [DefaultUserCollectionEmail], + [Type] FROM [dbo].[UserCollectionDetails](@UserId) GROUP BY @@ -22,5 +24,7 @@ BEGIN [Name], CreationDate, RevisionDate, - ExternalId + ExternalId, + [DefaultUserCollectionEmail], + [Type] END diff --git a/src/Sql/dbo/Stored Procedures/Collection_Update.sql b/src/Sql/dbo/Stored Procedures/Collection_Update.sql index e75f088d7d..69a009e27a 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_Update.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_Update.sql @@ -4,7 +4,9 @@ @Name VARCHAR(MAX), @ExternalId NVARCHAR(300), @CreationDate DATETIME2(7), - @RevisionDate DATETIME2(7) + @RevisionDate DATETIME2(7), + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 AS BEGIN SET NOCOUNT ON @@ -16,9 +18,11 @@ BEGIN [Name] = @Name, [ExternalId] = @ExternalId, [CreationDate] = @CreationDate, - [RevisionDate] = @RevisionDate + [RevisionDate] = @RevisionDate, + [DefaultUserCollectionEmail] = @DefaultUserCollectionEmail, + [Type] = @Type WHERE [Id] = @Id EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId -END \ No newline at end of file +END diff --git a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroupsAndUsers.sql b/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroupsAndUsers.sql index 4a66b20d86..29894f984b 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroupsAndUsers.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroupsAndUsers.sql @@ -6,12 +6,14 @@ @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7), @Groups AS [dbo].[CollectionAccessSelectionType] READONLY, - @Users AS [dbo].[CollectionAccessSelectionType] READONLY + @Users AS [dbo].[CollectionAccessSelectionType] READONLY, + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 AS BEGIN SET NOCOUNT ON - EXEC [dbo].[Collection_Update] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate + EXEC [dbo].[Collection_Update] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate, @DefaultUserCollectionEmail, @Type -- Groups -- Delete groups that are no longer in source diff --git a/src/Sql/dbo/Tables/Collection.sql b/src/Sql/dbo/Tables/Collection.sql index 0106f341df..03064fd978 100644 --- a/src/Sql/dbo/Tables/Collection.sql +++ b/src/Sql/dbo/Tables/Collection.sql @@ -1,10 +1,12 @@ CREATE TABLE [dbo].[Collection] ( - [Id] UNIQUEIDENTIFIER NOT NULL, - [OrganizationId] UNIQUEIDENTIFIER NOT NULL, - [Name] VARCHAR (MAX) NOT NULL, - [ExternalId] NVARCHAR (300) NULL, - [CreationDate] DATETIME2 (7) NOT NULL, - [RevisionDate] DATETIME2 (7) NOT NULL, + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [Name] VARCHAR (MAX) NOT NULL, + [ExternalId] NVARCHAR (300) NULL, + [CreationDate] DATETIME2 (7) NOT NULL, + [RevisionDate] DATETIME2 (7) NOT NULL, + [DefaultUserCollectionEmail] NVARCHAR(256) NULL, + [Type] TINYINT NOT NULL DEFAULT(0), CONSTRAINT [PK_Collection] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_Collection_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE ); diff --git a/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql b/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql index 3bb50a51cf..9f2caeb87f 100644 --- a/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql +++ b/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByIdWithPermissions.sql @@ -73,7 +73,9 @@ BEGIN C.[Name], C.[CreationDate], C.[RevisionDate], - C.[ExternalId] + C.[ExternalId], + C.[DefaultUserCollectionEmail], + C.[Type] IF (@IncludeAccessRelationships = 1) BEGIN diff --git a/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql b/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql index 2c99282eef..267024f56c 100644 --- a/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql +++ b/src/Sql/dbo/Vault/Stored Procedures/Collections/Collection_ReadByOrganizationIdWithPermissions.sql @@ -73,7 +73,9 @@ BEGIN C.[Name], C.[CreationDate], C.[RevisionDate], - C.[ExternalId] + C.[ExternalId], + C.[DefaultUserCollectionEmail], + C.[Type] IF (@IncludeAccessRelationships = 1) BEGIN diff --git a/util/Migrator/DbScripts/2025-06-02_00_AddOrgUserDefaultCollection.sql b/util/Migrator/DbScripts/2025-06-02_00_AddOrgUserDefaultCollection.sql new file mode 100644 index 0000000000..72ef987cc1 --- /dev/null +++ b/util/Migrator/DbScripts/2025-06-02_00_AddOrgUserDefaultCollection.sql @@ -0,0 +1,55 @@ +IF NOT EXISTS ( + SELECT * + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = 'dbo' + AND TABLE_NAME = 'Collection' + AND COLUMN_NAME = 'DefaultUserCollectionEmail' +) + BEGIN + ALTER TABLE [dbo].[Collection] + ADD [DefaultUserCollectionEmail] NVARCHAR(256) NULL + END +GO + +IF NOT EXISTS ( + SELECT * + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = 'dbo' + AND TABLE_NAME = 'Collection' + AND COLUMN_NAME = 'Type' +) + BEGIN + ALTER TABLE [dbo].[Collection] + ADD [Type] TINYINT NOT NULL DEFAULT (0) + END +GO + +IF OBJECT_ID('[dbo].[CollectionView]') IS NOT NULL + BEGIN + EXECUTE sp_refreshsqlmodule N'[dbo].[CollectionView]'; + END +GO + +IF OBJECT_ID('[dbo].[Collection_ReadById]') IS NOT NULL + BEGIN + EXECUTE sp_refreshsqlmodule N'[dbo].[Collection_ReadById]'; + END +GO + +IF OBJECT_ID('[dbo].[Collection_ReadByIds]') IS NOT NULL + BEGIN + EXECUTE sp_refreshsqlmodule N'[dbo].[Collection_ReadByIds]'; + END +GO + +IF OBJECT_ID('[dbo].[Collection_ReadByOrganizationId]') IS NOT NULL + BEGIN + EXECUTE sp_refreshsqlmodule N'[dbo].[Collection_ReadByOrganizationId]'; + END +GO + +IF OBJECT_ID('[dbo].[UserCollectionDetails]') IS NOT NULL + BEGIN + EXECUTE sp_refreshsqlmodule N'[dbo].[UserCollectionDetails]'; + END +GO diff --git a/util/Migrator/DbScripts/2025-06-02_01_AddOrgUserDefaultCollection.sql b/util/Migrator/DbScripts/2025-06-02_01_AddOrgUserDefaultCollection.sql new file mode 100644 index 0000000000..ea8b60970c --- /dev/null +++ b/util/Migrator/DbScripts/2025-06-02_01_AddOrgUserDefaultCollection.sql @@ -0,0 +1,456 @@ +CREATE OR ALTER PROCEDURE [dbo].[Collection_Create] + @Id UNIQUEIDENTIFIER OUTPUT, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @ExternalId NVARCHAR(300), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[Collection] + ( + [Id], + [OrganizationId], + [Name], + [ExternalId], + [CreationDate], + [RevisionDate], + [DefaultUserCollectionEmail], + [Type] + ) + VALUES + ( + @Id, + @OrganizationId, + @Name, + @ExternalId, + @CreationDate, + @RevisionDate, + @DefaultUserCollectionEmail, + @Type + ) + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Collection_ReadByUserId] +@UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + [Id], + [OrganizationId], + [Name], + [CreationDate], + [RevisionDate], + [ExternalId], + MIN([ReadOnly]) AS [ReadOnly], + MIN([HidePasswords]) AS [HidePasswords], + MAX([Manage]) AS [Manage], + [DefaultUserCollectionEmail], + [Type] + FROM + [dbo].[UserCollectionDetails](@UserId) + GROUP BY + [Id], + [OrganizationId], + [Name], + [CreationDate], + [RevisionDate], + [ExternalId], + [DefaultUserCollectionEmail], + [Type] +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Collection_Update] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @ExternalId NVARCHAR(300), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 +AS +BEGIN + SET NOCOUNT ON + + UPDATE + [dbo].[Collection] + SET + [OrganizationId] = @OrganizationId, + [Name] = @Name, + [ExternalId] = @ExternalId, + [CreationDate] = @CreationDate, + [RevisionDate] = @RevisionDate, + [DefaultUserCollectionEmail] = @DefaultUserCollectionEmail, + [Type] = @Type + WHERE + [Id] = @Id + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Collection_UpdateWithGroupsAndUsers] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @ExternalId NVARCHAR(300), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @Groups AS [dbo].[CollectionAccessSelectionType] READONLY, + @Users AS [dbo].[CollectionAccessSelectionType] READONLY, + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[Collection_Update] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate, @DefaultUserCollectionEmail, @Type + + -- Groups + -- Delete groups that are no longer in source + DELETE cg + FROM [dbo].[CollectionGroup] cg + LEFT JOIN @Groups g ON cg.GroupId = g.Id + WHERE cg.CollectionId = @Id + AND g.Id IS NULL; + + -- Update existing groups + UPDATE cg + SET cg.ReadOnly = g.ReadOnly, + cg.HidePasswords = g.HidePasswords, + cg.Manage = g.Manage + FROM [dbo].[CollectionGroup] cg + INNER JOIN @Groups g ON cg.GroupId = g.Id + WHERE cg.CollectionId = @Id + AND (cg.ReadOnly != g.ReadOnly + OR cg.HidePasswords != g.HidePasswords + OR cg.Manage != g.Manage); + + -- Insert new groups + INSERT INTO [dbo].[CollectionGroup] + ( + [CollectionId], + [GroupId], + [ReadOnly], + [HidePasswords], + [Manage] + ) + SELECT + @Id, + g.Id, + g.ReadOnly, + g.HidePasswords, + g.Manage + FROM @Groups g + INNER JOIN [dbo].[Group] grp ON grp.Id = g.Id + LEFT JOIN [dbo].[CollectionGroup] cg + ON cg.CollectionId = @Id AND cg.GroupId = g.Id + WHERE grp.OrganizationId = @OrganizationId + AND cg.CollectionId IS NULL; + + -- Users + -- Delete users that are no longer in source + DELETE cu + FROM [dbo].[CollectionUser] cu + LEFT JOIN @Users u ON cu.OrganizationUserId = u.Id + WHERE cu.CollectionId = @Id + AND u.Id IS NULL; + + -- Update existing users + UPDATE cu + SET cu.ReadOnly = u.ReadOnly, + cu.HidePasswords = u.HidePasswords, + cu.Manage = u.Manage + FROM [dbo].[CollectionUser] cu + INNER JOIN @Users u ON cu.OrganizationUserId = u.Id + WHERE cu.CollectionId = @Id + AND (cu.ReadOnly != u.ReadOnly + OR cu.HidePasswords != u.HidePasswords + OR cu.Manage != u.Manage); + + -- Insert new users + INSERT INTO [dbo].[CollectionUser] + ( + [CollectionId], + [OrganizationUserId], + [ReadOnly], + [HidePasswords], + [Manage] + ) + SELECT + @Id, + u.Id, + u.ReadOnly, + u.HidePasswords, + u.Manage + FROM @Users u + INNER JOIN [dbo].[OrganizationUser] ou ON ou.Id = u.Id + LEFT JOIN [dbo].[CollectionUser] cu + ON cu.CollectionId = @Id AND cu.OrganizationUserId = u.Id + WHERE ou.OrganizationId = @OrganizationId + AND cu.CollectionId IS NULL; + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Collection_ReadByOrganizationIdWithPermissions] + @OrganizationId UNIQUEIDENTIFIER, + @UserId UNIQUEIDENTIFIER, + @IncludeAccessRelationships BIT +AS +BEGIN + SET NOCOUNT ON + + SELECT + C.*, + MIN(CASE + WHEN + COALESCE(CU.[ReadOnly], CG.[ReadOnly], 0) = 0 + THEN 0 + ELSE 1 + END) AS [ReadOnly], + MIN(CASE + WHEN + COALESCE(CU.[HidePasswords], CG.[HidePasswords], 0) = 0 + THEN 0 + ELSE 1 + END) AS [HidePasswords], + MAX(CASE + WHEN + COALESCE(CU.[Manage], CG.[Manage], 0) = 0 + THEN 0 + ELSE 1 + END) AS [Manage], + MAX(CASE + WHEN + CU.[CollectionId] IS NULL AND CG.[CollectionId] IS NULL + THEN 0 + ELSE 1 + END) AS [Assigned], + CASE + WHEN + -- No user or group has manage rights + NOT EXISTS( + SELECT 1 + FROM [dbo].[CollectionUser] CU2 + JOIN [dbo].[OrganizationUser] OU2 ON CU2.[OrganizationUserId] = OU2.[Id] + WHERE + CU2.[CollectionId] = C.[Id] AND + CU2.[Manage] = 1 + ) + AND NOT EXISTS ( + SELECT 1 + FROM [dbo].[CollectionGroup] CG2 + WHERE + CG2.[CollectionId] = C.[Id] AND + CG2.[Manage] = 1 + ) + THEN 1 + ELSE 0 + END AS [Unmanaged] + FROM + [dbo].[CollectionView] C + LEFT JOIN + [dbo].[OrganizationUser] OU ON C.[OrganizationId] = OU.[OrganizationId] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[CollectionUser] CU ON CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = [OU].[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[Group] G ON G.[Id] = GU.[GroupId] + LEFT JOIN + [dbo].[CollectionGroup] CG ON CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] + WHERE + C.[OrganizationId] = @OrganizationId + GROUP BY + C.[Id], + C.[OrganizationId], + C.[Name], + C.[CreationDate], + C.[RevisionDate], + C.[ExternalId], + C.[DefaultUserCollectionEmail], + C.[Type] + + IF (@IncludeAccessRelationships = 1) + BEGIN + EXEC [dbo].[CollectionGroup_ReadByOrganizationId] @OrganizationId + EXEC [dbo].[CollectionUser_ReadByOrganizationId] @OrganizationId + END +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Collection_CreateWithGroupsAndUsers] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @ExternalId NVARCHAR(300), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @Groups AS [dbo].[CollectionAccessSelectionType] READONLY, + @Users AS [dbo].[CollectionAccessSelectionType] READONLY, + @DefaultUserCollectionEmail NVARCHAR(256) = NULL, + @Type TINYINT = 0 +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[Collection_Create] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate, @DefaultUserCollectionEmail, @Type + + -- Groups + ;WITH [AvailableGroupsCTE] AS( + SELECT + [Id] + FROM + [dbo].[Group] + WHERE + [OrganizationId] = @OrganizationId + ) + INSERT INTO [dbo].[CollectionGroup] + ( + [CollectionId], + [GroupId], + [ReadOnly], + [HidePasswords], + [Manage] + ) + SELECT + @Id, + [Id], + [ReadOnly], + [HidePasswords], + [Manage] + FROM + @Groups + WHERE + [Id] IN (SELECT [Id] FROM [AvailableGroupsCTE]) + + -- Users + ;WITH [AvailableUsersCTE] AS( + SELECT + [Id] + FROM + [dbo].[OrganizationUser] + WHERE + [OrganizationId] = @OrganizationId + ) + INSERT INTO [dbo].[CollectionUser] + ( + [CollectionId], + [OrganizationUserId], + [ReadOnly], + [HidePasswords], + [Manage] + ) + SELECT + @Id, + [Id], + [ReadOnly], + [HidePasswords], + [Manage] + FROM + @Users + WHERE + [Id] IN (SELECT [Id] FROM [AvailableUsersCTE]) + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Collection_ReadByIdWithPermissions] + @CollectionId UNIQUEIDENTIFIER, + @UserId UNIQUEIDENTIFIER, + @IncludeAccessRelationships BIT +AS +BEGIN + SET NOCOUNT ON + + SELECT + C.*, + MIN(CASE + WHEN + COALESCE(CU.[ReadOnly], CG.[ReadOnly], 0) = 0 + THEN 0 + ELSE 1 + END) AS [ReadOnly], + MIN (CASE + WHEN + COALESCE(CU.[HidePasswords], CG.[HidePasswords], 0) = 0 + THEN 0 + ELSE 1 + END) AS [HidePasswords], + MAX(CASE + WHEN + COALESCE(CU.[Manage], CG.[Manage], 0) = 0 + THEN 0 + ELSE 1 + END) AS [Manage], + MAX(CASE + WHEN + CU.[CollectionId] IS NULL AND CG.[CollectionId] IS NULL + THEN 0 + ELSE 1 + END) AS [Assigned], + CASE + WHEN + -- No user or group has manage rights + NOT EXISTS( + SELECT 1 + FROM [dbo].[CollectionUser] CU2 + JOIN [dbo].[OrganizationUser] OU2 ON CU2.[OrganizationUserId] = OU2.[Id] + WHERE + CU2.[CollectionId] = C.[Id] AND + CU2.[Manage] = 1 + ) + AND NOT EXISTS ( + SELECT 1 + FROM [dbo].[CollectionGroup] CG2 + WHERE + CG2.[CollectionId] = C.[Id] AND + CG2.[Manage] = 1 + ) + THEN 1 + ELSE 0 + END AS [Unmanaged] + FROM + [dbo].[CollectionView] C + LEFT JOIN + [dbo].[OrganizationUser] OU ON C.[OrganizationId] = OU.[OrganizationId] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[CollectionUser] CU ON CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = [OU].[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[Group] G ON G.[Id] = GU.[GroupId] + LEFT JOIN + [dbo].[CollectionGroup] CG ON CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] + WHERE + C.[Id] = @CollectionId + GROUP BY + C.[Id], + C.[OrganizationId], + C.[Name], + C.[CreationDate], + C.[RevisionDate], + C.[ExternalId], + C.[DefaultUserCollectionEmail], + C.[Type] + + IF (@IncludeAccessRelationships = 1) + BEGIN + EXEC [dbo].[CollectionGroup_ReadByCollectionId] @CollectionId + EXEC [dbo].[CollectionUser_ReadByCollectionId] @CollectionId + END +END diff --git a/util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.Designer.cs b/util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.Designer.cs new file mode 100644 index 0000000000..c937df9fe9 --- /dev/null +++ b/util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.Designer.cs @@ -0,0 +1,3125 @@ +// +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("20250603133713_AddOrgUserDefaultCollection")] + partial class AddOrgUserDefaultCollection + { + /// + 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.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("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("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("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.Models.Cache", b => + { + b.Property("Id") + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ExpiresAtTime") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Cache", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("DefaultUserCollectionEmail") + .HasColumnType("longtext"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("CipherId") + .HasColumnType("char(36)"); + + b.HasKey("CollectionId", "CipherId"); + + b.HasIndex("CipherId"); + + b.ToTable("CollectionCipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("char(36)"); + + b.Property("HidePasswords") + .HasColumnType("tinyint(1)"); + + b.Property("Manage") + .HasColumnType("tinyint(1)"); + + b.Property("ReadOnly") + .HasColumnType("tinyint(1)"); + + b.HasKey("CollectionId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("CollectionGroups"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("OrganizationUserId") + .HasColumnType("char(36)"); + + b.Property("HidePasswords") + .HasColumnType("tinyint(1)"); + + b.Property("Manage") + .HasColumnType("tinyint(1)"); + + b.Property("ReadOnly") + .HasColumnType("tinyint(1)"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Active") + .HasColumnType("tinyint(1)") + .HasDefaultValue(true); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("EncryptedPrivateKey") + .HasColumnType("longtext"); + + b.Property("EncryptedPublicKey") + .HasColumnType("longtext"); + + b.Property("EncryptedUserKey") + .HasColumnType("longtext"); + + b.Property("Identifier") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("Identifier") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "Identifier") + .IsUnique() + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Device", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ActingUserId") + .HasColumnType("char(36)"); + + b.Property("CipherId") + .HasColumnType("char(36)"); + + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DeviceType") + .HasColumnType("tinyint unsigned"); + + b.Property("DomainName") + .HasColumnType("longtext"); + + b.Property("GroupId") + .HasColumnType("char(36)"); + + b.Property("InstallationId") + .HasColumnType("char(36)"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("OrganizationUserId") + .HasColumnType("char(36)"); + + b.Property("PolicyId") + .HasColumnType("char(36)"); + + b.Property("ProviderId") + .HasColumnType("char(36)"); + + b.Property("ProviderOrganizationId") + .HasColumnType("char(36)"); + + b.Property("ProviderUserId") + .HasColumnType("char(36)"); + + b.Property("SecretId") + .HasColumnType("char(36)"); + + b.Property("ServiceAccountId") + .HasColumnType("char(36)"); + + b.Property("SystemUser") + .HasColumnType("tinyint unsigned"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("Date", "OrganizationId", "ActingUserId", "CipherId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("char(36)"); + + b.Property("OrganizationUserId") + .HasColumnType("char(36)"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("GroupUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Config") + .HasColumnType("longtext"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationConnection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("DomainName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("JobRunCount") + .HasColumnType("int"); + + b.Property("LastCheckedDate") + .HasColumnType("datetime(6)"); + + b.Property("NextRunDate") + .HasColumnType("datetime(6)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Txt") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("VerifiedDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationDomain", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("FriendlyName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("IsAdminInitiated") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncDate") + .HasColumnType("datetime(6)"); + + b.Property("Notes") + .HasColumnType("longtext"); + + b.Property("OfferedToEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PlanSponsorshipType") + .HasColumnType("tinyint unsigned"); + + b.Property("SponsoredOrganizationId") + .HasColumnType("char(36)"); + + b.Property("SponsoringOrganizationId") + .HasColumnType("char(36)"); + + b.Property("SponsoringOrganizationUserId") + .HasColumnType("char(36)"); + + b.Property("ToDelete") + .HasColumnType("tinyint(1)"); + + b.Property("ValidUntil") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("SponsoredOrganizationId"); + + b.HasIndex("SponsoringOrganizationId"); + + b.HasIndex("SponsoringOrganizationUserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("OrganizationSponsorship", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessSecretsManager") + .HasColumnType("tinyint(1)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Permissions") + .HasColumnType("longtext"); + + b.Property("ResetPasswordKey") + .HasColumnType("longtext"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("OrganizationUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessCount") + .HasColumnType("int"); + + b.Property("CipherId") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("DeletionDate") + .HasColumnType("datetime(6)"); + + b.Property("Disabled") + .HasColumnType("tinyint(1)"); + + b.Property("Emails") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("ExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("HideEmail") + .HasColumnType("tinyint(1)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("MaxAccessCount") + .HasColumnType("int"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Password") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DeletionDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Send", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b => + { + b.Property("Id") + .HasMaxLength(40) + .HasColumnType("varchar(40)"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("PostalCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("Rate") + .HasColumnType("decimal(65,30)"); + + b.Property("State") + .HasMaxLength(2) + .HasColumnType("varchar(2)"); + + b.HasKey("Id"); + + b.ToTable("TaxRate", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Gateway") + .HasColumnType("tinyint unsigned"); + + b.Property("GatewayId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("PaymentMethodType") + .HasColumnType("tinyint unsigned"); + + b.Property("ProviderId") + .HasColumnType("char(36)"); + + b.Property("Refunded") + .HasColumnType("tinyint(1)"); + + b.Property("RefundedAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "OrganizationId", "CreationDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Transaction", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccountRevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("AvatarColor") + .HasMaxLength(7) + .HasColumnType("varchar(7)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Culture") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailVerified") + .HasColumnType("tinyint(1)"); + + b.Property("EquivalentDomains") + .HasColumnType("longtext"); + + b.Property("ExcludedGlobalEquivalentDomains") + .HasColumnType("longtext"); + + b.Property("FailedLoginCount") + .HasColumnType("int"); + + b.Property("ForcePasswordReset") + .HasColumnType("tinyint(1)"); + + b.Property("Gateway") + .HasColumnType("tinyint unsigned"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Kdf") + .HasColumnType("tinyint unsigned"); + + b.Property("KdfIterations") + .HasColumnType("int"); + + b.Property("KdfMemory") + .HasColumnType("int"); + + b.Property("KdfParallelism") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("LastEmailChangeDate") + .HasColumnType("datetime(6)"); + + b.Property("LastFailedLoginDate") + .HasColumnType("datetime(6)"); + + b.Property("LastKdfChangeDate") + .HasColumnType("datetime(6)"); + + b.Property("LastKeyRotationDate") + .HasColumnType("datetime(6)"); + + b.Property("LastPasswordChangeDate") + .HasColumnType("datetime(6)"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Premium") + .HasColumnType("tinyint(1)"); + + b.Property("PremiumExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("PrivateKey") + .HasColumnType("longtext"); + + b.Property("PublicKey") + .HasColumnType("longtext"); + + b.Property("ReferenceData") + .HasColumnType("longtext"); + + b.Property("RenewalReminderDate") + .HasColumnType("datetime(6)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("longtext"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("UsesKeyConnector") + .HasColumnType("tinyint(1)"); + + b.Property("VerifyDevices") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique() + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("Premium", "PremiumExpirationDate", "RenewalReminderDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Body") + .HasMaxLength(3000) + .HasColumnType("varchar(3000)"); + + b.Property("ClientType") + .HasColumnType("tinyint unsigned"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Global") + .HasColumnType("tinyint(1)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Priority") + .HasColumnType("tinyint unsigned"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("TaskId") + .HasColumnType("char(36)"); + + b.Property("Title") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("TaskId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("ClientType", "Global", "UserId", "OrganizationId", "Priority", "CreationDate") + .IsDescending(false, false, false, false, true, true) + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Notification", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.NotificationStatus", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("NotificationId") + .HasColumnType("char(36)"); + + b.Property("DeletedDate") + .HasColumnType("datetime(6)"); + + b.Property("ReadDate") + .HasColumnType("datetime(6)"); + + b.HasKey("UserId", "NotificationId") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("NotificationId"); + + b.ToTable("NotificationStatus", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Platform.Installation", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("varchar(150)"); + + b.Property("LastActivityDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("Installation", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(34) + .HasColumnType("varchar(34)"); + + b.Property("Read") + .HasColumnType("tinyint(1)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Write") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.ToTable("AccessPolicy", (string)null); + + b.HasDiscriminator().HasValue("AccessPolicy"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("EncryptedPayload") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("varchar(4000)"); + + b.Property("ExpireAt") + .HasColumnType("datetime(6)"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Scope") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("varchar(4000)"); + + b.Property("ServiceAccountId") + .HasColumnType("char(36)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ServiceAccountId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("DeletedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Project", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("DeletedDate") + .HasColumnType("datetime(6)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Secret", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ServiceAccount", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Tools.Models.PasswordHealthReportApplication", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Uri") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("PasswordHealthReportApplication", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Attachments") + .HasColumnType("longtext"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("DeletedDate") + .HasColumnType("datetime(6)"); + + b.Property("Favorites") + .HasColumnType("longtext"); + + b.Property("Folders") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Reprompt") + .HasColumnType("tinyint unsigned"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CipherId") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("CipherId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("SecurityTask", (string)null); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.Property("ProjectsId") + .HasColumnType("char(36)"); + + b.Property("SecretsId") + .HasColumnType("char(36)"); + + b.HasKey("ProjectsId", "SecretsId"); + + b.HasIndex("SecretsId"); + + b.ToTable("ProjectSecret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedProjectId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedSecretId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedProjectId"); + + b.Property("ServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedSecretId"); + + b.Property("ServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedProjectId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedSecretId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegrationConfiguration", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", "OrganizationIntegration") + .WithMany() + .HasForeignKey("OrganizationIntegrationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationIntegration"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderOrganization", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") + .WithMany() + .HasForeignKey("ResponseDeviceId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("ResponseDevice"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.WebAuthnCredential", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.OrganizationInstallation", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Platform.Installation", "Installation") + .WithMany() + .HasForeignKey("InstallationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Installation"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderInvoiceItem", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderPlan", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Collections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("GroupUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Domains") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", "Task") + .WithMany() + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("Task"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.NotificationStatus", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", "Notification") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany("ApiKeys") + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Tools.Models.PasswordHealthReportApplication", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher") + .WithMany() + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedProject"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedSecret"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany("ProjectAccessPolicies") + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedSecret"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedProject"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedSecret"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Collections"); + + b.Navigation("Connections"); + + b.Navigation("Domains"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("Folders"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ProjectAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.cs b/util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.cs new file mode 100644 index 0000000000..e1577b83d3 --- /dev/null +++ b/util/MySqlMigrations/Migrations/20250603133713_AddOrgUserDefaultCollection.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.MySqlMigrations.Migrations; + +/// +public partial class AddOrgUserDefaultCollection : Migration +{ + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DefaultUserCollectionEmail", + table: "Collection", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Type", + table: "Collection", + type: "int", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DefaultUserCollectionEmail", + table: "Collection"); + + migrationBuilder.DropColumn( + name: "Type", + table: "Collection"); + } +} diff --git a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs index 48015e2cf4..a22b5baf85 100644 --- a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -956,6 +956,9 @@ namespace Bit.MySqlMigrations.Migrations b.Property("CreationDate") .HasColumnType("datetime(6)"); + b.Property("DefaultUserCollectionEmail") + .HasColumnType("longtext"); + b.Property("ExternalId") .HasMaxLength(300) .HasColumnType("varchar(300)"); @@ -970,6 +973,9 @@ namespace Bit.MySqlMigrations.Migrations b.Property("RevisionDate") .HasColumnType("datetime(6)"); + b.Property("Type") + .HasColumnType("int"); + b.HasKey("Id"); b.HasIndex("OrganizationId"); diff --git a/util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.Designer.cs b/util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.Designer.cs new file mode 100644 index 0000000000..b594f676d4 --- /dev/null +++ b/util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.Designer.cs @@ -0,0 +1,3131 @@ +// +using System; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Bit.PostgresMigrations.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20250603133704_AddOrgUserDefaultCollection")] + partial class AddOrgUserDefaultCollection + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:CollationDefinition:postgresIndetermanisticCollation", "en-u-ks-primary,en-u-ks-primary,icu,False") + .HasAnnotation("ProductVersion", "8.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllowAdminAccessToAllCollectionItems") + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BillingEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("BusinessAddress1") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessAddress2") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessAddress3") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessCountry") + .HasMaxLength(2) + .HasColumnType("character varying(2)"); + + b.Property("BusinessName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessTaxNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Gateway") + .HasColumnType("smallint"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .UseCollation("postgresIndetermanisticCollation"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("LimitCollectionCreation") + .HasColumnType("boolean"); + + b.Property("LimitCollectionDeletion") + .HasColumnType("boolean"); + + b.Property("LimitItemDeletion") + .HasColumnType("boolean"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("integer"); + + b.Property("MaxAutoscaleSmSeats") + .HasColumnType("integer"); + + b.Property("MaxAutoscaleSmServiceAccounts") + .HasColumnType("integer"); + + b.Property("MaxCollections") + .HasColumnType("smallint"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OwnersNotifiedOfAutoscaling") + .HasColumnType("timestamp with time zone"); + + b.Property("Plan") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PlanType") + .HasColumnType("smallint"); + + b.Property("PrivateKey") + .HasColumnType("text"); + + b.Property("PublicKey") + .HasColumnType("text"); + + b.Property("ReferenceData") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Seats") + .HasColumnType("integer"); + + b.Property("SelfHost") + .HasColumnType("boolean"); + + b.Property("SmSeats") + .HasColumnType("integer"); + + b.Property("SmServiceAccounts") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("text"); + + b.Property("Use2fa") + .HasColumnType("boolean"); + + b.Property("UseAdminSponsoredFamilies") + .HasColumnType("boolean"); + + b.Property("UseApi") + .HasColumnType("boolean"); + + b.Property("UseCustomPermissions") + .HasColumnType("boolean"); + + b.Property("UseDirectory") + .HasColumnType("boolean"); + + b.Property("UseEvents") + .HasColumnType("boolean"); + + b.Property("UseGroups") + .HasColumnType("boolean"); + + b.Property("UseKeyConnector") + .HasColumnType("boolean"); + + b.Property("UseOrganizationDomains") + .HasColumnType("boolean"); + + b.Property("UsePasswordManager") + .HasColumnType("boolean"); + + b.Property("UsePolicies") + .HasColumnType("boolean"); + + b.Property("UseResetPassword") + .HasColumnType("boolean"); + + b.Property("UseRiskInsights") + .HasColumnType("boolean"); + + b.Property("UseScim") + .HasColumnType("boolean"); + + b.Property("UseSecretsManager") + .HasColumnType("boolean"); + + b.Property("UseSso") + .HasColumnType("boolean"); + + b.Property("UseTotp") + .HasColumnType("boolean"); + + b.Property("UsersGetPremium") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("Id", "Enabled"); + + NpgsqlIndexBuilderExtensions.IncludeProperties(b.HasIndex("Id", "Enabled"), new[] { "UseTotp" }); + + b.ToTable("Organization", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Configuration") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("integer"); + + 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("uuid"); + + b.Property("Configuration") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .HasColumnType("integer"); + + b.Property("OrganizationIntegrationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Template") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationIntegrationId"); + + b.ToTable("OrganizationIntegrationConfiguration", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Policy", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + 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("uuid"); + + b.Property("BillingEmail") + .HasColumnType("text"); + + b.Property("BillingPhone") + .HasColumnType("text"); + + b.Property("BusinessAddress1") + .HasColumnType("text"); + + b.Property("BusinessAddress2") + .HasColumnType("text"); + + b.Property("BusinessAddress3") + .HasColumnType("text"); + + b.Property("BusinessCountry") + .HasColumnType("text"); + + b.Property("BusinessName") + .HasColumnType("text"); + + b.Property("BusinessTaxNumber") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DiscountId") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("Gateway") + .HasColumnType("smallint"); + + b.Property("GatewayCustomerId") + .HasColumnType("text"); + + b.Property("GatewaySubscriptionId") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UseEvents") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("Provider", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderOrganization", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Settings") + .HasColumnType("text"); + + 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("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + 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("uuid"); + + b.Property("AccessCode") + .HasMaxLength(25) + .HasColumnType("character varying(25)"); + + b.Property("Approved") + .HasColumnType("boolean"); + + b.Property("AuthenticationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("MasterPasswordHash") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("PublicKey") + .HasColumnType("text"); + + b.Property("RequestCountryName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequestDeviceIdentifier") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("RequestDeviceType") + .HasColumnType("smallint"); + + b.Property("RequestIpAddress") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ResponseDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ResponseDeviceId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + 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("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("GranteeId") + .HasColumnType("uuid"); + + b.Property("GrantorId") + .HasColumnType("uuid"); + + b.Property("KeyEncrypted") + .HasColumnType("text"); + + b.Property("LastNotificationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("WaitTimeDays") + .HasColumnType("integer"); + + 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("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ConsumedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(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"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + 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"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .UseCollation("postgresIndetermanisticCollation"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId"); + + b.HasIndex("OrganizationId", "ExternalId") + .IsUnique() + .HasAnnotation("SqlServer:Clustered", false); + + NpgsqlIndexBuilderExtensions.IncludeProperties(b.HasIndex("OrganizationId", "ExternalId"), new[] { "UserId" }); + + 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("uuid"); + + b.Property("AaGuid") + .HasColumnType("uuid"); + + b.Property("Counter") + .HasColumnType("integer"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CredentialId") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EncryptedPrivateKey") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("EncryptedPublicKey") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("EncryptedUserKey") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PublicKey") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SupportsPrf") + .HasColumnType("boolean"); + + b.Property("Type") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("WebAuthnCredential", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ClientOrganizationMigrationRecord", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("GatewayCustomerId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("GatewaySubscriptionId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("integer"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("PlanType") + .HasColumnType("smallint"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("Seats") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("smallint"); + + 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("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InstallationId") + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + 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("uuid"); + + b.Property("AssignedSeats") + .HasColumnType("integer"); + + b.Property("ClientId") + .HasColumnType("uuid"); + + b.Property("ClientName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Created") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PlanName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("Total") + .HasColumnType("numeric"); + + b.Property("UsedSeats") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderInvoiceItem", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderPlan", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AllocatedSeats") + .HasColumnType("integer"); + + b.Property("PlanType") + .HasColumnType("smallint"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("PurchasedSeats") + .HasColumnType("integer"); + + b.Property("SeatMinimum") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.HasIndex("Id", "PlanType") + .IsUnique(); + + b.ToTable("ProviderPlan", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cache", b => + { + b.Property("Id") + .HasMaxLength(449) + .HasColumnType("character varying(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresAtTime") + .HasColumnType("timestamp with time zone"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("bytea"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ExpiresAtTime") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Cache", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultUserCollectionEmail") + .HasColumnType("text"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("CipherId") + .HasColumnType("uuid"); + + b.HasKey("CollectionId", "CipherId"); + + b.HasIndex("CipherId"); + + b.ToTable("CollectionCipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("HidePasswords") + .HasColumnType("boolean"); + + b.Property("Manage") + .HasColumnType("boolean"); + + b.Property("ReadOnly") + .HasColumnType("boolean"); + + b.HasKey("CollectionId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("CollectionGroups"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("OrganizationUserId") + .HasColumnType("uuid"); + + b.Property("HidePasswords") + .HasColumnType("boolean"); + + b.Property("Manage") + .HasColumnType("boolean"); + + b.Property("ReadOnly") + .HasColumnType("boolean"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EncryptedPrivateKey") + .HasColumnType("text"); + + b.Property("EncryptedPublicKey") + .HasColumnType("text"); + + b.Property("EncryptedUserKey") + .HasColumnType("text"); + + b.Property("Identifier") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Identifier") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "Identifier") + .IsUnique() + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Device", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ActingUserId") + .HasColumnType("uuid"); + + b.Property("CipherId") + .HasColumnType("uuid"); + + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceType") + .HasColumnType("smallint"); + + b.Property("DomainName") + .HasColumnType("text"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("InstallationId") + .HasColumnType("uuid"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("OrganizationUserId") + .HasColumnType("uuid"); + + b.Property("PolicyId") + .HasColumnType("uuid"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("ProviderOrganizationId") + .HasColumnType("uuid"); + + b.Property("ProviderUserId") + .HasColumnType("uuid"); + + b.Property("SecretId") + .HasColumnType("uuid"); + + b.Property("ServiceAccountId") + .HasColumnType("uuid"); + + b.Property("SystemUser") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Date", "OrganizationId", "ActingUserId", "CipherId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("OrganizationUserId") + .HasColumnType("uuid"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("GroupUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Config") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationConnection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DomainName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("JobRunCount") + .HasColumnType("integer"); + + b.Property("LastCheckedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("NextRunDate") + .HasColumnType("timestamp with time zone"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Txt") + .IsRequired() + .HasColumnType("text"); + + b.Property("VerifiedDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationDomain", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("FriendlyName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("IsAdminInitiated") + .HasColumnType("boolean"); + + b.Property("LastSyncDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("OfferedToEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PlanSponsorshipType") + .HasColumnType("smallint"); + + b.Property("SponsoredOrganizationId") + .HasColumnType("uuid"); + + b.Property("SponsoringOrganizationId") + .HasColumnType("uuid"); + + b.Property("SponsoringOrganizationUserId") + .HasColumnType("uuid"); + + b.Property("ToDelete") + .HasColumnType("boolean"); + + b.Property("ValidUntil") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("SponsoredOrganizationId"); + + b.HasIndex("SponsoringOrganizationId"); + + b.HasIndex("SponsoringOrganizationUserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("OrganizationSponsorship", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessSecretsManager") + .HasColumnType("boolean"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("ResetPasswordKey") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("OrganizationUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessCount") + .HasColumnType("integer"); + + b.Property("CipherId") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DeletionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Disabled") + .HasColumnType("boolean"); + + b.Property("Emails") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HideEmail") + .HasColumnType("boolean"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("MaxAccessCount") + .HasColumnType("integer"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Password") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("DeletionDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Send", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b => + { + b.Property("Id") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PostalCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.Property("State") + .HasMaxLength(2) + .HasColumnType("character varying(2)"); + + b.HasKey("Id"); + + b.ToTable("TaxRate", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Details") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Gateway") + .HasColumnType("smallint"); + + b.Property("GatewayId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("PaymentMethodType") + .HasColumnType("smallint"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("Refunded") + .HasColumnType("boolean"); + + b.Property("RefundedAmount") + .HasColumnType("numeric"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "OrganizationId", "CreationDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Transaction", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountRevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("AvatarColor") + .HasMaxLength(7) + .HasColumnType("character varying(7)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Culture") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .UseCollation("postgresIndetermanisticCollation"); + + b.Property("EmailVerified") + .HasColumnType("boolean"); + + b.Property("EquivalentDomains") + .HasColumnType("text"); + + b.Property("ExcludedGlobalEquivalentDomains") + .HasColumnType("text"); + + b.Property("FailedLoginCount") + .HasColumnType("integer"); + + b.Property("ForcePasswordReset") + .HasColumnType("boolean"); + + b.Property("Gateway") + .HasColumnType("smallint"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Kdf") + .HasColumnType("smallint"); + + b.Property("KdfIterations") + .HasColumnType("integer"); + + b.Property("KdfMemory") + .HasColumnType("integer"); + + b.Property("KdfParallelism") + .HasColumnType("integer"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("LastEmailChangeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastFailedLoginDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastKdfChangeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastKeyRotationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastPasswordChangeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Premium") + .HasColumnType("boolean"); + + b.Property("PremiumExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PrivateKey") + .HasColumnType("text"); + + b.Property("PublicKey") + .HasColumnType("text"); + + b.Property("ReferenceData") + .HasColumnType("text"); + + b.Property("RenewalReminderDate") + .HasColumnType("timestamp with time zone"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("text"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("UsesKeyConnector") + .HasColumnType("boolean"); + + b.Property("VerifyDevices") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique() + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("Premium", "PremiumExpirationDate", "RenewalReminderDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Body") + .HasMaxLength(3000) + .HasColumnType("character varying(3000)"); + + b.Property("ClientType") + .HasColumnType("smallint"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Global") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Priority") + .HasColumnType("smallint"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("TaskId") + .HasColumnType("uuid"); + + b.Property("Title") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("TaskId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("ClientType", "Global", "UserId", "OrganizationId", "Priority", "CreationDate") + .IsDescending(false, false, false, false, true, true) + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Notification", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.NotificationStatus", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("NotificationId") + .HasColumnType("uuid"); + + b.Property("DeletedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ReadDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("UserId", "NotificationId") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("NotificationId"); + + b.ToTable("NotificationStatus", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Platform.Installation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("LastActivityDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Installation", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(34) + .HasColumnType("character varying(34)"); + + b.Property("Read") + .HasColumnType("boolean"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Write") + .HasColumnType("boolean"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.ToTable("AccessPolicy", (string)null); + + b.HasDiscriminator().HasValue("AccessPolicy"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EncryptedPayload") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("ExpireAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Scope") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("ServiceAccountId") + .HasColumnType("uuid"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ServiceAccountId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Project", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Secret", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ServiceAccount", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Tools.Models.PasswordHealthReportApplication", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Uri") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("PasswordHealthReportApplication", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Attachments") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DeletedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Favorites") + .HasColumnType("text"); + + b.Property("Folders") + .HasColumnType("text"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Reprompt") + .HasColumnType("smallint"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CipherId") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("CipherId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("SecurityTask", (string)null); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.Property("ProjectsId") + .HasColumnType("uuid"); + + b.Property("SecretsId") + .HasColumnType("uuid"); + + b.HasKey("ProjectsId", "SecretsId"); + + b.HasIndex("SecretsId"); + + b.ToTable("ProjectSecret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedProjectId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedSecretId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedProjectId"); + + b.Property("ServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedSecretId"); + + b.Property("ServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedProjectId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedSecretId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegrationConfiguration", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", "OrganizationIntegration") + .WithMany() + .HasForeignKey("OrganizationIntegrationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationIntegration"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderOrganization", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") + .WithMany() + .HasForeignKey("ResponseDeviceId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("ResponseDevice"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.WebAuthnCredential", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.OrganizationInstallation", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Platform.Installation", "Installation") + .WithMany() + .HasForeignKey("InstallationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Installation"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderInvoiceItem", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderPlan", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Collections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("GroupUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Domains") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", "Task") + .WithMany() + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("Task"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.NotificationStatus", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", "Notification") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany("ApiKeys") + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Tools.Models.PasswordHealthReportApplication", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher") + .WithMany() + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedProject"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedSecret"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany("ProjectAccessPolicies") + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedSecret"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedProject"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedSecret"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Collections"); + + b.Navigation("Connections"); + + b.Navigation("Domains"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("Folders"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ProjectAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.cs b/util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.cs new file mode 100644 index 0000000000..56bc32faf9 --- /dev/null +++ b/util/PostgresMigrations/Migrations/20250603133704_AddOrgUserDefaultCollection.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.PostgresMigrations.Migrations; + +/// +public partial class AddOrgUserDefaultCollection : Migration +{ + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DefaultUserCollectionEmail", + table: "Collection", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "Type", + table: "Collection", + type: "integer", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DefaultUserCollectionEmail", + table: "Collection"); + + migrationBuilder.DropColumn( + name: "Type", + table: "Collection"); + } +} diff --git a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs index 09f4e910c2..a016e9f350 100644 --- a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -961,6 +961,9 @@ namespace Bit.PostgresMigrations.Migrations b.Property("CreationDate") .HasColumnType("timestamp with time zone"); + b.Property("DefaultUserCollectionEmail") + .HasColumnType("text"); + b.Property("ExternalId") .HasMaxLength(300) .HasColumnType("character varying(300)"); @@ -975,6 +978,9 @@ namespace Bit.PostgresMigrations.Migrations b.Property("RevisionDate") .HasColumnType("timestamp with time zone"); + b.Property("Type") + .HasColumnType("integer"); + b.HasKey("Id"); b.HasIndex("OrganizationId"); diff --git a/util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.Designer.cs b/util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.Designer.cs new file mode 100644 index 0000000000..406703e696 --- /dev/null +++ b/util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.Designer.cs @@ -0,0 +1,3114 @@ +// +using System; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Bit.SqliteMigrations.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20250603133708_AddOrgUserDefaultCollection")] + partial class AddOrgUserDefaultCollection + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.8"); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AllowAdminAccessToAllCollectionItems") + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("BillingEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("BusinessAddress1") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessAddress2") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessAddress3") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessCountry") + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.Property("BusinessName") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessTaxNumber") + .HasMaxLength(30) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("Gateway") + .HasColumnType("INTEGER"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LimitCollectionCreation") + .HasColumnType("INTEGER"); + + b.Property("LimitCollectionDeletion") + .HasColumnType("INTEGER"); + + b.Property("LimitItemDeletion") + .HasColumnType("INTEGER"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("INTEGER"); + + b.Property("MaxAutoscaleSmSeats") + .HasColumnType("INTEGER"); + + b.Property("MaxAutoscaleSmServiceAccounts") + .HasColumnType("INTEGER"); + + b.Property("MaxCollections") + .HasColumnType("INTEGER"); + + b.Property("MaxStorageGb") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("OwnersNotifiedOfAutoscaling") + .HasColumnType("TEXT"); + + b.Property("Plan") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PlanType") + .HasColumnType("INTEGER"); + + b.Property("PrivateKey") + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasColumnType("TEXT"); + + b.Property("ReferenceData") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Seats") + .HasColumnType("INTEGER"); + + b.Property("SelfHost") + .HasColumnType("INTEGER"); + + b.Property("SmSeats") + .HasColumnType("INTEGER"); + + b.Property("SmServiceAccounts") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Storage") + .HasColumnType("INTEGER"); + + b.Property("TwoFactorProviders") + .HasColumnType("TEXT"); + + b.Property("Use2fa") + .HasColumnType("INTEGER"); + + b.Property("UseAdminSponsoredFamilies") + .HasColumnType("INTEGER"); + + b.Property("UseApi") + .HasColumnType("INTEGER"); + + b.Property("UseCustomPermissions") + .HasColumnType("INTEGER"); + + b.Property("UseDirectory") + .HasColumnType("INTEGER"); + + b.Property("UseEvents") + .HasColumnType("INTEGER"); + + b.Property("UseGroups") + .HasColumnType("INTEGER"); + + b.Property("UseKeyConnector") + .HasColumnType("INTEGER"); + + b.Property("UseOrganizationDomains") + .HasColumnType("INTEGER"); + + b.Property("UsePasswordManager") + .HasColumnType("INTEGER"); + + b.Property("UsePolicies") + .HasColumnType("INTEGER"); + + b.Property("UseResetPassword") + .HasColumnType("INTEGER"); + + b.Property("UseRiskInsights") + .HasColumnType("INTEGER"); + + b.Property("UseScim") + .HasColumnType("INTEGER"); + + b.Property("UseSecretsManager") + .HasColumnType("INTEGER"); + + b.Property("UseSso") + .HasColumnType("INTEGER"); + + b.Property("UseTotp") + .HasColumnType("INTEGER"); + + b.Property("UsersGetPremium") + .HasColumnType("INTEGER"); + + 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("TEXT"); + + b.Property("Configuration") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + 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("TEXT"); + + b.Property("Configuration") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("EventType") + .HasColumnType("INTEGER"); + + b.Property("OrganizationIntegrationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Template") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationIntegrationId"); + + b.ToTable("OrganizationIntegrationConfiguration", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Policy", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + 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("TEXT"); + + b.Property("BillingEmail") + .HasColumnType("TEXT"); + + b.Property("BillingPhone") + .HasColumnType("TEXT"); + + b.Property("BusinessAddress1") + .HasColumnType("TEXT"); + + b.Property("BusinessAddress2") + .HasColumnType("TEXT"); + + b.Property("BusinessAddress3") + .HasColumnType("TEXT"); + + b.Property("BusinessCountry") + .HasColumnType("TEXT"); + + b.Property("BusinessName") + .HasColumnType("TEXT"); + + b.Property("BusinessTaxNumber") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DiscountId") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Gateway") + .HasColumnType("INTEGER"); + + b.Property("GatewayCustomerId") + .HasColumnType("TEXT"); + + b.Property("GatewaySubscriptionId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UseEvents") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Provider", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderOrganization", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Settings") + .HasColumnType("TEXT"); + + 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("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Permissions") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + 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("TEXT"); + + b.Property("AccessCode") + .HasMaxLength(25) + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("AuthenticationDate") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("MasterPasswordHash") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasColumnType("TEXT"); + + b.Property("RequestCountryName") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("RequestDeviceIdentifier") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RequestDeviceType") + .HasColumnType("INTEGER"); + + b.Property("RequestIpAddress") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ResponseDate") + .HasColumnType("TEXT"); + + b.Property("ResponseDeviceId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + 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("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("GranteeId") + .HasColumnType("TEXT"); + + b.Property("GrantorId") + .HasColumnType("TEXT"); + + b.Property("KeyEncrypted") + .HasColumnType("TEXT"); + + b.Property("LastNotificationDate") + .HasColumnType("TEXT"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("WaitTimeDays") + .HasColumnType("INTEGER"); + + 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("INTEGER"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ConsumedDate") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + 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("TEXT"); + + b.Property("AaGuid") + .HasColumnType("TEXT"); + + b.Property("Counter") + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("CredentialId") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EncryptedPrivateKey") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("EncryptedPublicKey") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("EncryptedUserKey") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("SupportsPrf") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("WebAuthnCredential", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ClientOrganizationMigrationRecord", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("GatewayCustomerId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("GatewaySubscriptionId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("INTEGER"); + + b.Property("MaxStorageGb") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PlanType") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Seats") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + 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("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("InstallationId") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + 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("TEXT"); + + b.Property("AssignedSeats") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("TEXT"); + + b.Property("ClientName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("InvoiceId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("InvoiceNumber") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PlanName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Total") + .HasColumnType("TEXT"); + + b.Property("UsedSeats") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderInvoiceItem", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderPlan", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AllocatedSeats") + .HasColumnType("INTEGER"); + + b.Property("PlanType") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("PurchasedSeats") + .HasColumnType("INTEGER"); + + b.Property("SeatMinimum") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.HasIndex("Id", "PlanType") + .IsUnique(); + + b.ToTable("ProviderPlan", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cache", b => + { + b.Property("Id") + .HasMaxLength(449) + .HasColumnType("TEXT"); + + b.Property("AbsoluteExpiration") + .HasColumnType("TEXT"); + + b.Property("ExpiresAtTime") + .HasColumnType("TEXT"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("INTEGER"); + + b.Property("Value") + .IsRequired() + .HasColumnType("BLOB"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ExpiresAtTime") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Cache", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DefaultUserCollectionEmail") + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("CipherId") + .HasColumnType("TEXT"); + + b.HasKey("CollectionId", "CipherId"); + + b.HasIndex("CipherId"); + + b.ToTable("CollectionCipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("GroupId") + .HasColumnType("TEXT"); + + b.Property("HidePasswords") + .HasColumnType("INTEGER"); + + b.Property("Manage") + .HasColumnType("INTEGER"); + + b.Property("ReadOnly") + .HasColumnType("INTEGER"); + + b.HasKey("CollectionId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("CollectionGroups"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("OrganizationUserId") + .HasColumnType("TEXT"); + + b.Property("HidePasswords") + .HasColumnType("INTEGER"); + + b.Property("Manage") + .HasColumnType("INTEGER"); + + b.Property("ReadOnly") + .HasColumnType("INTEGER"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Active") + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("EncryptedPrivateKey") + .HasColumnType("TEXT"); + + b.Property("EncryptedPublicKey") + .HasColumnType("TEXT"); + + b.Property("EncryptedUserKey") + .HasColumnType("TEXT"); + + b.Property("Identifier") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Identifier") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "Identifier") + .IsUnique() + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Device", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActingUserId") + .HasColumnType("TEXT"); + + b.Property("CipherId") + .HasColumnType("TEXT"); + + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("DeviceType") + .HasColumnType("INTEGER"); + + b.Property("DomainName") + .HasColumnType("TEXT"); + + b.Property("GroupId") + .HasColumnType("TEXT"); + + b.Property("InstallationId") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("OrganizationUserId") + .HasColumnType("TEXT"); + + b.Property("PolicyId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("ProviderOrganizationId") + .HasColumnType("TEXT"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecretId") + .HasColumnType("TEXT"); + + b.Property("ServiceAccountId") + .HasColumnType("TEXT"); + + b.Property("SystemUser") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Date", "OrganizationId", "ActingUserId", "CipherId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("TEXT"); + + b.Property("OrganizationUserId") + .HasColumnType("TEXT"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("GroupUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Config") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationConnection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DomainName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("JobRunCount") + .HasColumnType("INTEGER"); + + b.Property("LastCheckedDate") + .HasColumnType("TEXT"); + + b.Property("NextRunDate") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Txt") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("VerifiedDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationDomain", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("FriendlyName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("IsAdminInitiated") + .HasColumnType("INTEGER"); + + b.Property("LastSyncDate") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OfferedToEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PlanSponsorshipType") + .HasColumnType("INTEGER"); + + b.Property("SponsoredOrganizationId") + .HasColumnType("TEXT"); + + b.Property("SponsoringOrganizationId") + .HasColumnType("TEXT"); + + b.Property("SponsoringOrganizationUserId") + .HasColumnType("TEXT"); + + b.Property("ToDelete") + .HasColumnType("INTEGER"); + + b.Property("ValidUntil") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SponsoredOrganizationId"); + + b.HasIndex("SponsoringOrganizationId"); + + b.HasIndex("SponsoringOrganizationUserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("OrganizationSponsorship", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessSecretsManager") + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Permissions") + .HasColumnType("TEXT"); + + b.Property("ResetPasswordKey") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("OrganizationUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessCount") + .HasColumnType("INTEGER"); + + b.Property("CipherId") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("DeletionDate") + .HasColumnType("TEXT"); + + b.Property("Disabled") + .HasColumnType("INTEGER"); + + b.Property("Emails") + .HasMaxLength(1024) + .HasColumnType("TEXT"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("HideEmail") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("MaxAccessCount") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Password") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DeletionDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Send", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b => + { + b.Property("Id") + .HasMaxLength(40) + .HasColumnType("TEXT"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PostalCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("Rate") + .HasColumnType("TEXT"); + + b.Property("State") + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TaxRate", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Details") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Gateway") + .HasColumnType("INTEGER"); + + b.Property("GatewayId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PaymentMethodType") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("Refunded") + .HasColumnType("INTEGER"); + + b.Property("RefundedAmount") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId", "OrganizationId", "CreationDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Transaction", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccountRevisionDate") + .HasColumnType("TEXT"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("TEXT"); + + b.Property("AvatarColor") + .HasMaxLength(7) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Culture") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailVerified") + .HasColumnType("INTEGER"); + + b.Property("EquivalentDomains") + .HasColumnType("TEXT"); + + b.Property("ExcludedGlobalEquivalentDomains") + .HasColumnType("TEXT"); + + b.Property("FailedLoginCount") + .HasColumnType("INTEGER"); + + b.Property("ForcePasswordReset") + .HasColumnType("INTEGER"); + + b.Property("Gateway") + .HasColumnType("INTEGER"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Kdf") + .HasColumnType("INTEGER"); + + b.Property("KdfIterations") + .HasColumnType("INTEGER"); + + b.Property("KdfMemory") + .HasColumnType("INTEGER"); + + b.Property("KdfParallelism") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("LastEmailChangeDate") + .HasColumnType("TEXT"); + + b.Property("LastFailedLoginDate") + .HasColumnType("TEXT"); + + b.Property("LastKdfChangeDate") + .HasColumnType("TEXT"); + + b.Property("LastKeyRotationDate") + .HasColumnType("TEXT"); + + b.Property("LastPasswordChangeDate") + .HasColumnType("TEXT"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("MaxStorageGb") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Premium") + .HasColumnType("INTEGER"); + + b.Property("PremiumExpirationDate") + .HasColumnType("TEXT"); + + b.Property("PrivateKey") + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasColumnType("TEXT"); + + b.Property("ReferenceData") + .HasColumnType("TEXT"); + + b.Property("RenewalReminderDate") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Storage") + .HasColumnType("INTEGER"); + + b.Property("TwoFactorProviders") + .HasColumnType("TEXT"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("UsesKeyConnector") + .HasColumnType("INTEGER"); + + b.Property("VerifyDevices") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique() + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("Premium", "PremiumExpirationDate", "RenewalReminderDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Body") + .HasMaxLength(3000) + .HasColumnType("TEXT"); + + b.Property("ClientType") + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Global") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Priority") + .HasColumnType("INTEGER"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("TaskId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("TaskId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("UserId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("ClientType", "Global", "UserId", "OrganizationId", "Priority", "CreationDate") + .IsDescending(false, false, false, false, true, true) + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Notification", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.NotificationStatus", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("NotificationId") + .HasColumnType("TEXT"); + + b.Property("DeletedDate") + .HasColumnType("TEXT"); + + b.Property("ReadDate") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "NotificationId") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("NotificationId"); + + b.ToTable("NotificationStatus", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Platform.Installation", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("TEXT"); + + b.Property("LastActivityDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Installation", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(34) + .HasColumnType("TEXT"); + + b.Property("Read") + .HasColumnType("INTEGER"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Write") + .HasColumnType("INTEGER"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.ToTable("AccessPolicy", (string)null); + + b.HasDiscriminator().HasValue("AccessPolicy"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("EncryptedPayload") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("TEXT"); + + b.Property("ExpireAt") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Scope") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("TEXT"); + + b.Property("ServiceAccountId") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ServiceAccountId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DeletedDate") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Project", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DeletedDate") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Secret", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ServiceAccount", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Tools.Models.PasswordHealthReportApplication", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Uri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("PasswordHealthReportApplication", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Attachments") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("DeletedDate") + .HasColumnType("TEXT"); + + b.Property("Favorites") + .HasColumnType("TEXT"); + + b.Property("Folders") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Reprompt") + .HasColumnType("INTEGER"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CipherId") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("CipherId") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("SecurityTask", (string)null); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.Property("ProjectsId") + .HasColumnType("TEXT"); + + b.Property("SecretsId") + .HasColumnType("TEXT"); + + b.HasKey("ProjectsId", "SecretsId"); + + b.HasIndex("SecretsId"); + + b.ToTable("ProjectSecret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedProjectId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedSecretId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedProjectId"); + + b.Property("ServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedSecretId"); + + b.Property("ServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedProjectId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserSecretAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedSecretId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedSecretId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedSecretId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_secret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegrationConfiguration", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.OrganizationIntegration", "OrganizationIntegration") + .WithMany() + .HasForeignKey("OrganizationIntegrationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OrganizationIntegration"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderOrganization", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.ProviderUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") + .WithMany() + .HasForeignKey("ResponseDeviceId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("ResponseDevice"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.WebAuthnCredential", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.OrganizationInstallation", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Platform.Installation", "Installation") + .WithMany() + .HasForeignKey("InstallationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Installation"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderInvoiceItem", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Billing.Models.ProviderPlan", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Collections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("GroupUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Domains") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", "Task") + .WithMany() + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("Task"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.NotificationStatus", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.NotificationCenter.Models.Notification", "Notification") + .WithMany() + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany("ApiKeys") + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Tools.Models.PasswordHealthReportApplication", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.SecurityTask", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", "Cipher") + .WithMany() + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedProject"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedSecret"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany("ProjectAccessPolicies") + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedSecret"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedProject"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserSecretAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", "GrantedSecret") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedSecretId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedSecret"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Collections"); + + b.Navigation("Connections"); + + b.Navigation("Domains"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("Folders"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ProjectAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.cs b/util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.cs new file mode 100644 index 0000000000..4d1b6371cf --- /dev/null +++ b/util/SqliteMigrations/Migrations/20250603133708_AddOrgUserDefaultCollection.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.SqliteMigrations.Migrations; + +/// +public partial class AddOrgUserDefaultCollection : Migration +{ + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DefaultUserCollectionEmail", + table: "Collection", + type: "TEXT", + nullable: true); + + migrationBuilder.AddColumn( + name: "Type", + table: "Collection", + type: "INTEGER", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DefaultUserCollectionEmail", + table: "Collection"); + + migrationBuilder.DropColumn( + name: "Type", + table: "Collection"); + } +} diff --git a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs index 6068941f2b..b730831439 100644 --- a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -945,6 +945,9 @@ namespace Bit.SqliteMigrations.Migrations b.Property("CreationDate") .HasColumnType("TEXT"); + b.Property("DefaultUserCollectionEmail") + .HasColumnType("TEXT"); + b.Property("ExternalId") .HasMaxLength(300) .HasColumnType("TEXT"); @@ -959,6 +962,9 @@ namespace Bit.SqliteMigrations.Migrations b.Property("RevisionDate") .HasColumnType("TEXT"); + b.Property("Type") + .HasColumnType("INTEGER"); + b.HasKey("Id"); b.HasIndex("OrganizationId"); From fbdd62fadd78ccfccd8950f61e9d8d02740314be Mon Sep 17 00:00:00 2001 From: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com> Date: Tue, 10 Jun 2025 07:50:09 +0100 Subject: [PATCH 15/19] [PM-20416]Downgraded paid org cannot upgrade from Free (#5748) * enable the downgrade of free org * resolve the free org update issue Signed-off-by: Cy Okeke * Retain the canceled subscriptionId Signed-off-by: Cy Okeke * resolve the pr coments * Refactor the code base on the pr comment Signed-off-by: Cy Okeke * Resolve the pr comments Signed-off-by: Cy Okeke * Resolve the pr comment Signed-off-by: Cy Okeke * Resolve the failing test Signed-off-by: Cy Okeke * Resolve the repeated condition Signed-off-by: Cy Okeke * apply the condition suggestion Signed-off-by: Cy Okeke * Add the missing MaxCollection --------- Signed-off-by: Cy Okeke --- .../Controllers/OrganizationsController.cs | 26 +++++++++++++++++-- .../OrganizationBillingController.cs | 22 +++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/Admin/AdminConsole/Controllers/OrganizationsController.cs b/src/Admin/AdminConsole/Controllers/OrganizationsController.cs index 6d38a77d8b..ecdd372df4 100644 --- a/src/Admin/AdminConsole/Controllers/OrganizationsController.cs +++ b/src/Admin/AdminConsole/Controllers/OrganizationsController.cs @@ -242,10 +242,32 @@ public class OrganizationsController : Controller Seats = organization.Seats }; + if (model.PlanType.HasValue) + { + var freePlan = await _pricingClient.GetPlanOrThrow(model.PlanType.Value); + var isDowngradingToFree = organization.PlanType != PlanType.Free && model.PlanType.Value == PlanType.Free; + if (isDowngradingToFree) + { + if (model.Seats.HasValue && model.Seats.Value > freePlan.PasswordManager.MaxSeats) + { + TempData["Error"] = $"Organizations with more than {freePlan.PasswordManager.MaxSeats} seats cannot be downgraded to the Free plan"; + return RedirectToAction("Edit", new { id }); + } + + if (model.MaxCollections > freePlan.PasswordManager.MaxCollections) + { + TempData["Error"] = $"Organizations with more than {freePlan.PasswordManager.MaxCollections} collections cannot be downgraded to the Free plan. Your organization currently has {organization.MaxCollections} collections."; + return RedirectToAction("Edit", new { id }); + } + + model.MaxStorageGb = null; + model.ExpirationDate = null; + model.Enabled = true; + } + } + UpdateOrganization(organization, model); - var plan = await _pricingClient.GetPlanOrThrow(organization.PlanType); - if (organization.UseSecretsManager && !plan.SupportsSecretsManager) { TempData["Error"] = "Plan does not support Secrets Manager"; diff --git a/src/Api/Billing/Controllers/OrganizationBillingController.cs b/src/Api/Billing/Controllers/OrganizationBillingController.cs index 071aae5060..f1ab1be6bd 100644 --- a/src/Api/Billing/Controllers/OrganizationBillingController.cs +++ b/src/Api/Billing/Controllers/OrganizationBillingController.cs @@ -4,6 +4,7 @@ using Bit.Api.AdminConsole.Models.Request.Organizations; using Bit.Api.Billing.Models.Requests; using Bit.Api.Billing.Models.Responses; using Bit.Api.Billing.Queries.Organizations; +using Bit.Core.Billing.Enums; using Bit.Core.Billing.Models; using Bit.Core.Billing.Models.Sales; using Bit.Core.Billing.Pricing; @@ -280,17 +281,36 @@ public class OrganizationBillingController( } var organization = await organizationRepository.GetByIdAsync(organizationId); - if (organization == null) { return Error.NotFound(); } + var existingPlan = organization.PlanType; var organizationSignup = model.ToOrganizationSignup(user); var sale = OrganizationSale.From(organization, organizationSignup); var plan = await pricingClient.GetPlanOrThrow(model.PlanType); sale.Organization.PlanType = plan.Type; sale.Organization.Plan = plan.Name; sale.SubscriptionSetup.SkipTrial = true; + if (existingPlan == PlanType.Free && organization.GatewaySubscriptionId is not null) + { + sale.Organization.UseTotp = plan.HasTotp; + sale.Organization.UseGroups = plan.HasGroups; + sale.Organization.UseDirectory = plan.HasDirectory; + sale.Organization.SelfHost = plan.HasSelfHost; + sale.Organization.UsersGetPremium = plan.UsersGetPremium; + sale.Organization.UseEvents = plan.HasEvents; + sale.Organization.Use2fa = plan.Has2fa; + sale.Organization.UseApi = plan.HasApi; + sale.Organization.UsePolicies = plan.HasPolicies; + sale.Organization.UseSso = plan.HasSso; + sale.Organization.UseResetPassword = plan.HasResetPassword; + sale.Organization.UseKeyConnector = plan.HasKeyConnector; + sale.Organization.UseScim = plan.HasScim; + sale.Organization.UseCustomPermissions = plan.HasCustomPermissions; + sale.Organization.UseOrganizationDomains = plan.HasOrganizationDomains; + sale.Organization.MaxCollections = plan.PasswordManager.MaxCollections; + } if (organizationSignup.PaymentMethodType == null || string.IsNullOrEmpty(organizationSignup.PaymentToken)) { From 021e69bc5dfea8be3b74f7a046a1cd48a206a712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rui=20Tom=C3=A9?= <108268980+r-tome@users.noreply.github.com> Date: Tue, 10 Jun 2025 09:57:29 +0100 Subject: [PATCH 16/19] [PM-17154] Limit item deletion feature flag logic removal (#5925) * Refactor CiphersController and related tests by removing unused IFeatureService dependency and associated feature flag checks. Cleaned up tests to reflect these changes, ensuring they focus on manage permissions without reliance on feature flags. * Refactor CipherService and related tests by removing feature flag checks for item deletion permissions. Updated tests to focus on user manage permissions without reliance on feature flags, ensuring cleaner and more maintainable code. * Enhance CiphersControllerTests by adding user retrieval and organization ability checks. Updated test cases to ensure proper handling of item deletion permissions based on user roles and organization settings, improving test coverage and reliability. --- .../Vault/Controllers/CiphersController.cs | 8 - .../Services/Implementations/CipherService.cs | 16 - .../Controllers/CiphersControllerTests.cs | 621 +++++++----------- .../Vault/Services/CipherServiceTests.cs | 497 +++----------- 4 files changed, 322 insertions(+), 820 deletions(-) diff --git a/src/Api/Vault/Controllers/CiphersController.cs b/src/Api/Vault/Controllers/CiphersController.cs index 7b302f3724..5991d0babb 100644 --- a/src/Api/Vault/Controllers/CiphersController.cs +++ b/src/Api/Vault/Controllers/CiphersController.cs @@ -42,7 +42,6 @@ public class CiphersController : Controller private readonly ICurrentContext _currentContext; private readonly ILogger _logger; private readonly GlobalSettings _globalSettings; - private readonly IFeatureService _featureService; private readonly IOrganizationCiphersQuery _organizationCiphersQuery; private readonly IApplicationCacheService _applicationCacheService; private readonly ICollectionRepository _collectionRepository; @@ -57,7 +56,6 @@ public class CiphersController : Controller ICurrentContext currentContext, ILogger logger, GlobalSettings globalSettings, - IFeatureService featureService, IOrganizationCiphersQuery organizationCiphersQuery, IApplicationCacheService applicationCacheService, ICollectionRepository collectionRepository) @@ -71,7 +69,6 @@ public class CiphersController : Controller _currentContext = currentContext; _logger = logger; _globalSettings = globalSettings; - _featureService = featureService; _organizationCiphersQuery = organizationCiphersQuery; _applicationCacheService = applicationCacheService; _collectionRepository = collectionRepository; @@ -375,11 +372,6 @@ public class CiphersController : Controller private async Task CanDeleteOrRestoreCipherAsAdminAsync(Guid organizationId, IEnumerable cipherIds) { - if (!_featureService.IsEnabled(FeatureFlagKeys.LimitItemDeletion)) - { - return await CanEditCipherAsAdminAsync(organizationId, cipherIds); - } - var org = _currentContext.GetOrganization(organizationId); // If we're not an "admin" or if we're a provider user we don't need to check the ciphers diff --git a/src/Core/Vault/Services/Implementations/CipherService.cs b/src/Core/Vault/Services/Implementations/CipherService.cs index 413aee3e0d..5d17441024 100644 --- a/src/Core/Vault/Services/Implementations/CipherService.cs +++ b/src/Core/Vault/Services/Implementations/CipherService.cs @@ -821,11 +821,6 @@ public class CipherService : ICipherService private async Task UserCanDeleteAsync(CipherDetails cipher, Guid userId) { - if (!_featureService.IsEnabled(FeatureFlagKeys.LimitItemDeletion)) - { - return await UserCanEditAsync(cipher, userId); - } - var user = await _userService.GetUserByIdAsync(userId); var organizationAbility = cipher.OrganizationId.HasValue ? await _applicationCacheService.GetOrganizationAbilityAsync(cipher.OrganizationId.Value) : null; @@ -835,11 +830,6 @@ public class CipherService : ICipherService private async Task UserCanRestoreAsync(CipherDetails cipher, Guid userId) { - if (!_featureService.IsEnabled(FeatureFlagKeys.LimitItemDeletion)) - { - return await UserCanEditAsync(cipher, userId); - } - var user = await _userService.GetUserByIdAsync(userId); var organizationAbility = cipher.OrganizationId.HasValue ? await _applicationCacheService.GetOrganizationAbilityAsync(cipher.OrganizationId.Value) : null; @@ -1059,17 +1049,11 @@ public class CipherService : ICipherService } // This method is used to filter ciphers based on the user's permissions to delete them. - // It supports both the old and new logic depending on the feature flag. private async Task> FilterCiphersByDeletePermission( IEnumerable ciphers, HashSet cipherIdsSet, Guid userId) where T : CipherDetails { - if (!_featureService.IsEnabled(FeatureFlagKeys.LimitItemDeletion)) - { - return ciphers.Where(c => cipherIdsSet.Contains(c.Id) && c.Edit).ToList(); - } - var user = await _userService.GetUserByIdAsync(userId); var organizationAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync(); diff --git a/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs b/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs index bca6bbc048..d1f5a212c9 100644 --- a/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs +++ b/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs @@ -4,7 +4,6 @@ using Bit.Api.Vault.Controllers; using Bit.Api.Vault.Models; using Bit.Api.Vault.Models.Request; using Bit.Api.Vault.Models.Response; -using Bit.Core; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; @@ -169,6 +168,7 @@ public class CiphersControllerTests } sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); @@ -197,65 +197,7 @@ public class CiphersControllerTests [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteAdmin_WithOwnerOrAdmin_WithEditPermission_DeletesCipher( - OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, - CurrentContextOrganization organization, SutProvider sutProvider) - { - cipherDetails.UserId = null; - cipherDetails.OrganizationId = organization.Id; - cipherDetails.Edit = true; - cipherDetails.Manage = false; - - organization.Type = organizationUserType; - - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(new List - { - cipherDetails - }); - - await sutProvider.Sut.DeleteAdmin(cipherDetails.Id); - - await sutProvider.GetDependency().Received(1).DeleteAsync(cipherDetails, userId, true); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteAdmin_WithOwnerOrAdmin_WithoutEditPermission_ThrowsNotFoundException( - OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, - CurrentContextOrganization organization, SutProvider sutProvider) - { - cipherDetails.UserId = null; - cipherDetails.OrganizationId = organization.Id; - cipherDetails.Edit = false; - cipherDetails.Manage = false; - - organization.Type = organizationUserType; - - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(new List - { - cipherDetails - }); - - await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteAdmin(cipherDetails.Id)); - - await sutProvider.GetDependency().DidNotReceive().DeleteAsync(Arg.Any(), Arg.Any(), Arg.Any()); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithManagePermission_DeletesCipher( + public async Task DeleteAdmin_WithOwnerOrAdmin_WithManagePermission_DeletesCipher( OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -266,7 +208,6 @@ public class CiphersControllerTests organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -293,7 +234,7 @@ public class CiphersControllerTests [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( + public async Task DeleteAdmin_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -304,7 +245,6 @@ public class CiphersControllerTests organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -339,11 +279,22 @@ public class CiphersControllerTests organization.Type = organizationUserType; sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); sutProvider.GetDependency() .GetManyUnassignedOrganizationDetailsByOrganizationIdAsync(organization.Id) - .Returns(new List { new() { Id = cipherDetails.Id } }); + .Returns(new List + { + new() { Id = cipherDetails.Id, OrganizationId = cipherDetails.OrganizationId } + }); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true + }); await sutProvider.Sut.DeleteAdmin(cipherDetails.Id); @@ -426,10 +377,14 @@ public class CiphersControllerTests await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteAdmin(cipher.Id)); } + + + + [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteManyAdmin_WithOwnerOrAdmin_WithEditPermission_DeletesCiphers( + public async Task DeleteManyAdmin_WithOwnerOrAdmin_WithManagePermission_DeletesCiphers( OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -437,74 +392,6 @@ public class CiphersControllerTests model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); organization.Type = organizationUserType; - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organization.Id, - Edit = true - }).ToList()); - - await sutProvider.Sut.DeleteManyAdmin(model); - - await sutProvider.GetDependency() - .Received(1) - .DeleteManyAsync( - Arg.Is>(ids => - ids.All(id => model.Ids.Contains(id.ToString())) && ids.Count() == model.Ids.Count()), - userId, organization.Id, true); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteManyAdmin_WithOwnerOrAdmin_WithoutEditPermission_ThrowsNotFoundException( - OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, - CurrentContextOrganization organization, SutProvider sutProvider) - { - model.OrganizationId = organization.Id.ToString(); - model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); - - organization.Type = organizationUserType; - - sutProvider.GetDependency() - .GetProperUserId(default) - .ReturnsForAnyArgs(userId); - - sutProvider.GetDependency() - .GetOrganization(new Guid(model.OrganizationId)) - .Returns(organization); - - sutProvider.GetDependency() - .GetManyByOrganizationIdAsync(new Guid(model.OrganizationId)) - .Returns(ciphers); - - sutProvider.GetDependency() - .GetOrganizationAbilityAsync(new Guid(model.OrganizationId)) - .Returns(new OrganizationAbility - { - Id = new Guid(model.OrganizationId), - AllowAdminAccessToAllCollectionItems = false, - }); - - await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteManyAdmin(model)); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteManyAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithManagePermission_DeletesCiphers( - OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, - CurrentContextOrganization organization, SutProvider sutProvider) - { - model.OrganizationId = organization.Id.ToString(); - model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); - organization.Type = organizationUserType; - - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -540,7 +427,7 @@ public class CiphersControllerTests [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task DeleteManyAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( + public async Task DeleteManyAdmin_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -548,7 +435,6 @@ public class CiphersControllerTests model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -586,10 +472,18 @@ public class CiphersControllerTests organization.Type = organizationUserType; sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency() .GetManyUnassignedOrganizationDetailsByOrganizationIdAsync(organization.Id) - .Returns(ciphers.Select(c => new CipherOrganizationDetails { Id = c.Id }).ToList()); + .Returns(ciphers.Select(c => new CipherOrganizationDetails { Id = c.Id, OrganizationId = organization.Id }).ToList()); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true + }); await sutProvider.Sut.DeleteManyAdmin(model); @@ -688,67 +582,14 @@ public class CiphersControllerTests await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteManyAdmin(model)); } - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteAdmin_WithOwnerOrAdmin_WithEditPermission_SoftDeletesCipher( - OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, - CurrentContextOrganization organization, SutProvider sutProvider) - { - cipherDetails.UserId = null; - cipherDetails.OrganizationId = organization.Id; - cipherDetails.Edit = true; - organization.Type = organizationUserType; - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(new List - { - cipherDetails - }); - await sutProvider.Sut.PutDeleteAdmin(cipherDetails.Id); - - await sutProvider.GetDependency().Received(1).SoftDeleteAsync(cipherDetails, userId, true); - } [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteAdmin_WithOwnerOrAdmin_WithoutEditPermission_ThrowsNotFoundException( - OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, - CurrentContextOrganization organization, SutProvider sutProvider) - { - cipherDetails.UserId = null; - cipherDetails.OrganizationId = organization.Id; - cipherDetails.Edit = false; - cipherDetails.Manage = false; - - organization.Type = organizationUserType; - - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(new List - { - cipherDetails - }); - - await Assert.ThrowsAsync(() => sutProvider.Sut.PutDeleteAdmin(cipherDetails.Id)); - - await sutProvider.GetDependency().DidNotReceive().SoftDeleteAsync(Arg.Any(), Arg.Any(), Arg.Any()); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithManagePermission_SoftDeletesCipher( + public async Task PutDeleteAdmin_WithOwnerOrAdmin_WithManagePermission_SoftDeletesCipher( OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -759,7 +600,6 @@ public class CiphersControllerTests organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -786,7 +626,7 @@ public class CiphersControllerTests [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( + public async Task PutDeleteAdmin_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -797,7 +637,6 @@ public class CiphersControllerTests organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -833,12 +672,20 @@ public class CiphersControllerTests organization.Type = organizationUserType; sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency() .GetManyUnassignedOrganizationDetailsByOrganizationIdAsync(organization.Id) - .Returns(new List { new() { Id = cipherDetails.Id } }); + .Returns(new List { new() { Id = cipherDetails.Id, OrganizationId = organization.Id } }); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true + }); await sutProvider.Sut.PutDeleteAdmin(cipherDetails.Id); @@ -856,6 +703,7 @@ public class CiphersControllerTests organization.Type = organizationUserType; sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency().GetManyByOrganizationIdAsync(organization.Id).Returns(new List { cipherDetails }); @@ -890,6 +738,70 @@ public class CiphersControllerTests await sutProvider.GetDependency().Received(1).SoftDeleteAsync(cipherDetails, userId, true); } + [Theory] + [BitAutoData(OrganizationUserType.Owner)] + [BitAutoData(OrganizationUserType.Admin)] + public async Task PutDeleteAdmin_WithOwnerOrAdmin_WithEditPermission_WithLimitItemDeletionFalse_SoftDeletesCipher( + OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, + CurrentContextOrganization organization, SutProvider sutProvider) + { + cipherDetails.UserId = null; + cipherDetails.OrganizationId = organization.Id; + cipherDetails.Edit = true; + cipherDetails.Manage = false; // Only Edit permission, not Manage + organization.Type = organizationUserType; + + sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); + sutProvider.GetDependency() + .GetManyByUserIdAsync(userId) + .Returns(new List { cipherDetails }); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = false + }); + + await sutProvider.Sut.PutDeleteAdmin(cipherDetails.Id); + + await sutProvider.GetDependency().Received(1).SoftDeleteAsync(cipherDetails, userId, true); + } + + [Theory] + [BitAutoData(OrganizationUserType.Owner)] + [BitAutoData(OrganizationUserType.Admin)] + public async Task PutDeleteAdmin_WithOwnerOrAdmin_WithEditPermission_WithLimitItemDeletionTrue_ThrowsNotFoundException( + OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, + CurrentContextOrganization organization, SutProvider sutProvider) + { + cipherDetails.UserId = null; + cipherDetails.OrganizationId = organization.Id; + cipherDetails.Edit = true; + cipherDetails.Manage = false; // Only Edit permission, not Manage + organization.Type = organizationUserType; + + sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); + sutProvider.GetDependency() + .GetManyByUserIdAsync(userId) + .Returns(new List { cipherDetails }); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true + }); + + await Assert.ThrowsAsync(() => sutProvider.Sut.PutDeleteAdmin(cipherDetails.Id)); + } + [Theory] [BitAutoData] public async Task PutDeleteAdmin_WithCustomUser_WithEditAnyCollectionFalse_ThrowsNotFoundException( @@ -922,10 +834,14 @@ public class CiphersControllerTests await Assert.ThrowsAsync(() => sutProvider.Sut.PutDeleteAdmin(cipher.Id)); } + + + + [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteManyAdmin_WithOwnerOrAdmin_WithEditPermission_SoftDeletesCiphers( + public async Task PutDeleteManyAdmin_WithOwnerOrAdmin_WithManagePermission_SoftDeletesCiphers( OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -933,65 +849,6 @@ public class CiphersControllerTests model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); organization.Type = organizationUserType; - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organization.Id, - Edit = true - }).ToList()); - - await sutProvider.Sut.PutDeleteManyAdmin(model); - - await sutProvider.GetDependency() - .Received(1) - .SoftDeleteManyAsync( - Arg.Is>(ids => - ids.All(id => model.Ids.Contains(id.ToString())) && ids.Count() == model.Ids.Count()), - userId, organization.Id, true); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteManyAdmin_WithOwnerOrAdmin_WithoutEditPermission_ThrowsNotFoundException( - OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, - CurrentContextOrganization organization, SutProvider sutProvider) - { - model.OrganizationId = organization.Id.ToString(); - model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); - organization.Type = organizationUserType; - - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organization.Id, - Edit = false - }).ToList()); - - await Assert.ThrowsAsync(() => sutProvider.Sut.PutDeleteManyAdmin(model)); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteManyAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithManagePermission_SoftDeletesCiphers( - OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, - CurrentContextOrganization organization, SutProvider sutProvider) - { - model.OrganizationId = organization.Id.ToString(); - model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); - organization.Type = organizationUserType; - - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -1027,7 +884,7 @@ public class CiphersControllerTests [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutDeleteManyAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( + public async Task PutDeleteManyAdmin_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( OrganizationUserType organizationUserType, CipherBulkDeleteRequestModel model, Guid userId, List ciphers, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -1035,7 +892,6 @@ public class CiphersControllerTests model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -1073,10 +929,18 @@ public class CiphersControllerTests organization.Type = organizationUserType; sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency() .GetManyUnassignedOrganizationDetailsByOrganizationIdAsync(organization.Id) - .Returns(ciphers.Select(c => new CipherOrganizationDetails { Id = c.Id }).ToList()); + .Returns(ciphers.Select(c => new CipherOrganizationDetails { Id = c.Id, OrganizationId = organization.Id }).ToList()); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true + }); await sutProvider.Sut.PutDeleteManyAdmin(model); @@ -1099,7 +963,14 @@ public class CiphersControllerTests model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); organization.Type = organizationUserType; + // Set organization ID on ciphers to avoid "Cipher needs to belong to a user or an organization" error + foreach (var cipher in ciphers) + { + cipher.OrganizationId = organization.Id; + } + sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency().GetManyByOrganizationIdAsync(organization.Id).Returns(ciphers); sutProvider.GetDependency().GetOrganizationAbilityAsync(organization.Id).Returns(new OrganizationAbility @@ -1130,7 +1001,14 @@ public class CiphersControllerTests organization.Type = OrganizationUserType.Custom; organization.Permissions.EditAnyCollection = true; + // Set organization ID on ciphers to avoid "Cipher needs to belong to a user or an organization" error + foreach (var cipher in ciphers) + { + cipher.OrganizationId = organization.Id; + } + sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency().GetManyByOrganizationIdAsync(organization.Id).Returns(ciphers); @@ -1175,68 +1053,14 @@ public class CiphersControllerTests await Assert.ThrowsAsync(() => sutProvider.Sut.PutDeleteManyAdmin(model)); } - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreAdmin_WithOwnerOrAdmin_WithEditPermission_RestoresCipher( - OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, - CurrentContextOrganization organization, SutProvider sutProvider) - { - cipherDetails.UserId = null; - cipherDetails.OrganizationId = organization.Id; - cipherDetails.Type = CipherType.Login; - cipherDetails.Data = JsonSerializer.Serialize(new CipherLoginData()); - cipherDetails.Edit = true; - organization.Type = organizationUserType; - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(new List - { - cipherDetails - }); - var result = await sutProvider.Sut.PutRestoreAdmin(cipherDetails.Id); - - Assert.IsType(result); - await sutProvider.GetDependency().Received(1).RestoreAsync(cipherDetails, userId, true); - } [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreAdmin_WithOwnerOrAdmin_WithoutEditPermission_ThrowsNotFoundException( - OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, - CurrentContextOrganization organization, SutProvider sutProvider) - { - cipherDetails.UserId = null; - cipherDetails.OrganizationId = organization.Id; - cipherDetails.Edit = false; - cipherDetails.Manage = false; - - organization.Type = organizationUserType; - - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(new List - { - cipherDetails - }); - - await Assert.ThrowsAsync(() => sutProvider.Sut.PutRestoreAdmin(cipherDetails.Id)); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithManagePermission_RestoresCipher( + public async Task PutRestoreAdmin_WithOwnerOrAdmin_WithManagePermission_RestoresCipher( OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -1249,7 +1073,6 @@ public class CiphersControllerTests organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -1277,7 +1100,7 @@ public class CiphersControllerTests [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( + public async Task PutRestoreAdmin_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -1288,7 +1111,6 @@ public class CiphersControllerTests organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -1323,11 +1145,19 @@ public class CiphersControllerTests organization.Type = organizationUserType; sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); sutProvider.GetDependency() .GetManyUnassignedOrganizationDetailsByOrganizationIdAsync(organization.Id) - .Returns(new List { new() { Id = cipherDetails.Id } }); + .Returns(new List { new() { Id = cipherDetails.Id, OrganizationId = organization.Id } }); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true + }); var result = await sutProvider.Sut.PutRestoreAdmin(cipherDetails.Id); @@ -1386,6 +1216,75 @@ public class CiphersControllerTests await sutProvider.GetDependency().Received(1).RestoreAsync(cipherDetails, userId, true); } + [Theory] + [BitAutoData(OrganizationUserType.Owner)] + [BitAutoData(OrganizationUserType.Admin)] + public async Task PutRestoreAdmin_WithOwnerOrAdmin_WithEditPermission_LimitItemDeletionFalse_RestoresCipher( + OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, + CurrentContextOrganization organization, SutProvider sutProvider) + { + cipherDetails.UserId = null; + cipherDetails.OrganizationId = organization.Id; + cipherDetails.Type = CipherType.Login; + cipherDetails.Data = JsonSerializer.Serialize(new CipherLoginData()); + cipherDetails.Edit = true; + cipherDetails.Manage = false; // Only Edit permission, not Manage + organization.Type = organizationUserType; + + sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); + sutProvider.GetDependency() + .GetManyByUserIdAsync(userId) + .Returns(new List { cipherDetails }); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = false // Permissive mode - Edit permission should work + }); + + var result = await sutProvider.Sut.PutRestoreAdmin(cipherDetails.Id); + + Assert.IsType(result); + await sutProvider.GetDependency().Received(1).RestoreAsync(cipherDetails, userId, true); + } + + [Theory] + [BitAutoData(OrganizationUserType.Owner)] + [BitAutoData(OrganizationUserType.Admin)] + public async Task PutRestoreAdmin_WithOwnerOrAdmin_WithEditPermission_LimitItemDeletionTrue_ThrowsNotFoundException( + OrganizationUserType organizationUserType, CipherDetails cipherDetails, Guid userId, + CurrentContextOrganization organization, SutProvider sutProvider) + { + cipherDetails.UserId = null; + cipherDetails.OrganizationId = organization.Id; + cipherDetails.Type = CipherType.Login; + cipherDetails.Data = JsonSerializer.Serialize(new CipherLoginData()); + cipherDetails.Edit = true; + cipherDetails.Manage = false; // Only Edit permission, not Manage + organization.Type = organizationUserType; + + sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); + sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); + sutProvider.GetDependency().GetByIdAsync(cipherDetails.Id, userId).Returns(cipherDetails); + sutProvider.GetDependency() + .GetManyByUserIdAsync(userId) + .Returns(new List { cipherDetails }); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true // Restrictive mode - Edit permission should NOT work + }); + + await Assert.ThrowsAsync(() => sutProvider.Sut.PutRestoreAdmin(cipherDetails.Id)); + } + [Theory] [BitAutoData] public async Task PutRestoreAdmin_WithCustomUser_WithEditAnyCollectionFalse_ThrowsNotFoundException( @@ -1420,10 +1319,14 @@ public class CiphersControllerTests await Assert.ThrowsAsync(() => sutProvider.Sut.PutRestoreAdmin(cipherDetails.Id)); } + + + + [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreManyAdmin_WithOwnerOrAdmin_WithEditPermission_RestoresCiphers( + public async Task PutRestoreManyAdmin_WithOwnerOrAdmin_WithManagePermission_RestoresCiphers( OrganizationUserType organizationUserType, CipherBulkRestoreRequestModel model, Guid userId, List ciphers, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -1431,77 +1334,6 @@ public class CiphersControllerTests model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); organization.Type = organizationUserType; - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organization.Id, - Edit = true - }).ToList()); - - var cipherOrgDetails = ciphers.Select(c => new CipherOrganizationDetails - { - Id = c.Id, - OrganizationId = organization.Id - }).ToList(); - - sutProvider.GetDependency() - .RestoreManyAsync(Arg.Is>(ids => - ids.All(id => model.Ids.Contains(id.ToString())) && ids.Count == model.Ids.Count()), - userId, organization.Id, true) - .Returns(cipherOrgDetails); - - var result = await sutProvider.Sut.PutRestoreManyAdmin(model); - - await sutProvider.GetDependency().Received(1) - .RestoreManyAsync( - Arg.Is>(ids => - ids.All(id => model.Ids.Contains(id.ToString())) && ids.Count == model.Ids.Count()), - userId, organization.Id, true); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreManyAdmin_WithOwnerOrAdmin_WithoutEditPermission_ThrowsNotFoundException( - OrganizationUserType organizationUserType, CipherBulkRestoreRequestModel model, Guid userId, List ciphers, - CurrentContextOrganization organization, SutProvider sutProvider) - { - model.OrganizationId = organization.Id; - model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); - organization.Type = organizationUserType; - - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); - sutProvider.GetDependency() - .GetManyByUserIdAsync(userId) - .Returns(ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organization.Id, - Edit = false, - Type = CipherType.Login, - Data = JsonSerializer.Serialize(new CipherLoginData()) - }).ToList()); - - await Assert.ThrowsAsync(() => sutProvider.Sut.PutRestoreManyAdmin(model)); - } - - [Theory] - [BitAutoData(OrganizationUserType.Owner)] - [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreManyAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithManagePermission_RestoresCiphers( - OrganizationUserType organizationUserType, CipherBulkRestoreRequestModel model, Guid userId, List ciphers, - CurrentContextOrganization organization, SutProvider sutProvider) - { - model.OrganizationId = organization.Id; - model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); - organization.Type = organizationUserType; - - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -1553,7 +1385,7 @@ public class CiphersControllerTests [Theory] [BitAutoData(OrganizationUserType.Owner)] [BitAutoData(OrganizationUserType.Admin)] - public async Task PutRestoreManyAdmin_WithLimitItemDeletionEnabled_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( + public async Task PutRestoreManyAdmin_WithOwnerOrAdmin_WithoutManagePermission_ThrowsNotFoundException( OrganizationUserType organizationUserType, CipherBulkRestoreRequestModel model, Guid userId, List ciphers, CurrentContextOrganization organization, SutProvider sutProvider) { @@ -1561,7 +1393,6 @@ public class CiphersControllerTests model.Ids = ciphers.Select(c => c.Id.ToString()).ToList(); organization.Type = organizationUserType; - sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.LimitItemDeletion).Returns(true); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); @@ -1599,6 +1430,7 @@ public class CiphersControllerTests organization.Type = organizationUserType; sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(new User { Id = userId }); sutProvider.GetDependency().GetOrganization(organization.Id).Returns(organization); var cipherOrgDetails = ciphers.Select(c => new CipherOrganizationDetails @@ -1614,9 +1446,16 @@ public class CiphersControllerTests .Returns(cipherOrgDetails); sutProvider.GetDependency() .RestoreManyAsync(Arg.Is>(ids => - ids.All(id => model.Ids.Contains(id.ToString()) && ids.Count == model.Ids.Count())), + ids.All(id => model.Ids.Contains(id.ToString())) && ids.Count() == model.Ids.Count()), userId, organization.Id, true) .Returns(cipherOrgDetails); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(organization.Id) + .Returns(new OrganizationAbility + { + Id = organization.Id, + LimitItemDeletion = true + }); var result = await sutProvider.Sut.PutRestoreManyAdmin(model); diff --git a/test/Core.Test/Vault/Services/CipherServiceTests.cs b/test/Core.Test/Vault/Services/CipherServiceTests.cs index 95fd8179e3..0941372963 100644 --- a/test/Core.Test/Vault/Services/CipherServiceTests.cs +++ b/test/Core.Test/Vault/Services/CipherServiceTests.cs @@ -673,13 +673,21 @@ public class CipherServiceTests [BitAutoData] public async Task RestoreAsync_UpdatesUserCipher(Guid restoringUserId, CipherDetails cipher, SutProvider sutProvider) { - sutProvider.GetDependency().GetCanEditByIdAsync(restoringUserId, cipher.Id).Returns(true); + cipher.UserId = restoringUserId; + cipher.OrganizationId = null; var initialRevisionDate = new DateTime(1970, 1, 1, 0, 0, 0); cipher.DeletedDate = initialRevisionDate; cipher.RevisionDate = initialRevisionDate; - await sutProvider.Sut.RestoreAsync(cipher, restoringUserId, cipher.OrganizationId.HasValue); + sutProvider.GetDependency() + .GetUserByIdAsync(restoringUserId) + .Returns(new User + { + Id = restoringUserId, + }); + + await sutProvider.Sut.RestoreAsync(cipher, restoringUserId); Assert.Null(cipher.DeletedDate); Assert.NotEqual(initialRevisionDate, cipher.RevisionDate); @@ -688,15 +696,28 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task RestoreAsync_UpdatesOrganizationCipher(Guid restoringUserId, CipherDetails cipher, SutProvider sutProvider) + public async Task RestoreAsync_UpdatesOrganizationCipher(Guid restoringUserId, CipherDetails cipher, User user, SutProvider sutProvider) { - sutProvider.GetDependency().GetCanEditByIdAsync(restoringUserId, cipher.Id).Returns(true); + cipher.OrganizationId = Guid.NewGuid(); + cipher.Edit = false; + cipher.Manage = true; + + sutProvider.GetDependency() + .GetUserByIdAsync(restoringUserId) + .Returns(user); + sutProvider.GetDependency() + .GetOrganizationAbilityAsync(cipher.OrganizationId.Value) + .Returns(new OrganizationAbility + { + Id = cipher.OrganizationId.Value, + LimitItemDeletion = true + }); var initialRevisionDate = new DateTime(1970, 1, 1, 0, 0, 0); cipher.DeletedDate = initialRevisionDate; cipher.RevisionDate = initialRevisionDate; - await sutProvider.Sut.RestoreAsync(cipher, restoringUserId, cipher.OrganizationId.HasValue); + await sutProvider.Sut.RestoreAsync(cipher, restoringUserId); Assert.Null(cipher.DeletedDate); Assert.NotEqual(initialRevisionDate, cipher.RevisionDate); @@ -724,24 +745,12 @@ public class CipherServiceTests cipherDetails.UserId = Guid.NewGuid(); cipherDetails.OrganizationId = null; - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.RestoreAsync(cipherDetails, restoringUserId)); - - Assert.Contains("do not have permissions", exception.Message); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().UpsertAsync(default); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().LogCipherEventAsync(default, default); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().PushSyncCipherUpdateAsync(default, default); - } - - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task RestoreAsync_WithOrgCipherLackingEditPermission_ThrowsBadRequestException( - Guid restoringUserId, CipherDetails cipherDetails, SutProvider sutProvider) - { - sutProvider.GetDependency() - .GetCanEditByIdAsync(restoringUserId, cipherDetails.Id) - .Returns(false); + sutProvider.GetDependency() + .GetUserByIdAsync(restoringUserId) + .Returns(new User + { + Id = restoringUserId, + }); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.RestoreAsync(cipherDetails, restoringUserId)); @@ -752,28 +761,6 @@ public class CipherServiceTests await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().PushSyncCipherUpdateAsync(default, default); } - [Theory] - [BitAutoData] - public async Task RestoreAsync_WithEditPermission_RestoresCipherDetails( - Guid restoringUserId, CipherDetails cipherDetails, SutProvider sutProvider) - { - sutProvider.GetDependency() - .GetCanEditByIdAsync(restoringUserId, cipherDetails.Id) - .Returns(true); - - var initialRevisionDate = new DateTime(1970, 1, 1, 0, 0, 0); - cipherDetails.DeletedDate = initialRevisionDate; - cipherDetails.RevisionDate = initialRevisionDate; - - await sutProvider.Sut.RestoreAsync(cipherDetails, restoringUserId); - - Assert.Null(cipherDetails.DeletedDate); - Assert.NotEqual(initialRevisionDate, cipherDetails.RevisionDate); - await sutProvider.GetDependency().Received(1).UpsertAsync(cipherDetails); - await sutProvider.GetDependency().Received(1).LogCipherEventAsync(cipherDetails, EventType.Cipher_Restored); - await sutProvider.GetDependency().Received(1).PushSyncCipherUpdateAsync(cipherDetails, null); - } - [Theory] [OrganizationCipherCustomize] [BitAutoData] @@ -794,7 +781,7 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task RestoreAsync_WithLimitItemDeletionEnabled_WithManagePermission_RestoresCipher( + public async Task RestoreAsync_WithManagePermission_RestoresCipher( Guid restoringUserId, CipherDetails cipherDetails, User user, SutProvider sutProvider) { cipherDetails.OrganizationId = Guid.NewGuid(); @@ -802,9 +789,6 @@ public class CipherServiceTests cipherDetails.Edit = false; cipherDetails.Manage = true; - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetUserByIdAsync(restoringUserId) .Returns(user); @@ -828,7 +812,7 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task RestoreAsync_WithLimitItemDeletionEnabled_WithoutManagePermission_ThrowsBadRequestException( + public async Task RestoreAsync_WithoutManagePermission_ThrowsBadRequestException( Guid restoringUserId, CipherDetails cipherDetails, User user, SutProvider sutProvider) { cipherDetails.OrganizationId = Guid.NewGuid(); @@ -836,9 +820,6 @@ public class CipherServiceTests cipherDetails.Edit = true; cipherDetails.Manage = false; - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetUserByIdAsync(restoringUserId) .Returns(user); @@ -859,32 +840,7 @@ public class CipherServiceTests await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().PushSyncCipherUpdateAsync(default, default); } - [Theory] - [BitAutoData] - public async Task RestoreManyAsync_UpdatesCiphers(ICollection ciphers, - SutProvider sutProvider) - { - var cipherIds = ciphers.Select(c => c.Id).ToArray(); - var restoringUserId = ciphers.First().UserId.Value; - var previousRevisionDate = DateTime.UtcNow; - foreach (var cipher in ciphers) - { - cipher.Edit = true; - cipher.RevisionDate = previousRevisionDate; - } - sutProvider.GetDependency().GetManyByUserIdAsync(restoringUserId).Returns(ciphers); - var revisionDate = previousRevisionDate + TimeSpan.FromMinutes(1); - sutProvider.GetDependency().RestoreAsync(Arg.Any>(), restoringUserId).Returns(revisionDate); - - await sutProvider.Sut.RestoreManyAsync(cipherIds, restoringUserId); - - foreach (var cipher in ciphers) - { - Assert.Null(cipher.DeletedDate); - Assert.Equal(revisionDate, cipher.RevisionDate); - } - } [Theory] [BitAutoData] @@ -971,90 +927,14 @@ public class CipherServiceTests .PushSyncCiphersAsync(restoringUserId); } - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task RestoreManyAsync_WithOrgCipherAndEditPermission_RestoresCiphers( - Guid restoringUserId, List ciphers, Guid organizationId, SutProvider sutProvider) - { - var cipherIds = ciphers.Select(c => c.Id).ToArray(); - var previousRevisionDate = DateTime.UtcNow; - foreach (var cipher in ciphers) - { - cipher.OrganizationId = organizationId; - cipher.Edit = true; - cipher.DeletedDate = DateTime.UtcNow; - cipher.RevisionDate = previousRevisionDate; - } - sutProvider.GetDependency() - .GetManyByUserIdAsync(restoringUserId) - .Returns(ciphers); - var revisionDate = previousRevisionDate + TimeSpan.FromMinutes(1); - sutProvider.GetDependency() - .RestoreAsync(Arg.Any>(), restoringUserId) - .Returns(revisionDate); - - var result = await sutProvider.Sut.RestoreManyAsync(cipherIds, restoringUserId); - - Assert.Equal(ciphers.Count, result.Count); - foreach (var cipher in result) - { - Assert.Null(cipher.DeletedDate); - Assert.Equal(revisionDate, cipher.RevisionDate); - } - - await sutProvider.GetDependency() - .Received(1) - .RestoreAsync(Arg.Is>(ids => ids.Count() == cipherIds.Count() && - ids.All(id => cipherIds.Contains(id))), restoringUserId); - await sutProvider.GetDependency() - .Received(1) - .LogCipherEventsAsync(Arg.Any>>()); - await sutProvider.GetDependency() - .Received(1) - .PushSyncCiphersAsync(restoringUserId); - } [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task RestoreManyAsync_WithOrgCipherLackingEditPermission_DoesNotRestoreCiphers( - Guid restoringUserId, List ciphers, Guid organizationId, SutProvider sutProvider) - { - var cipherIds = ciphers.Select(c => c.Id).ToArray(); - var cipherDetailsList = ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organizationId, - Edit = false, - DeletedDate = DateTime.UtcNow - }).ToList(); - - sutProvider.GetDependency() - .GetManyByUserIdAsync(restoringUserId) - .Returns(cipherDetailsList); - - var result = await sutProvider.Sut.RestoreManyAsync(cipherIds, restoringUserId); - - Assert.Empty(result); - await sutProvider.GetDependency() - .Received(1) - .RestoreAsync(Arg.Is>(ids => !ids.Any()), restoringUserId); - await sutProvider.GetDependency() - .DidNotReceiveWithAnyArgs() - .LogCipherEventsAsync(Arg.Any>>()); - await sutProvider.GetDependency() - .Received(1) - .PushSyncCiphersAsync(restoringUserId); - } - - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task RestoreManyAsync_WithLimitItemDeletionEnabled_WithManagePermission_RestoresCiphers( + public async Task RestoreManyAsync_WithManagePermission_RestoresCiphers( Guid restoringUserId, List ciphers, User user, SutProvider sutProvider) { var organizationId = Guid.NewGuid(); @@ -1070,9 +950,6 @@ public class CipherServiceTests cipher.RevisionDate = previousRevisionDate; } - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetManyByUserIdAsync(restoringUserId) .Returns(ciphers); @@ -1121,7 +998,7 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task RestoreManyAsync_WithLimitItemDeletionEnabled_WithoutManagePermission_DoesNotRestoreCiphers( + public async Task RestoreManyAsync_WithoutManagePermission_DoesNotRestoreCiphers( Guid restoringUserId, List ciphers, User user, SutProvider sutProvider) { var organizationId = Guid.NewGuid(); @@ -1135,9 +1012,6 @@ public class CipherServiceTests cipher.DeletedDate = DateTime.UtcNow; } - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetManyByUserIdAsync(restoringUserId) .Returns(ciphers); @@ -1502,23 +1376,12 @@ public class CipherServiceTests cipherDetails.UserId = deletingUserId; cipherDetails.OrganizationId = null; - await sutProvider.Sut.DeleteAsync(cipherDetails, deletingUserId); - - await sutProvider.GetDependency().Received(1).DeleteAsync(cipherDetails); - await sutProvider.GetDependency().Received(1).DeleteAttachmentsForCipherAsync(cipherDetails.Id); - await sutProvider.GetDependency().Received(1).LogCipherEventAsync(cipherDetails, EventType.Cipher_Deleted); - await sutProvider.GetDependency().Received(1).PushSyncCipherDeleteAsync(cipherDetails); - } - - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task DeleteAsync_WithOrgCipherAndEditPermission_DeletesCipher( - Guid deletingUserId, CipherDetails cipherDetails, SutProvider sutProvider) - { - sutProvider.GetDependency() - .GetCanEditByIdAsync(deletingUserId, cipherDetails.Id) - .Returns(true); + sutProvider.GetDependency() + .GetUserByIdAsync(deletingUserId) + .Returns(new User + { + Id = deletingUserId, + }); await sutProvider.Sut.DeleteAsync(cipherDetails, deletingUserId); @@ -1528,6 +1391,8 @@ public class CipherServiceTests await sutProvider.GetDependency().Received(1).PushSyncCipherDeleteAsync(cipherDetails); } + + [Theory] [BitAutoData] public async Task DeleteAsync_WithPersonalCipherBelongingToDifferentUser_ThrowsBadRequestException( @@ -1536,25 +1401,12 @@ public class CipherServiceTests cipherDetails.UserId = Guid.NewGuid(); cipherDetails.OrganizationId = null; - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.DeleteAsync(cipherDetails, deletingUserId)); - - Assert.Contains("do not have permissions", exception.Message); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteAsync(default); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteAttachmentsForCipherAsync(default); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().LogCipherEventAsync(default, default); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().PushSyncCipherDeleteAsync(default); - } - - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task DeleteAsync_WithOrgCipherLackingEditPermission_ThrowsBadRequestException( - Guid deletingUserId, CipherDetails cipherDetails, SutProvider sutProvider) - { - sutProvider.GetDependency() - .GetCanEditByIdAsync(deletingUserId, cipherDetails.Id) - .Returns(false); + sutProvider.GetDependency() + .GetUserByIdAsync(deletingUserId) + .Returns(new User + { + Id = deletingUserId, + }); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.DeleteAsync(cipherDetails, deletingUserId)); @@ -1583,16 +1435,13 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task DeleteAsync_WithLimitItemDeletionEnabled_WithManagePermission_DeletesCipher( + public async Task DeleteAsync_WithManagePermission_DeletesCipher( Guid deletingUserId, CipherDetails cipherDetails, User user, SutProvider sutProvider) { cipherDetails.OrganizationId = Guid.NewGuid(); cipherDetails.Edit = false; cipherDetails.Manage = true; - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetUserByIdAsync(deletingUserId) .Returns(user); @@ -1615,16 +1464,13 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task DeleteAsync_WithLimitItemDeletionEnabled_WithoutManagePermission_ThrowsBadRequestException( + public async Task DeleteAsync_WithoutManagePermission_ThrowsBadRequestException( Guid deletingUserId, CipherDetails cipherDetails, User user, SutProvider sutProvider) { cipherDetails.OrganizationId = Guid.NewGuid(); cipherDetails.Edit = true; cipherDetails.Manage = false; - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetUserByIdAsync(deletingUserId) .Returns(user); @@ -1691,6 +1537,12 @@ public class CipherServiceTests cipher.Edit = true; } + sutProvider.GetDependency() + .GetUserByIdAsync(deletingUserId) + .Returns(new User + { + Id = deletingUserId, + }); sutProvider.GetDependency() .GetManyByUserIdAsync(deletingUserId) .Returns(ciphers); @@ -1740,71 +1592,14 @@ public class CipherServiceTests .PushSyncCiphersAsync(deletingUserId); } - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task DeleteManyAsync_WithOrgCipherAndEditPermission_DeletesCiphers( - Guid deletingUserId, List ciphers, Guid organizationId, SutProvider sutProvider) - { - var cipherIds = ciphers.Select(c => c.Id).ToArray(); - foreach (var cipher in ciphers) - { - cipher.OrganizationId = organizationId; - cipher.Edit = true; - } - sutProvider.GetDependency() - .GetManyByUserIdAsync(deletingUserId) - .Returns(ciphers); - await sutProvider.Sut.DeleteManyAsync(cipherIds, deletingUserId, organizationId); - await sutProvider.GetDependency() - .Received(1) - .DeleteAsync(Arg.Is>(ids => ids.Count() == cipherIds.Count() && ids.All(id => cipherIds.Contains(id))), deletingUserId); - await sutProvider.GetDependency() - .Received(1) - .LogCipherEventsAsync(Arg.Any>>()); - await sutProvider.GetDependency() - .Received(1) - .PushSyncCiphersAsync(deletingUserId); - } [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task DeleteManyAsync_WithOrgCipherLackingEditPermission_DoesNotDeleteCiphers( - Guid deletingUserId, List ciphers, Guid organizationId, SutProvider sutProvider) - { - var cipherIds = ciphers.Select(c => c.Id).ToArray(); - var cipherDetailsList = ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organizationId, - Edit = false - }).ToList(); - - sutProvider.GetDependency() - .GetManyByUserIdAsync(deletingUserId) - .Returns(cipherDetailsList); - - await sutProvider.Sut.DeleteManyAsync(cipherIds, deletingUserId, organizationId); - - await sutProvider.GetDependency() - .Received(1) - .DeleteAsync(Arg.Is>(ids => !ids.Any()), deletingUserId); - await sutProvider.GetDependency() - .DidNotReceiveWithAnyArgs() - .LogCipherEventsAsync(Arg.Any>>()); - await sutProvider.GetDependency() - .Received(1) - .PushSyncCiphersAsync(deletingUserId); - } - - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task DeleteManyAsync_WithLimitItemDeletionEnabled_WithoutManagePermission_DoesNotDeleteCiphers( + public async Task DeleteManyAsync_WithoutManagePermission_DoesNotDeleteCiphers( Guid deletingUserId, List ciphers, User user, SutProvider sutProvider) { var organizationId = Guid.NewGuid(); @@ -1817,9 +1612,6 @@ public class CipherServiceTests cipher.Manage = false; } - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetManyByUserIdAsync(deletingUserId) .Returns(ciphers); @@ -1855,7 +1647,7 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task DeleteManyAsync_WithLimitItemDeletionEnabled_WithManagePermission_DeletesCiphers( + public async Task DeleteManyAsync_WithManagePermission_DeletesCiphers( Guid deletingUserId, List ciphers, User user, SutProvider sutProvider) { var organizationId = Guid.NewGuid(); @@ -1868,9 +1660,6 @@ public class CipherServiceTests cipher.Manage = true; } - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetManyByUserIdAsync(deletingUserId) .Returns(ciphers); @@ -1913,9 +1702,12 @@ public class CipherServiceTests cipherDetails.OrganizationId = null; cipherDetails.DeletedDate = null; - sutProvider.GetDependency() - .GetCanEditByIdAsync(deletingUserId, cipherDetails.Id) - .Returns(true); + sutProvider.GetDependency() + .GetUserByIdAsync(deletingUserId) + .Returns(new User + { + Id = deletingUserId, + }); await sutProvider.Sut.SoftDeleteAsync(cipherDetails, deletingUserId); @@ -1926,26 +1718,7 @@ public class CipherServiceTests await sutProvider.GetDependency().Received(1).PushSyncCipherUpdateAsync(cipherDetails, null); } - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task SoftDeleteAsync_WithOrgCipherAndEditPermission_SoftDeletesCipher( - Guid deletingUserId, CipherDetails cipherDetails, SutProvider sutProvider) - { - cipherDetails.DeletedDate = null; - sutProvider.GetDependency() - .GetCanEditByIdAsync(deletingUserId, cipherDetails.Id) - .Returns(true); - - await sutProvider.Sut.SoftDeleteAsync(cipherDetails, deletingUserId); - - Assert.NotNull(cipherDetails.DeletedDate); - Assert.Equal(cipherDetails.RevisionDate, cipherDetails.DeletedDate); - await sutProvider.GetDependency().Received(1).UpsertAsync(cipherDetails); - await sutProvider.GetDependency().Received(1).LogCipherEventAsync(cipherDetails, EventType.Cipher_SoftDeleted); - await sutProvider.GetDependency().Received(1).PushSyncCipherUpdateAsync(cipherDetails, null); - } [Theory] [BitAutoData] @@ -1955,9 +1728,12 @@ public class CipherServiceTests cipherDetails.UserId = Guid.NewGuid(); cipherDetails.OrganizationId = null; - sutProvider.GetDependency() - .GetCanEditByIdAsync(deletingUserId, cipherDetails.Id) - .Returns(false); + sutProvider.GetDependency() + .GetUserByIdAsync(deletingUserId) + .Returns(new User + { + Id = deletingUserId, + }); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.SoftDeleteAsync(cipherDetails, deletingUserId)); @@ -1965,48 +1741,23 @@ public class CipherServiceTests Assert.Contains("do not have permissions", exception.Message); } - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task SoftDeleteAsync_WithOrgCipherLackingEditPermission_ThrowsBadRequestException( - Guid deletingUserId, CipherDetails cipherDetails, SutProvider sutProvider) - { - sutProvider.GetDependency() - .GetCanEditByIdAsync(deletingUserId, cipherDetails.Id) - .Returns(false); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.SoftDeleteAsync(cipherDetails, deletingUserId)); - - Assert.Contains("do not have permissions", exception.Message); - } - - [Theory] - [BitAutoData] - public async Task SoftDeleteAsync_WithEditPermission_SoftDeletesCipherDetails( - Guid deletingUserId, CipherDetails cipherDetails, SutProvider sutProvider) - { - cipherDetails.DeletedDate = null; - - await sutProvider.Sut.SoftDeleteAsync(cipherDetails, deletingUserId, true); - - Assert.NotNull(cipherDetails.DeletedDate); - Assert.Equal(cipherDetails.RevisionDate, cipherDetails.DeletedDate); - await sutProvider.GetDependency().Received(1).UpsertAsync(cipherDetails); - await sutProvider.GetDependency().Received(1).LogCipherEventAsync(cipherDetails, EventType.Cipher_SoftDeleted); - await sutProvider.GetDependency().Received(1).PushSyncCipherUpdateAsync(cipherDetails, null); - } - [Theory] [BitAutoData] public async Task SoftDeleteAsync_WithAlreadySoftDeletedCipher_SkipsOperation( Guid deletingUserId, CipherDetails cipherDetails, SutProvider sutProvider) { - sutProvider.GetDependency() - .GetCanEditByIdAsync(deletingUserId, cipherDetails.Id) - .Returns(true); + // Set up as personal cipher owned by the deleting user + cipherDetails.UserId = deletingUserId; + cipherDetails.OrganizationId = null; cipherDetails.DeletedDate = DateTime.UtcNow.AddDays(-1); + sutProvider.GetDependency() + .GetUserByIdAsync(deletingUserId) + .Returns(new User + { + Id = deletingUserId, + }); + await sutProvider.Sut.SoftDeleteAsync(cipherDetails, deletingUserId); await sutProvider.GetDependency().DidNotReceive().UpsertAsync(Arg.Any()); @@ -2032,7 +1783,7 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task SoftDeleteAsync_WithLimitItemDeletionEnabled_WithManagePermission_SoftDeletesCipher( + public async Task SoftDeleteAsync_WithManagePermission_SoftDeletesCipher( Guid deletingUserId, CipherDetails cipherDetails, User user, SutProvider sutProvider) { cipherDetails.OrganizationId = Guid.NewGuid(); @@ -2040,9 +1791,6 @@ public class CipherServiceTests cipherDetails.Edit = false; cipherDetails.Manage = true; - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetUserByIdAsync(deletingUserId) .Returns(user); @@ -2066,7 +1814,7 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task SoftDeleteAsync_WithLimitItemDeletionEnabled_WithoutManagePermission_ThrowsBadRequestException( + public async Task SoftDeleteAsync_WithoutManagePermission_ThrowsBadRequestException( Guid deletingUserId, CipherDetails cipherDetails, User user, SutProvider sutProvider) { cipherDetails.OrganizationId = Guid.NewGuid(); @@ -2074,9 +1822,6 @@ public class CipherServiceTests cipherDetails.Edit = true; cipherDetails.Manage = false; - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetUserByIdAsync(deletingUserId) .Returns(user); @@ -2143,6 +1888,12 @@ public class CipherServiceTests cipher.DeletedDate = null; } + sutProvider.GetDependency() + .GetUserByIdAsync(deletingUserId) + .Returns(new User + { + Id = deletingUserId, + }); sutProvider.GetDependency() .GetManyByUserIdAsync(deletingUserId) .Returns(ciphers); @@ -2192,72 +1943,14 @@ public class CipherServiceTests .PushSyncCiphersAsync(deletingUserId); } - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task SoftDeleteManyAsync_WithOrgCipherAndEditPermission_SoftDeletesCiphers( - Guid deletingUserId, List ciphers, Guid organizationId, SutProvider sutProvider) - { - var cipherIds = ciphers.Select(c => c.Id).ToArray(); - foreach (var cipher in ciphers) - { - cipher.OrganizationId = organizationId; - cipher.Edit = true; - cipher.DeletedDate = null; - } - sutProvider.GetDependency() - .GetManyByUserIdAsync(deletingUserId) - .Returns(ciphers); - await sutProvider.Sut.SoftDeleteManyAsync(cipherIds, deletingUserId, organizationId, false); - await sutProvider.GetDependency() - .Received(1) - .SoftDeleteAsync(Arg.Is>(ids => ids.Count() == cipherIds.Count() && ids.All(id => cipherIds.Contains(id))), deletingUserId); - await sutProvider.GetDependency() - .Received(1) - .LogCipherEventsAsync(Arg.Any>>()); - await sutProvider.GetDependency() - .Received(1) - .PushSyncCiphersAsync(deletingUserId); - } [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task SoftDeleteManyAsync_WithOrgCipherLackingEditPermission_DoesNotDeleteCiphers( - Guid deletingUserId, List ciphers, Guid organizationId, SutProvider sutProvider) - { - var cipherIds = ciphers.Select(c => c.Id).ToArray(); - var cipherDetailsList = ciphers.Select(c => new CipherDetails - { - Id = c.Id, - OrganizationId = organizationId, - Edit = false - }).ToList(); - - sutProvider.GetDependency() - .GetManyByUserIdAsync(deletingUserId) - .Returns(cipherDetailsList); - - await sutProvider.Sut.SoftDeleteManyAsync(cipherIds, deletingUserId, organizationId, false); - - await sutProvider.GetDependency() - .Received(1) - .SoftDeleteAsync(Arg.Is>(ids => !ids.Any()), deletingUserId); - await sutProvider.GetDependency() - .DidNotReceiveWithAnyArgs() - .LogCipherEventsAsync(Arg.Any>>()); - await sutProvider.GetDependency() - .Received(1) - .PushSyncCiphersAsync(deletingUserId); - } - - [Theory] - [OrganizationCipherCustomize] - [BitAutoData] - public async Task SoftDeleteManyAsync_WithLimitItemDeletionEnabled_WithoutManagePermission_DoesNotDeleteCiphers( + public async Task SoftDeleteManyAsync_WithoutManagePermission_DoesNotDeleteCiphers( Guid deletingUserId, List ciphers, User user, SutProvider sutProvider) { var organizationId = Guid.NewGuid(); @@ -2270,9 +1963,6 @@ public class CipherServiceTests cipher.Manage = false; } - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetManyByUserIdAsync(deletingUserId) .Returns(ciphers); @@ -2308,7 +1998,7 @@ public class CipherServiceTests [Theory] [OrganizationCipherCustomize] [BitAutoData] - public async Task SoftDeleteManyAsync_WithLimitItemDeletionEnabled_WithManagePermission_SoftDeletesCiphers( + public async Task SoftDeleteManyAsync_WithManagePermission_SoftDeletesCiphers( Guid deletingUserId, List ciphers, User user, SutProvider sutProvider) { var organizationId = Guid.NewGuid(); @@ -2322,9 +2012,6 @@ public class CipherServiceTests cipher.DeletedDate = null; } - sutProvider.GetDependency() - .IsEnabled(FeatureFlagKeys.LimitItemDeletion) - .Returns(true); sutProvider.GetDependency() .GetManyByUserIdAsync(deletingUserId) .Returns(ciphers); From 4277f435abbc3c280127ee9e97d0ed087e97b951 Mon Sep 17 00:00:00 2001 From: Graham Walker Date: Tue, 10 Jun 2025 12:36:49 -0500 Subject: [PATCH 17/19] PM-22564 Fix Namespaces from Tools to Dirt (#5947) * PM-22564 fixing namespaces * PM-22564 fixing namespace in integration test * PM-22564 fixing .sqlproj file --- src/Api/Dirt/Controllers/HibpController.cs | 2 +- src/Api/Dirt/Controllers/ReportsController.cs | 20 +++++++------- .../PasswordHealthReportApplicationModel.cs | 2 +- .../Response/MemberAccessReportModel.cs | 6 ++--- .../MemberCipherDetailsResponseModel.cs | 4 +-- src/Api/Startup.cs | 2 +- .../PasswordHealthReportApplication.cs | 8 +++--- .../Models/Data/MemberAccessCipherDetails.cs | 8 +++--- ...dPasswordHealthReportApplicationCommand.cs | 12 ++++----- ...pPasswordHealthReportApplicationCommand.cs | 10 +++---- ...GetPasswordHealthReportApplicationQuery.cs | 10 +++---- ...dPasswordHealthReportApplicationCommand.cs | 6 ++--- ...pPasswordHealthReportApplicationCommand.cs | 4 +-- ...GetPasswordHealthReportApplicationQuery.cs | 4 +-- .../MemberAccessCipherDetailsQuery.cs | 8 +++--- .../IMemberAccessCipherDetailsQuery.cs | 6 ++--- .../ReportingServiceCollectionExtensions.cs | 6 ++--- ...dPasswordHealthReportApplicationRequest.cs | 2 +- ...pPasswordHealthReportApplicationRequest.cs | 2 +- .../MemberAccessCipherDetailsRequest.cs | 2 +- ...sswordHealthReportApplicationRepository.cs | 6 ++--- .../DapperServiceCollectionExtensions.cs | 2 ++ ...sswordHealthReportApplicationRepository.cs | 12 ++++----- ...eportApplicationEntityTypeConfiguration.cs | 4 +-- .../Models/PasswordHealthReportApplication.cs | 6 ++--- ...sswordHealthReportApplicationRepository.cs | 13 +++++---- ...ityFrameworkServiceCollectionExtensions.cs | 2 ++ .../Repositories/DatabaseContext.cs | 2 +- .../Utilities/ServiceCollectionExtensions.cs | 2 +- test/Api.Test/Dirt/ReportsControllerTests.cs | 17 ++++++------ ...wordHealthReportApplicationCommandTests.cs | 10 +++---- ...wordHealthReportApplicationCommandTests.cs | 10 +++---- ...sswordHealthReportApplicationQueryTests.cs | 8 +++--- .../EntityFrameworkRepositoryFixtures.cs | 2 +- ...PasswordHealthReportApplicationFixtures.cs | 4 +-- ...dHealthReportApplicationRepositoryTests.cs | 27 +++++++++---------- 36 files changed, 127 insertions(+), 124 deletions(-) rename src/Infrastructure.EntityFramework/{Tools => Dirt}/Configurations/PasswordHealthReportApplicationEntityTypeConfiguration.cs (83%) rename src/Infrastructure.EntityFramework/{Tools => Dirt}/Models/PasswordHealthReportApplication.cs (52%) rename src/Infrastructure.EntityFramework/{Tools => Dirt}/Repositories/PasswordHealthReportApplicationRepository.cs (58%) rename test/Infrastructure.EFIntegration.Test/{Tools => Dirt}/Repositories/PasswordHealthReportApplicationRepositoryTests.cs (91%) diff --git a/src/Api/Dirt/Controllers/HibpController.cs b/src/Api/Dirt/Controllers/HibpController.cs index f12027cb31..e0ec40d0ab 100644 --- a/src/Api/Dirt/Controllers/HibpController.cs +++ b/src/Api/Dirt/Controllers/HibpController.cs @@ -8,7 +8,7 @@ using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace Bit.Api.Tools.Controllers; +namespace Bit.Api.Dirt.Controllers; [Route("hibp")] [Authorize("Application")] diff --git a/src/Api/Dirt/Controllers/ReportsController.cs b/src/Api/Dirt/Controllers/ReportsController.cs index 4c0a802da2..2f7a5a4328 100644 --- a/src/Api/Dirt/Controllers/ReportsController.cs +++ b/src/Api/Dirt/Controllers/ReportsController.cs @@ -1,16 +1,16 @@ -using Bit.Api.Tools.Models; -using Bit.Api.Tools.Models.Response; +using Bit.Api.Dirt.Models; +using Bit.Api.Dirt.Models.Response; using Bit.Core.Context; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.Models.Data; +using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.OrganizationReportMembers.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; using Bit.Core.Exceptions; -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.Models.Data; -using Bit.Core.Tools.ReportFeatures.Interfaces; -using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces; -using Bit.Core.Tools.ReportFeatures.Requests; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace Bit.Api.Tools.Controllers; +namespace Bit.Api.Dirt.Controllers; [Route("reports")] [Authorize("Application")] @@ -47,7 +47,7 @@ public class ReportsController : Controller [HttpGet("member-cipher-details/{orgId}")] public async Task> GetMemberCipherDetails(Guid orgId) { - // Using the AccessReports permission here until new permissions + // Using the AccessReports permission here until new permissions // are needed for more control over reports if (!await _currentContext.AccessReports(orgId)) { @@ -84,7 +84,7 @@ public class ReportsController : Controller } /// - /// Contains the organization member info, the cipher ids associated with the member, + /// Contains the organization member info, the cipher ids associated with the member, /// and details on their collections, groups, and permissions /// /// Request to the MemberAccessCipherDetailsQuery diff --git a/src/Api/Dirt/Models/PasswordHealthReportApplicationModel.cs b/src/Api/Dirt/Models/PasswordHealthReportApplicationModel.cs index 93467e1175..5dbc07afb5 100644 --- a/src/Api/Dirt/Models/PasswordHealthReportApplicationModel.cs +++ b/src/Api/Dirt/Models/PasswordHealthReportApplicationModel.cs @@ -1,4 +1,4 @@ -namespace Bit.Api.Tools.Models; +namespace Bit.Api.Dirt.Models; public class PasswordHealthReportApplicationModel { diff --git a/src/Api/Dirt/Models/Response/MemberAccessReportModel.cs b/src/Api/Dirt/Models/Response/MemberAccessReportModel.cs index b110c316c1..b8356e5d44 100644 --- a/src/Api/Dirt/Models/Response/MemberAccessReportModel.cs +++ b/src/Api/Dirt/Models/Response/MemberAccessReportModel.cs @@ -1,10 +1,10 @@ -using Bit.Core.Tools.Models.Data; +using Bit.Core.Dirt.Reports.Models.Data; -namespace Bit.Api.Tools.Models.Response; +namespace Bit.Api.Dirt.Models.Response; /// /// Contains the collections and group collections a user has access to including -/// the permission level for the collection and group collection. +/// the permission level for the collection and group collection. /// public class MemberAccessReportResponseModel { diff --git a/src/Api/Dirt/Models/Response/MemberCipherDetailsResponseModel.cs b/src/Api/Dirt/Models/Response/MemberCipherDetailsResponseModel.cs index d927da8123..30065ad05a 100644 --- a/src/Api/Dirt/Models/Response/MemberCipherDetailsResponseModel.cs +++ b/src/Api/Dirt/Models/Response/MemberCipherDetailsResponseModel.cs @@ -1,6 +1,6 @@ -using Bit.Core.Tools.Models.Data; +using Bit.Core.Dirt.Reports.Models.Data; -namespace Bit.Api.Tools.Models.Response; +namespace Bit.Api.Dirt.Models.Response; public class MemberCipherDetailsResponseModel { diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index e24f96a7a9..c2a75c9278 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -31,8 +31,8 @@ using Bit.Api.Billing; using Bit.Core.Auth.Models.Data; using Bit.Core.Auth.Identity.TokenProviders; using Bit.Core.Tools.ImportFeatures; -using Bit.Core.Tools.ReportFeatures; using Bit.Core.Auth.Models.Api.Request; +using Bit.Core.Dirt.Reports.ReportFeatures; using Bit.Core.Tools.SendFeatures; #if !OSS diff --git a/src/Core/Dirt/Reports/Entities/PasswordHealthReportApplication.cs b/src/Core/Dirt/Reports/Entities/PasswordHealthReportApplication.cs index 9d89edf633..db605d6b74 100644 --- a/src/Core/Dirt/Reports/Entities/PasswordHealthReportApplication.cs +++ b/src/Core/Dirt/Reports/Entities/PasswordHealthReportApplication.cs @@ -1,9 +1,9 @@ -using Bit.Core.Entities; +#nullable enable + +using Bit.Core.Entities; using Bit.Core.Utilities; -#nullable enable - -namespace Bit.Core.Tools.Entities; +namespace Bit.Core.Dirt.Reports.Entities; public class PasswordHealthReportApplication : ITableObject, IRevisable { diff --git a/src/Core/Dirt/Reports/Models/Data/MemberAccessCipherDetails.cs b/src/Core/Dirt/Reports/Models/Data/MemberAccessCipherDetails.cs index 943d56c53e..759337d5cf 100644 --- a/src/Core/Dirt/Reports/Models/Data/MemberAccessCipherDetails.cs +++ b/src/Core/Dirt/Reports/Models/Data/MemberAccessCipherDetails.cs @@ -1,4 +1,4 @@ -namespace Bit.Core.Tools.Models.Data; +namespace Bit.Core.Dirt.Reports.Models.Data; public class MemberAccessDetails { @@ -30,13 +30,13 @@ public class MemberAccessCipherDetails public bool UsesKeyConnector { get; set; } /// - /// The details for the member's collection access depending - /// on the collections and groups they are assigned to + /// The details for the member's collection access depending + /// on the collections and groups they are assigned to /// public IEnumerable AccessDetails { get; set; } /// - /// A distinct list of the cipher ids associated with + /// A distinct list of the cipher ids associated with /// the organization member /// public IEnumerable CipherIds { get; set; } diff --git a/src/Core/Dirt/Reports/ReportFeatures/AddPasswordHealthReportApplicationCommand.cs b/src/Core/Dirt/Reports/ReportFeatures/AddPasswordHealthReportApplicationCommand.cs index b191799ba0..f8232ffa92 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/AddPasswordHealthReportApplicationCommand.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/AddPasswordHealthReportApplicationCommand.cs @@ -1,11 +1,11 @@ -using Bit.Core.Exceptions; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; +using Bit.Core.Dirt.Reports.Repositories; +using Bit.Core.Exceptions; using Bit.Core.Repositories; -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.ReportFeatures.Interfaces; -using Bit.Core.Tools.ReportFeatures.Requests; -using Bit.Core.Tools.Repositories; -namespace Bit.Core.Tools.ReportFeatures; +namespace Bit.Core.Dirt.Reports.ReportFeatures; public class AddPasswordHealthReportApplicationCommand : IAddPasswordHealthReportApplicationCommand { diff --git a/src/Core/Dirt/Reports/ReportFeatures/DropPasswordHealthReportApplicationCommand.cs b/src/Core/Dirt/Reports/ReportFeatures/DropPasswordHealthReportApplicationCommand.cs index 73a8f84e6a..55914dca37 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/DropPasswordHealthReportApplicationCommand.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/DropPasswordHealthReportApplicationCommand.cs @@ -1,9 +1,9 @@ -using Bit.Core.Exceptions; -using Bit.Core.Tools.ReportFeatures.Interfaces; -using Bit.Core.Tools.ReportFeatures.Requests; -using Bit.Core.Tools.Repositories; +using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; +using Bit.Core.Dirt.Reports.Repositories; +using Bit.Core.Exceptions; -namespace Bit.Core.Tools.ReportFeatures; +namespace Bit.Core.Dirt.Reports.ReportFeatures; public class DropPasswordHealthReportApplicationCommand : IDropPasswordHealthReportApplicationCommand { diff --git a/src/Core/Dirt/Reports/ReportFeatures/GetPasswordHealthReportApplicationQuery.cs b/src/Core/Dirt/Reports/ReportFeatures/GetPasswordHealthReportApplicationQuery.cs index 5baf5b2f72..d9b5e79a0c 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/GetPasswordHealthReportApplicationQuery.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/GetPasswordHealthReportApplicationQuery.cs @@ -1,9 +1,9 @@ -using Bit.Core.Exceptions; -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.ReportFeatures.Interfaces; -using Bit.Core.Tools.Repositories; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; +using Bit.Core.Dirt.Reports.Repositories; +using Bit.Core.Exceptions; -namespace Bit.Core.Tools.ReportFeatures; +namespace Bit.Core.Dirt.Reports.ReportFeatures; public class GetPasswordHealthReportApplicationQuery : IGetPasswordHealthReportApplicationQuery { diff --git a/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IAddPasswordHealthReportApplicationCommand.cs b/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IAddPasswordHealthReportApplicationCommand.cs index 9d145a79b6..0a4aa29f2f 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IAddPasswordHealthReportApplicationCommand.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IAddPasswordHealthReportApplicationCommand.cs @@ -1,7 +1,7 @@ -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.ReportFeatures.Requests; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; -namespace Bit.Core.Tools.ReportFeatures.Interfaces; +namespace Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; public interface IAddPasswordHealthReportApplicationCommand { diff --git a/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IDropPasswordHealthReportApplicationCommand.cs b/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IDropPasswordHealthReportApplicationCommand.cs index 0adf09cab8..8e97e32ac7 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IDropPasswordHealthReportApplicationCommand.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IDropPasswordHealthReportApplicationCommand.cs @@ -1,6 +1,6 @@ -using Bit.Core.Tools.ReportFeatures.Requests; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; -namespace Bit.Core.Tools.ReportFeatures.Interfaces; +namespace Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; public interface IDropPasswordHealthReportApplicationCommand { diff --git a/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IGetPasswordHealthReportApplicationQuery.cs b/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IGetPasswordHealthReportApplicationQuery.cs index f24119c2b7..ae2f759756 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IGetPasswordHealthReportApplicationQuery.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/Interfaces/IGetPasswordHealthReportApplicationQuery.cs @@ -1,6 +1,6 @@ -using Bit.Core.Tools.Entities; +using Bit.Core.Dirt.Reports.Entities; -namespace Bit.Core.Tools.ReportFeatures.Interfaces; +namespace Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; public interface IGetPasswordHealthReportApplicationQuery { diff --git a/src/Core/Dirt/Reports/ReportFeatures/MemberAccessCipherDetailsQuery.cs b/src/Core/Dirt/Reports/ReportFeatures/MemberAccessCipherDetailsQuery.cs index 0c165a7dc2..4a8039e6bc 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/MemberAccessCipherDetailsQuery.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/MemberAccessCipherDetailsQuery.cs @@ -2,21 +2,21 @@ using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Repositories; using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces; +using Bit.Core.Dirt.Reports.Models.Data; +using Bit.Core.Dirt.Reports.ReportFeatures.OrganizationReportMembers.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; using Bit.Core.Entities; using Bit.Core.Models.Data; using Bit.Core.Models.Data.Organizations; using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Repositories; using Bit.Core.Services; -using Bit.Core.Tools.Models.Data; -using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces; -using Bit.Core.Tools.ReportFeatures.Requests; using Bit.Core.Vault.Models.Data; using Bit.Core.Vault.Queries; using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces; using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Requests; -namespace Bit.Core.Tools.ReportFeatures; +namespace Bit.Core.Dirt.Reports.ReportFeatures; public class MemberAccessCipherDetailsQuery : IMemberAccessCipherDetailsQuery { diff --git a/src/Core/Dirt/Reports/ReportFeatures/OrganizationReportMembers/Interfaces/IMemberAccessCipherDetailsQuery.cs b/src/Core/Dirt/Reports/ReportFeatures/OrganizationReportMembers/Interfaces/IMemberAccessCipherDetailsQuery.cs index c55495fd13..98ed780db3 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/OrganizationReportMembers/Interfaces/IMemberAccessCipherDetailsQuery.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/OrganizationReportMembers/Interfaces/IMemberAccessCipherDetailsQuery.cs @@ -1,7 +1,7 @@ -using Bit.Core.Tools.Models.Data; -using Bit.Core.Tools.ReportFeatures.Requests; +using Bit.Core.Dirt.Reports.Models.Data; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; -namespace Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces; +namespace Bit.Core.Dirt.Reports.ReportFeatures.OrganizationReportMembers.Interfaces; public interface IMemberAccessCipherDetailsQuery { diff --git a/src/Core/Dirt/Reports/ReportFeatures/ReportingServiceCollectionExtensions.cs b/src/Core/Dirt/Reports/ReportFeatures/ReportingServiceCollectionExtensions.cs index 4970f0515b..d847c8051e 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/ReportingServiceCollectionExtensions.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/ReportingServiceCollectionExtensions.cs @@ -1,8 +1,8 @@ -using Bit.Core.Tools.ReportFeatures.Interfaces; -using Bit.Core.Tools.ReportFeatures.OrganizationReportMembers.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.OrganizationReportMembers.Interfaces; using Microsoft.Extensions.DependencyInjection; -namespace Bit.Core.Tools.ReportFeatures; +namespace Bit.Core.Dirt.Reports.ReportFeatures; public static class ReportingServiceCollectionExtensions { diff --git a/src/Core/Dirt/Reports/ReportFeatures/Requests/AddPasswordHealthReportApplicationRequest.cs b/src/Core/Dirt/Reports/ReportFeatures/Requests/AddPasswordHealthReportApplicationRequest.cs index dfc544b1c3..c4e646fcd7 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/Requests/AddPasswordHealthReportApplicationRequest.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/Requests/AddPasswordHealthReportApplicationRequest.cs @@ -1,4 +1,4 @@ -namespace Bit.Core.Tools.ReportFeatures.Requests; +namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests; public class AddPasswordHealthReportApplicationRequest { diff --git a/src/Core/Dirt/Reports/ReportFeatures/Requests/DropPasswordHealthReportApplicationRequest.cs b/src/Core/Dirt/Reports/ReportFeatures/Requests/DropPasswordHealthReportApplicationRequest.cs index 1464e68f04..544b9a51d5 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/Requests/DropPasswordHealthReportApplicationRequest.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/Requests/DropPasswordHealthReportApplicationRequest.cs @@ -1,4 +1,4 @@ -namespace Bit.Core.Tools.ReportFeatures.Requests; +namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests; public class DropPasswordHealthReportApplicationRequest { diff --git a/src/Core/Dirt/Reports/ReportFeatures/Requests/MemberAccessCipherDetailsRequest.cs b/src/Core/Dirt/Reports/ReportFeatures/Requests/MemberAccessCipherDetailsRequest.cs index 395230f430..b40dfc6dec 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/Requests/MemberAccessCipherDetailsRequest.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/Requests/MemberAccessCipherDetailsRequest.cs @@ -1,4 +1,4 @@ -namespace Bit.Core.Tools.ReportFeatures.Requests; +namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests; public class MemberAccessCipherDetailsRequest { diff --git a/src/Core/Dirt/Reports/Repositories/IPasswordHealthReportApplicationRepository.cs b/src/Core/Dirt/Reports/Repositories/IPasswordHealthReportApplicationRepository.cs index 374f12e122..5b57932868 100644 --- a/src/Core/Dirt/Reports/Repositories/IPasswordHealthReportApplicationRepository.cs +++ b/src/Core/Dirt/Reports/Repositories/IPasswordHealthReportApplicationRepository.cs @@ -1,7 +1,7 @@ -using Bit.Core.Repositories; -using Bit.Core.Tools.Entities; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Repositories; -namespace Bit.Core.Tools.Repositories; +namespace Bit.Core.Dirt.Reports.Repositories; public interface IPasswordHealthReportApplicationRepository : IRepository { diff --git a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs index ba374ae988..a95c2bd4c6 100644 --- a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs +++ b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs @@ -2,6 +2,7 @@ using Bit.Core.Auth.Repositories; using Bit.Core.Billing.Providers.Repositories; using Bit.Core.Billing.Repositories; +using Bit.Core.Dirt.Reports.Repositories; using Bit.Core.KeyManagement.Repositories; using Bit.Core.NotificationCenter.Repositories; using Bit.Core.Platform.Installations; @@ -12,6 +13,7 @@ using Bit.Core.Vault.Repositories; using Bit.Infrastructure.Dapper.AdminConsole.Repositories; using Bit.Infrastructure.Dapper.Auth.Repositories; using Bit.Infrastructure.Dapper.Billing.Repositories; +using Bit.Infrastructure.Dapper.Dirt; using Bit.Infrastructure.Dapper.KeyManagement.Repositories; using Bit.Infrastructure.Dapper.NotificationCenter.Repositories; using Bit.Infrastructure.Dapper.Platform; diff --git a/src/Infrastructure.Dapper/Dirt/PasswordHealthReportApplicationRepository.cs b/src/Infrastructure.Dapper/Dirt/PasswordHealthReportApplicationRepository.cs index 0c45998416..2445de8a9e 100644 --- a/src/Infrastructure.Dapper/Dirt/PasswordHealthReportApplicationRepository.cs +++ b/src/Infrastructure.Dapper/Dirt/PasswordHealthReportApplicationRepository.cs @@ -1,14 +1,14 @@ using System.Data; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.Repositories; using Bit.Core.Settings; -using Bit.Core.Tools.Repositories; using Bit.Infrastructure.Dapper.Repositories; using Dapper; using Microsoft.Data.SqlClient; -using ToolsEntities = Bit.Core.Tools.Entities; -namespace Bit.Infrastructure.Dapper.Tools.Repositories; +namespace Bit.Infrastructure.Dapper.Dirt; -public class PasswordHealthReportApplicationRepository : Repository, IPasswordHealthReportApplicationRepository +public class PasswordHealthReportApplicationRepository : Repository, IPasswordHealthReportApplicationRepository { public PasswordHealthReportApplicationRepository(GlobalSettings globalSettings) : this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString) @@ -18,11 +18,11 @@ public class PasswordHealthReportApplicationRepository : Repository> GetByOrganizationIdAsync(Guid organizationId) + public async Task> GetByOrganizationIdAsync(Guid organizationId) { using (var connection = new SqlConnection(ReadOnlyConnectionString)) { - var results = await connection.QueryAsync( + var results = await connection.QueryAsync( $"[{Schema}].[PasswordHealthReportApplication_ReadByOrganizationId]", new { OrganizationId = organizationId }, commandType: CommandType.StoredProcedure); diff --git a/src/Infrastructure.EntityFramework/Tools/Configurations/PasswordHealthReportApplicationEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/Dirt/Configurations/PasswordHealthReportApplicationEntityTypeConfiguration.cs similarity index 83% rename from src/Infrastructure.EntityFramework/Tools/Configurations/PasswordHealthReportApplicationEntityTypeConfiguration.cs rename to src/Infrastructure.EntityFramework/Dirt/Configurations/PasswordHealthReportApplicationEntityTypeConfiguration.cs index 4f4c5473d5..0d3c8ffc61 100644 --- a/src/Infrastructure.EntityFramework/Tools/Configurations/PasswordHealthReportApplicationEntityTypeConfiguration.cs +++ b/src/Infrastructure.EntityFramework/Dirt/Configurations/PasswordHealthReportApplicationEntityTypeConfiguration.cs @@ -1,8 +1,8 @@ -using Bit.Infrastructure.EntityFramework.Tools.Models; +using Bit.Infrastructure.EntityFramework.Dirt.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Bit.Infrastructure.EntityFramework.Tools.Configurations; +namespace Bit.Infrastructure.EntityFramework.Dirt.Configurations; public class PasswordHealthReportApplicationEntityTypeConfiguration : IEntityTypeConfiguration { diff --git a/src/Infrastructure.EntityFramework/Tools/Models/PasswordHealthReportApplication.cs b/src/Infrastructure.EntityFramework/Dirt/Models/PasswordHealthReportApplication.cs similarity index 52% rename from src/Infrastructure.EntityFramework/Tools/Models/PasswordHealthReportApplication.cs rename to src/Infrastructure.EntityFramework/Dirt/Models/PasswordHealthReportApplication.cs index 524cd283c6..222bfbeb65 100644 --- a/src/Infrastructure.EntityFramework/Tools/Models/PasswordHealthReportApplication.cs +++ b/src/Infrastructure.EntityFramework/Dirt/Models/PasswordHealthReportApplication.cs @@ -1,9 +1,9 @@ using AutoMapper; using Bit.Infrastructure.EntityFramework.AdminConsole.Models; -namespace Bit.Infrastructure.EntityFramework.Tools.Models; +namespace Bit.Infrastructure.EntityFramework.Dirt.Models; -public class PasswordHealthReportApplication : Core.Tools.Entities.PasswordHealthReportApplication +public class PasswordHealthReportApplication : Core.Dirt.Reports.Entities.PasswordHealthReportApplication { public virtual Organization Organization { get; set; } } @@ -12,7 +12,7 @@ public class PasswordHealthReportApplicationProfile : Profile { public PasswordHealthReportApplicationProfile() { - CreateMap() + CreateMap() .ReverseMap(); } } diff --git a/src/Infrastructure.EntityFramework/Tools/Repositories/PasswordHealthReportApplicationRepository.cs b/src/Infrastructure.EntityFramework/Dirt/Repositories/PasswordHealthReportApplicationRepository.cs similarity index 58% rename from src/Infrastructure.EntityFramework/Tools/Repositories/PasswordHealthReportApplicationRepository.cs rename to src/Infrastructure.EntityFramework/Dirt/Repositories/PasswordHealthReportApplicationRepository.cs index 1d8204a82f..604a0d87a1 100644 --- a/src/Infrastructure.EntityFramework/Tools/Repositories/PasswordHealthReportApplicationRepository.cs +++ b/src/Infrastructure.EntityFramework/Dirt/Repositories/PasswordHealthReportApplicationRepository.cs @@ -1,22 +1,21 @@ using AutoMapper; -using Bit.Core.Tools.Repositories; +using Bit.Core.Dirt.Reports.Repositories; +using Bit.Infrastructure.EntityFramework.Dirt.Models; using Bit.Infrastructure.EntityFramework.Repositories; -using Bit.Infrastructure.EntityFramework.Tools.Models; using LinqToDB; using Microsoft.Extensions.DependencyInjection; -using AdminConsoleEntities = Bit.Core.Tools.Entities; -namespace Bit.Infrastructure.EntityFramework.Tools.Repositories; +namespace Bit.Infrastructure.EntityFramework.Dirt.Repositories; public class PasswordHealthReportApplicationRepository : - Repository, + Repository, IPasswordHealthReportApplicationRepository { public PasswordHealthReportApplicationRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.PasswordHealthReportApplications) { } - public async Task> GetByOrganizationIdAsync(Guid organizationId) + public async Task> GetByOrganizationIdAsync(Guid organizationId) { using (var scope = ServiceScopeFactory.CreateScope()) { @@ -24,7 +23,7 @@ public class PasswordHealthReportApplicationRepository : var results = await dbContext.PasswordHealthReportApplications .Where(p => p.OrganizationId == organizationId) .ToListAsync(); - return Mapper.Map>(results); + return Mapper.Map>(results); } } } diff --git a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs index 22818517d3..321c4c90e5 100644 --- a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs +++ b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs @@ -2,6 +2,7 @@ using Bit.Core.Auth.Repositories; using Bit.Core.Billing.Providers.Repositories; using Bit.Core.Billing.Repositories; +using Bit.Core.Dirt.Reports.Repositories; using Bit.Core.Enums; using Bit.Core.KeyManagement.Repositories; using Bit.Core.NotificationCenter.Repositories; @@ -13,6 +14,7 @@ using Bit.Core.Vault.Repositories; using Bit.Infrastructure.EntityFramework.AdminConsole.Repositories; using Bit.Infrastructure.EntityFramework.Auth.Repositories; using Bit.Infrastructure.EntityFramework.Billing.Repositories; +using Bit.Infrastructure.EntityFramework.Dirt.Repositories; using Bit.Infrastructure.EntityFramework.KeyManagement.Repositories; using Bit.Infrastructure.EntityFramework.NotificationCenter.Repositories; using Bit.Infrastructure.EntityFramework.Platform; diff --git a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs index 5c1c1bc87f..647b3e3ab1 100644 --- a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +++ b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs @@ -4,11 +4,11 @@ using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider; using Bit.Infrastructure.EntityFramework.Auth.Models; using Bit.Infrastructure.EntityFramework.Billing.Models; using Bit.Infrastructure.EntityFramework.Converters; +using Bit.Infrastructure.EntityFramework.Dirt.Models; using Bit.Infrastructure.EntityFramework.Models; using Bit.Infrastructure.EntityFramework.NotificationCenter.Models; using Bit.Infrastructure.EntityFramework.Platform; using Bit.Infrastructure.EntityFramework.SecretsManager.Models; -using Bit.Infrastructure.EntityFramework.Tools.Models; using Bit.Infrastructure.EntityFramework.Vault.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; diff --git a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs index ccf2b5212f..5451400803 100644 --- a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs +++ b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs @@ -23,6 +23,7 @@ using Bit.Core.Auth.UserFeatures; using Bit.Core.Billing.Services; using Bit.Core.Billing.Services.Implementations; using Bit.Core.Billing.TrialInitiation; +using Bit.Core.Dirt.Reports.ReportFeatures; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.HostedServices; @@ -43,7 +44,6 @@ using Bit.Core.Services; using Bit.Core.Settings; using Bit.Core.Tokens; using Bit.Core.Tools.ImportFeatures; -using Bit.Core.Tools.ReportFeatures; using Bit.Core.Tools.SendFeatures; using Bit.Core.Tools.Services; using Bit.Core.Utilities; diff --git a/test/Api.Test/Dirt/ReportsControllerTests.cs b/test/Api.Test/Dirt/ReportsControllerTests.cs index 3057e10641..37a6cb79c3 100644 --- a/test/Api.Test/Dirt/ReportsControllerTests.cs +++ b/test/Api.Test/Dirt/ReportsControllerTests.cs @@ -1,15 +1,16 @@ using AutoFixture; -using Bit.Api.Tools.Controllers; +using Bit.Api.Dirt.Controllers; +using Bit.Api.Dirt.Models; using Bit.Core.Context; +using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; using Bit.Core.Exceptions; -using Bit.Core.Tools.ReportFeatures.Interfaces; -using Bit.Core.Tools.ReportFeatures.Requests; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Api.Test.Tools.Controllers; +namespace Bit.Api.Test.Dirt; [ControllerCustomize(typeof(ReportsController))] @@ -54,7 +55,7 @@ public class ReportsControllerTests sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(true); // Act - var request = new Api.Tools.Models.PasswordHealthReportApplicationModel + var request = new PasswordHealthReportApplicationModel { OrganizationId = Guid.NewGuid(), Url = "https://example.com", @@ -77,7 +78,7 @@ public class ReportsControllerTests // Act var fixture = new Fixture(); - var request = fixture.CreateMany(2); + var request = fixture.CreateMany(2); await sutProvider.Sut.AddPasswordHealthReportApplications(request); // Assert @@ -93,7 +94,7 @@ public class ReportsControllerTests sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(false); // Act - var request = new Api.Tools.Models.PasswordHealthReportApplicationModel + var request = new PasswordHealthReportApplicationModel { OrganizationId = Guid.NewGuid(), Url = "https://example.com", @@ -114,7 +115,7 @@ public class ReportsControllerTests // Act var fixture = new Fixture(); - var request = fixture.Create(); + var request = fixture.Create(); await Assert.ThrowsAsync(async () => await sutProvider.Sut.AddPasswordHealthReportApplication(request)); diff --git a/test/Core.Test/Dirt/ReportFeatures/AddPasswordHealthReportApplicationCommandTests.cs b/test/Core.Test/Dirt/ReportFeatures/AddPasswordHealthReportApplicationCommandTests.cs index 5018123e22..be54bc5310 100644 --- a/test/Core.Test/Dirt/ReportFeatures/AddPasswordHealthReportApplicationCommandTests.cs +++ b/test/Core.Test/Dirt/ReportFeatures/AddPasswordHealthReportApplicationCommandTests.cs @@ -1,17 +1,17 @@ using AutoFixture; using Bit.Core.AdminConsole.Entities; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.ReportFeatures; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; +using Bit.Core.Dirt.Reports.Repositories; using Bit.Core.Exceptions; using Bit.Core.Repositories; -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.ReportFeatures; -using Bit.Core.Tools.ReportFeatures.Requests; -using Bit.Core.Tools.Repositories; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Core.Test.Tools.ReportFeatures; +namespace Bit.Core.Test.Dirt.ReportFeatures; [SutProviderCustomize] public class AddPasswordHealthReportApplicationCommandTests diff --git a/test/Core.Test/Dirt/ReportFeatures/DeletePasswordHealthReportApplicationCommandTests.cs b/test/Core.Test/Dirt/ReportFeatures/DeletePasswordHealthReportApplicationCommandTests.cs index c459d0e81b..7756995805 100644 --- a/test/Core.Test/Dirt/ReportFeatures/DeletePasswordHealthReportApplicationCommandTests.cs +++ b/test/Core.Test/Dirt/ReportFeatures/DeletePasswordHealthReportApplicationCommandTests.cs @@ -1,15 +1,15 @@ using AutoFixture; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.ReportFeatures; +using Bit.Core.Dirt.Reports.ReportFeatures.Requests; +using Bit.Core.Dirt.Reports.Repositories; using Bit.Core.Exceptions; -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.ReportFeatures; -using Bit.Core.Tools.ReportFeatures.Requests; -using Bit.Core.Tools.Repositories; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Core.Test.Tools.ReportFeatures; +namespace Bit.Core.Test.Dirt.ReportFeatures; [SutProviderCustomize] public class DeletePasswordHealthReportApplicationCommandTests diff --git a/test/Core.Test/Dirt/ReportFeatures/GetPasswordHealthReportApplicationQueryTests.cs b/test/Core.Test/Dirt/ReportFeatures/GetPasswordHealthReportApplicationQueryTests.cs index c4f098b0c2..eddfd6c1bc 100644 --- a/test/Core.Test/Dirt/ReportFeatures/GetPasswordHealthReportApplicationQueryTests.cs +++ b/test/Core.Test/Dirt/ReportFeatures/GetPasswordHealthReportApplicationQueryTests.cs @@ -1,14 +1,14 @@ using AutoFixture; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.ReportFeatures; +using Bit.Core.Dirt.Reports.Repositories; using Bit.Core.Exceptions; -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.ReportFeatures; -using Bit.Core.Tools.Repositories; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Core.Test.Tools.ReportFeatures; +namespace Bit.Core.Test.Dirt.ReportFeatures; [SutProviderCustomize] public class GetPasswordHealthReportApplicationQueryTests diff --git a/test/Infrastructure.EFIntegration.Test/AutoFixture/EntityFrameworkRepositoryFixtures.cs b/test/Infrastructure.EFIntegration.Test/AutoFixture/EntityFrameworkRepositoryFixtures.cs index 0ebcf8903d..4a56d2cb22 100644 --- a/test/Infrastructure.EFIntegration.Test/AutoFixture/EntityFrameworkRepositoryFixtures.cs +++ b/test/Infrastructure.EFIntegration.Test/AutoFixture/EntityFrameworkRepositoryFixtures.cs @@ -7,10 +7,10 @@ using Bit.Infrastructure.EFIntegration.Test.Helpers; using Bit.Infrastructure.EntityFramework.AdminConsole.Models; using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider; using Bit.Infrastructure.EntityFramework.Auth.Models; +using Bit.Infrastructure.EntityFramework.Dirt.Models; using Bit.Infrastructure.EntityFramework.Models; using Bit.Infrastructure.EntityFramework.Platform; using Bit.Infrastructure.EntityFramework.Repositories; -using Bit.Infrastructure.EntityFramework.Tools.Models; using Bit.Infrastructure.EntityFramework.Vault.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Infrastructure.EFIntegration.Test/AutoFixture/PasswordHealthReportApplicationFixtures.cs b/test/Infrastructure.EFIntegration.Test/AutoFixture/PasswordHealthReportApplicationFixtures.cs index 7a1d1bb039..f6100fc71f 100644 --- a/test/Infrastructure.EFIntegration.Test/AutoFixture/PasswordHealthReportApplicationFixtures.cs +++ b/test/Infrastructure.EFIntegration.Test/AutoFixture/PasswordHealthReportApplicationFixtures.cs @@ -1,9 +1,9 @@ using AutoFixture; using AutoFixture.Kernel; -using Bit.Core.Tools.Entities; +using Bit.Core.Dirt.Reports.Entities; using Bit.Infrastructure.EntityFramework.AdminConsole.Repositories; +using Bit.Infrastructure.EntityFramework.Dirt.Repositories; using Bit.Infrastructure.EntityFramework.Repositories; -using Bit.Infrastructure.EntityFramework.Tools.Repositories; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; diff --git a/test/Infrastructure.EFIntegration.Test/Tools/Repositories/PasswordHealthReportApplicationRepositoryTests.cs b/test/Infrastructure.EFIntegration.Test/Dirt/Repositories/PasswordHealthReportApplicationRepositoryTests.cs similarity index 91% rename from test/Infrastructure.EFIntegration.Test/Tools/Repositories/PasswordHealthReportApplicationRepositoryTests.cs rename to test/Infrastructure.EFIntegration.Test/Dirt/Repositories/PasswordHealthReportApplicationRepositoryTests.cs index 9c83972a02..d796635153 100644 --- a/test/Infrastructure.EFIntegration.Test/Tools/Repositories/PasswordHealthReportApplicationRepositoryTests.cs +++ b/test/Infrastructure.EFIntegration.Test/Dirt/Repositories/PasswordHealthReportApplicationRepositoryTests.cs @@ -1,17 +1,16 @@ using AutoFixture; using Bit.Core.AdminConsole.Entities; +using Bit.Core.Dirt.Reports.Entities; +using Bit.Core.Dirt.Reports.Repositories; using Bit.Core.Repositories; using Bit.Core.Test.AutoFixture.Attributes; -using Bit.Core.Tools.Entities; -using Bit.Core.Tools.Repositories; +using Bit.Infrastructure.Dapper.Dirt; using Bit.Infrastructure.EFIntegration.Test.AutoFixture; using Xunit; using EfRepo = Bit.Infrastructure.EntityFramework.Repositories; -using EfToolsRepo = Bit.Infrastructure.EntityFramework.Tools.Repositories; -using SqlAdminConsoleRepo = Bit.Infrastructure.Dapper.Tools.Repositories; using SqlRepo = Bit.Infrastructure.Dapper.Repositories; -namespace Bit.Infrastructure.EFIntegration.Test.Tools.Repositories; +namespace Bit.Infrastructure.EFIntegration.Test.Dirt.Repositories; public class PasswordHealthReportApplicationRepositoryTests { @@ -19,9 +18,9 @@ public class PasswordHealthReportApplicationRepositoryTests public async Task CreateAsync_Works_DataMatches( PasswordHealthReportApplication passwordHealthReportApplication, Organization organization, - List suts, + List suts, List efOrganizationRepos, - SqlAdminConsoleRepo.PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, + PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, SqlRepo.OrganizationRepository sqlOrganizationRepo ) { @@ -53,7 +52,7 @@ public class PasswordHealthReportApplicationRepositoryTests [CiSkippedTheory, EfPasswordHealthReportApplicationAutoData] public async Task RetrieveByOrganisation_Works( - SqlAdminConsoleRepo.PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, + PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, SqlRepo.OrganizationRepository sqlOrganizationRepo) { var (firstOrg, firstRecord) = await CreateSampleRecord(sqlOrganizationRepo, sqlPasswordHealthReportApplicationRepo); @@ -68,9 +67,9 @@ public class PasswordHealthReportApplicationRepositoryTests [CiSkippedTheory, EfPasswordHealthReportApplicationAutoData] public async Task ReplaceQuery_Works( - List suts, + List suts, List efOrganizationRepos, - SqlAdminConsoleRepo.PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, + PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, SqlRepo.OrganizationRepository sqlOrganizationRepo) { var (org, pwdRecord) = await CreateSampleRecord(sqlOrganizationRepo, sqlPasswordHealthReportApplicationRepo); @@ -127,9 +126,9 @@ public class PasswordHealthReportApplicationRepositoryTests [CiSkippedTheory, EfPasswordHealthReportApplicationAutoData] public async Task Upsert_Works( - List suts, + List suts, List efOrganizationRepos, - SqlAdminConsoleRepo.PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, + PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, SqlRepo.OrganizationRepository sqlOrganizationRepo) { var fixture = new Fixture(); @@ -204,9 +203,9 @@ public class PasswordHealthReportApplicationRepositoryTests [CiSkippedTheory, EfPasswordHealthReportApplicationAutoData] public async Task Delete_Works( - List suts, + List suts, List efOrganizationRepos, - SqlAdminConsoleRepo.PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, + PasswordHealthReportApplicationRepository sqlPasswordHealthReportApplicationRepo, SqlRepo.OrganizationRepository sqlOrganizationRepo) { var fixture = new Fixture(); From 1bd11e61ef564648ad662c5707e7f845a2c1cfb8 Mon Sep 17 00:00:00 2001 From: Robyn MacCallum Date: Tue, 10 Jun 2025 15:50:22 -0400 Subject: [PATCH 18/19] Add enable-pm-prelogin-settings flag (#5946) --- src/Core/Constants.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index e6a822452a..1a2af31d03 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -181,6 +181,7 @@ public static class FeatureFlagKeys public const string EnablePMFlightRecorder = "enable-pm-flight-recorder"; public const string MobileErrorReporting = "mobile-error-reporting"; public const string AndroidChromeAutofill = "android-chrome-autofill"; + public const string EnablePMPreloginSettings = "enable-pm-prelogin-settings"; /* Platform Team */ public const string PersistPopupView = "persist-popup-view"; From f532236f05da8695b58ce4df9a0949986c61b030 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Tue, 10 Jun 2025 17:27:51 -0300 Subject: [PATCH 19/19] [PM-22572] Added app-intents feature flag key (#5948) --- src/Core/Constants.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 1a2af31d03..49d360ec50 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -182,6 +182,7 @@ public static class FeatureFlagKeys public const string MobileErrorReporting = "mobile-error-reporting"; public const string AndroidChromeAutofill = "android-chrome-autofill"; public const string EnablePMPreloginSettings = "enable-pm-prelogin-settings"; + public const string AppIntents = "app-intents"; /* Platform Team */ public const string PersistPopupView = "persist-popup-view";