1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-25 12:45:18 +01:00
bitwarden-server/util/PostgresMigrations/HelperScripts/2024-04-25_00_EnableOrgsCollectionEnhancements.psql

143 lines
6.3 KiB
Plaintext
Raw Normal View History

[AC-1978] Flexible collections: EF data migrations for deprecated permissions (#3969) * [AC-1682] Added MySql migration and script (cherry picked from commit d367f6de6b65343f1e99c9cf928e77215b13c34d) * [AC-1682] Added Postgres migration and script (cherry picked from commit 9bde1604da8432a6066fc6b48e88738fdc171869) * [AC-1682] Added Sqlite migration and script (cherry picked from commit 262887f9c3e484d5de856b715ee3c40092b4eb5f) * [AC-1682] dotnet format (cherry picked from commit 00eea0621c7c1092ea51c936fe2e7389a46109b9) * [AC-1682] Fixed Sqlite query (cherry picked from commit 26f5bf8afdf7607d01d56be8ba880ae592a127fc) * [AC-1682] Drop temp tables if they exist when starting the scripts (cherry picked from commit c20912f95c237da671a69eba0e39e5449a1a6d60) * [AC-1682] Removed MySql transaction from script because EF migration already wraps it under its own transaction (cherry picked from commit 7b54d78d6755788cabcc035f293af04881b0015a) * [AC-1682] Setting FlexibleCollections = 1 only for Orgs that had data migrated in previous steps (cherry picked from commit 28bba94d81d3c1a2515882b40829170b42096026) * [AC-1682] Updated queries to check for OrganizationId (cherry picked from commit a957530d5ed9caaa42fae6901fceb83b93ae99ce) * [AC-1682] Fixed MySql script (cherry picked from commit deee483ab7037f46233ca0802d1fcc698aa4d3d4) * [AC-1682] Fixed Postgres query (cherry picked from commit c3ca9ec3c8de625a5cf560c76474ee03eb1a50b2) * [AC-1682] Fix Sqlite query (cherry picked from commit fada0a81bf21b89d3debda9d3b51d31b1867631f) * [AC-1682] Reverted scripts back to enabling Flexible Collections to all existing Orgs (cherry picked from commit bd3b21b9698f13f57322a1eb5bac9fd1b99f779a) * [AC-1682] Removed dropping temporary table from scripts (cherry picked from commit eb7794d592cdd782a64154068046d708d30f371b) * [AC-1682] Removed other temp table drops (cherry picked from commit 26768b7bf82fd297fafa2638f59e600e7ac093a5) * [AC-1978] Fix issue that allows the web app to have the user type Manager available (cherry picked from commit 2890f78870a8b624c0598c9c39df22c6f05eecc0) * [AC-1682] Bump dates on migration scripts --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2024-04-26 15:11:29 +02:00
-- Step 1: AccessAll migration for Groups
-- Create a temporary table to store the groups with AccessAll = true
CREATE TEMPORARY TABLE "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 "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 "TempUserManagers" AS
SELECT "OU"."Id" AS "OrganizationUserId",
"OU"."OrganizationId",
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
WHERE "CG"."CollectionId" IN (
SELECT "C"."Id"
FROM "Collection" "C"
INNER JOIN "TempGroupsAccessAll" "TG" ON "C"."OrganizationId" = "TG"."OrganizationId"
WHERE "CG"."GroupId" = "TG"."GroupId"
);
-- 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" "CU"
SET "ReadOnly" = false,
"HidePasswords" = false,
"Manage" = false
WHERE "CU"."CollectionId" IN (
SELECT "C"."Id"
FROM "Collection" "C"
INNER JOIN "TempUsersAccessAll" "TU" ON "C"."OrganizationId" = "TU"."OrganizationId"
WHERE "CU"."OrganizationUserId" = "TU"."OrganizationUserId"
);
-- 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 6: Drop the temporary tables
DROP TABLE IF EXISTS "TempGroupsAccessAll";
DROP TABLE IF EXISTS "TempUsersAccessAll";
DROP TABLE IF EXISTS "TempUserManagers";