diff --git a/util/PostgresMigrations/HelperScripts/2024-03-22_00_EnableOrgsCollectionEnhancements.psql b/util/PostgresMigrations/HelperScripts/2024-03-22_00_EnableOrgsCollectionEnhancements.psql
new file mode 100644
index 0000000000..f837960f3c
--- /dev/null
+++ b/util/PostgresMigrations/HelperScripts/2024-03-22_00_EnableOrgsCollectionEnhancements.psql
@@ -0,0 +1,133 @@
+-- Step 1: AccessAll migration for Groups
+ -- Create a temporary table to store the groups with AccessAll = true
+ CREATE TEMPORARY TABLE IF NOT EXISTS "TempGroupsAccessAll" AS
+ SELECT "G"."Id" AS "GroupId",
+ "G"."OrganizationId"
+ FROM "Group" "G"
+ INNER JOIN "Organization" "O" ON "G"."OrganizationId" = "O"."Id"
+ WHERE "O"."FlexibleCollections" = false AND "G"."AccessAll" = true;
+
+-- Step 2: AccessAll migration for OrganizationUsers
+ -- Create a temporary table to store the OrganizationUsers with AccessAll = true
+ CREATE TEMPORARY TABLE IF NOT EXISTS "TempUsersAccessAll" AS
+ SELECT "OU"."Id" AS "OrganizationUserId",
+ "OU"."OrganizationId"
+ FROM "OrganizationUser" "OU"
+ INNER JOIN "Organization" "O" ON "OU"."OrganizationId" = "O"."Id"
+ WHERE "O"."FlexibleCollections" = false AND "OU"."AccessAll" = true;
+
+-- Step 3: For all OrganizationUsers with Manager role or 'EditAssignedCollections' permission update their existing CollectionUsers rows and insert new rows with Manage = 1
+-- and finally update all OrganizationUsers with Manager role to User role
+ -- Create a temporary table to store the OrganizationUsers with Manager role or 'EditAssignedCollections' permission
+ CREATE TEMPORARY TABLE IF NOT EXISTS "TempUserManagers" AS
+ SELECT "OU"."Id" AS "OrganizationUserId",
+ CASE WHEN "OU"."Type" = 3 THEN true ELSE false END AS "IsManager"
+ FROM "OrganizationUser" "OU"
+ INNER JOIN "Organization" "O" ON "OU"."OrganizationId" = "O"."Id"
+ WHERE "O"."FlexibleCollections" = false AND
+ ("OU"."Type" = 3 OR
+ ("OU"."Type" = 4 AND
+ "OU"."Permissions" IS NOT NULL AND
+ (("OU"."Permissions"::text)::jsonb->>'editAssignedCollections') = 'true'));
+
+ -- Step 1
+ -- Update existing rows in CollectionGroups
+ UPDATE "CollectionGroups" "CG"
+ SET "ReadOnly" = false,
+ "HidePasswords" = false,
+ "Manage" = false
+ FROM "Collection" "C"
+ WHERE "CG"."CollectionId" = "C"."Id"
+ AND "C"."OrganizationId" IN (SELECT "OrganizationId" FROM "TempGroupsAccessAll");
+
+ -- Insert new rows into CollectionGroups
+ INSERT INTO "CollectionGroups" ("CollectionId", "GroupId", "ReadOnly", "HidePasswords", "Manage")
+ SELECT "C"."Id", "TG"."GroupId", false, false, false
+ FROM "Collection" "C"
+ INNER JOIN "TempGroupsAccessAll" "TG" ON "C"."OrganizationId" = "TG"."OrganizationId"
+ LEFT JOIN "CollectionGroups" "CG" ON "C"."Id" = "CG"."CollectionId" AND "TG"."GroupId" = "CG"."GroupId"
+ WHERE "CG"."CollectionId" IS NULL;
+
+ -- Update "Group" to clear "AccessAll" flag and update "RevisionDate"
+ UPDATE "Group" "G"
+ SET "AccessAll" = false, "RevisionDate" = CURRENT_TIMESTAMP
+ WHERE "G"."Id" IN (SELECT "GroupId" FROM "TempGroupsAccessAll");
+
+ -- Step 2
+ -- Update existing rows in CollectionUsers
+ UPDATE "CollectionUsers" "target"
+ SET "ReadOnly" = false,
+ "HidePasswords" = false,
+ "Manage" = false
+ FROM "Collection" "C"
+ WHERE "target"."CollectionId" = "C"."Id"
+ AND "C"."OrganizationId" IN (SELECT "OrganizationId" FROM "TempUsersAccessAll")
+ AND "target"."OrganizationUserId" IN (SELECT "OrganizationUserId" FROM "TempUsersAccessAll");
+
+ -- Insert new rows into CollectionUsers
+ INSERT INTO "CollectionUsers" ("CollectionId", "OrganizationUserId", "ReadOnly", "HidePasswords", "Manage")
+ SELECT "C"."Id", "TU"."OrganizationUserId", false, false, false
+ FROM "Collection" "C"
+ INNER JOIN "TempUsersAccessAll" "TU" ON "C"."OrganizationId" = "TU"."OrganizationId"
+ LEFT JOIN "CollectionUsers" "target" ON "C"."Id" = "target"."CollectionId" AND "TU"."OrganizationUserId" = "target"."OrganizationUserId"
+ WHERE "target"."CollectionId" IS NULL;
+
+ -- Update "OrganizationUser" to clear "AccessAll" flag
+ UPDATE "OrganizationUser" "OU"
+ SET "AccessAll" = false, "RevisionDate" = CURRENT_TIMESTAMP
+ WHERE "OU"."Id" IN (SELECT "OrganizationUserId" FROM "TempUsersAccessAll");
+
+ -- Step 3
+ -- Update CollectionUsers with Manage = 1 using the temporary table
+ UPDATE "CollectionUsers" "CU"
+ SET "ReadOnly" = false,
+ "HidePasswords" = false,
+ "Manage" = true
+ FROM "TempUserManagers" "TUM"
+ WHERE "CU"."OrganizationUserId" = "TUM"."OrganizationUserId";
+
+ -- Insert rows to CollectionUsers with Manage = true using the temporary table
+ -- This is for orgUsers who are Managers / EditAssignedCollections but have access via a group
+ -- We cannot give the whole group Manage permissions so we have to give them a direct assignment
+ INSERT INTO "CollectionUsers" ("CollectionId", "OrganizationUserId", "ReadOnly", "HidePasswords", "Manage")
+ SELECT DISTINCT "CG"."CollectionId", "TUM"."OrganizationUserId", false, false, true
+ FROM "CollectionGroups" "CG"
+ INNER JOIN "GroupUser" "GU" ON "CG"."GroupId" = "GU"."GroupId"
+ INNER JOIN "TempUserManagers" "TUM" ON "GU"."OrganizationUserId" = "TUM"."OrganizationUserId"
+ WHERE NOT EXISTS (
+ SELECT 1 FROM "CollectionUsers" "CU"
+ WHERE "CU"."CollectionId" = "CG"."CollectionId" AND "CU"."OrganizationUserId" = "TUM"."OrganizationUserId"
+ );
+
+ -- Update "OrganizationUser" to migrate all OrganizationUsers with Manager role to User role
+ UPDATE "OrganizationUser" "OU"
+ SET "Type" = 2, "RevisionDate" = CURRENT_TIMESTAMP -- User
+ WHERE "OU"."Id" IN (SELECT "OrganizationUserId" FROM "TempUserManagers" WHERE "IsManager" = true);
+
+ -- Step 4
+ -- Update "User" "AccountRevisionDate" for each unique "OrganizationUserId"
+ UPDATE "User" "U"
+ SET "AccountRevisionDate" = CURRENT_TIMESTAMP
+ FROM "OrganizationUser" "OU"
+ WHERE "U"."Id" = "OU"."UserId"
+ AND "OU"."Id" IN (
+ SELECT "OrganizationUserId"
+ FROM "GroupUser"
+ WHERE "GroupId" IN (SELECT "GroupId" FROM "TempGroupsAccessAll")
+ UNION
+ SELECT "OrganizationUserId" FROM "TempUsersAccessAll"
+ UNION
+ SELECT "OrganizationUserId" FROM "TempUserManagers"
+ );
+
+ -- Step 5
+ -- Set "FlexibleCollections" = true for all organizations that have not yet been migrated.
+ UPDATE "Organization"
+ SET "FlexibleCollections" = true
+ WHERE "FlexibleCollections" = false;
+
+-- Step 5: Drop the temporary tables
+DROP TABLE IF EXISTS "TempGroupsAccessAll";
+DROP TABLE IF EXISTS "TempUsersAccessAll";
+DROP TABLE IF EXISTS "TempUserManagers";
+
diff --git a/util/PostgresMigrations/Migrations/20240322155520_EnableOrgsCollectionEnhancements.Designer.cs b/util/PostgresMigrations/Migrations/20240322155520_EnableOrgsCollectionEnhancements.Designer.cs
new file mode 100644
index 0000000000..a843495ca4
--- /dev/null
+++ b/util/PostgresMigrations/Migrations/20240322155520_EnableOrgsCollectionEnhancements.Designer.cs
@@ -0,0 +1,2596 @@
+//
+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("20240322155520_EnableOrgsCollectionEnhancements")]
+ partial class EnableOrgsCollectionEnhancements
+ {
+ ///
+ 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", "7.0.16")
+ .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")
+ .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("FlexibleCollections")
+ .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("Identifier")
+ .HasMaxLength(50)
+ .HasColumnType("character varying(50)")
+ .UseCollation("postgresIndetermanisticCollation");
+
+ b.Property("LicenseKey")
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)");
+
+ b.Property("LimitCollectionCreationDeletion")
+ .HasColumnType("boolean")
+ .HasDefaultValue(true);
+
+ 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")
+ .HasMaxLength(50)
+ .HasColumnType("character varying(50)");
+
+ b.Property("OwnersNotifiedOfAutoscaling")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Plan")
+ .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("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("UsePasswordManager")
+ .HasColumnType("boolean");
+
+ b.Property("UsePolicies")
+ .HasColumnType("boolean");
+
+ b.Property("UseResetPassword")
+ .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.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("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("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(50)
+ .HasColumnType("character varying(50)")
+ .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.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.Collection", 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")
+ .HasColumnType("text");
+
+ b.Property("OrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("RevisionDate")
+ .HasColumnType("timestamp with time zone");
+
+ 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("CreationDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EncryptedPrivateKey")
+ .HasColumnType("text");
+
+ b.Property("EncryptedPublicKey")
+ .HasColumnType("text");
+
+ b.Property("EncryptedUserKey")
+ .HasColumnType("text");
+
+ b.Property("Identifier")
+ .HasMaxLength(50)
+ .HasColumnType("character varying(50)");
+
+ b.Property("Name")
+ .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("AccessAll")
+ .HasColumnType("boolean");
+
+ b.Property("CreationDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ExternalId")
+ .HasMaxLength(300)
+ .HasColumnType("character varying(300)");
+
+ b.Property("Name")
+ .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.Installation", 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("Enabled")
+ .HasColumnType("boolean");
+
+ b.Property("Key")
+ .HasMaxLength(150)
+ .HasColumnType("character varying(150)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Installation", (string)null);
+ });
+
+ modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ApiKey")
+ .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")
+ .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")
+ .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