1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 07:36:14 -05:00

[AC-1682] Added Sqlite migration and script

This commit is contained in:
Rui Tome
2024-03-25 15:22:17 +00:00
parent 9bde1604da
commit 262887f9c3
4 changed files with 2752 additions and 0 deletions

View File

@ -0,0 +1,151 @@
-- Step 1: AccessAll migration for Groups
-- Create a temporary table to store the groups with AccessAll = 1
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" = 0 AND "G"."AccessAll" = 1;
-- Step 2: AccessAll migration for OrganizationUsers
-- Create a temporary table to store the OrganizationUsers with AccessAll = 1
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" = 0 AND "OU"."AccessAll" = 1;
-- 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 1 ELSE 0 END AS "IsManager"
FROM "OrganizationUser" "OU"
INNER JOIN "Organization" "O" ON "OU"."OrganizationId" = "O"."Id"
WHERE "O"."FlexibleCollections" = 0 AND
("OU"."Type" = 3 OR
("OU"."Type" = 4 AND
"OU"."Permissions" IS NOT NULL AND
JSON_VALID("OU"."Permissions") AND JSON_EXTRACT(ou."Permissions", '$.editAssignedCollections') = 'true'));
-- Step 1
-- Update existing rows in "CollectionGroups"
UPDATE "CollectionGroups"
SET
"ReadOnly" = 0,
"HidePasswords" = 0,
"Manage" = 0
WHERE EXISTS (
SELECT 1
FROM "Collection" "C"
INNER JOIN "TempGroupsAccessAll" "TG" ON "CollectionGroups"."GroupId" = "TG"."GroupId"
WHERE "CollectionGroups"."CollectionId" = "C"."Id" AND C."OrganizationId" = "TG"."OrganizationId"
);
-- Insert new rows into "CollectionGroups"
INSERT INTO "CollectionGroups" ("CollectionId", "GroupId", "ReadOnly", "HidePasswords", "Manage")
SELECT "C"."Id", "TG"."GroupId", 0, 0, 0
FROM "Collection" "C"
INNER JOIN "TempGroupsAccessAll" "TG" ON "C"."OrganizationId" = "TG"."OrganizationId"
LEFT JOIN "CollectionGroups" "CG" ON "CG"."CollectionId" = "C"."Id" AND "CG"."GroupId" = "TG"."GroupId"
WHERE "CG"."CollectionId" IS NULL;
-- Update "Group" to clear "AccessAll" flag and update "RevisionDate"
UPDATE "Group"
SET "AccessAll" = 0, "RevisionDate" = CURRENT_TIMESTAMP
WHERE "Id" IN (SELECT "GroupId" FROM "TempGroupsAccessAll");
-- Step 2
-- Update existing rows in "CollectionUsers"
UPDATE "CollectionUsers"
SET
"ReadOnly" = 0,
"HidePasswords" = 0,
"Manage" = 0
WHERE "CollectionId" IN (
SELECT "C"."Id"
FROM "Collection" "C"
INNER JOIN "TempUsersAccessAll" "TU" ON "C"."OrganizationId" = "TU"."OrganizationId"
);
-- Insert new rows into "CollectionUsers"
INSERT INTO "CollectionUsers" ("CollectionId", "OrganizationUserId", "ReadOnly", "HidePasswords", "Manage")
SELECT "C"."Id", "TU"."OrganizationUserId", 0, 0, 0
FROM "Collection" "C"
INNER JOIN "TempUsersAccessAll" "TU" ON "C"."OrganizationId" = "TU"."OrganizationId"
LEFT JOIN "CollectionUsers" "target"
ON "target"."CollectionId" = "C"."Id" AND "target"."OrganizationUserId" = "TU"."OrganizationUserId"
WHERE "target"."CollectionId" IS NULL;
-- Update "OrganizationUser" to clear "AccessAll" flag
UPDATE "OrganizationUser"
SET "AccessAll" = 0, "RevisionDate" = CURRENT_TIMESTAMP
WHERE "Id" IN (SELECT "OrganizationUserId" FROM "TempUsersAccessAll");
-- Step 3
-- Update "CollectionUsers" with "Manage" = 1 using the temporary table
UPDATE "CollectionUsers"
SET
"ReadOnly" = 0,
"HidePasswords" = 0,
"Manage" = 1
WHERE "OrganizationUserId" IN (SELECT "OrganizationUserId" FROM "TempUserManagers");
-- Insert rows to "CollectionUsers" with "Manage" = 1 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", 0, 0, 1
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"
SET "Type" = 2, "RevisionDate" = CURRENT_TIMESTAMP -- User
WHERE "Id" IN (SELECT "OrganizationUserId" FROM "TempUserManagers" WHERE "IsManager" = 1);
-- Step 4
-- Update "User" "AccountRevisionDate" for each unique "OrganizationUserId"
UPDATE "User"
SET "AccountRevisionDate" = CURRENT_TIMESTAMP
WHERE "Id" IN (
SELECT DISTINCT "OU"."UserId"
FROM "OrganizationUser" "OU"
INNER JOIN (
-- Step 1
SELECT "GU"."OrganizationUserId"
FROM "GroupUser" "GU"
INNER JOIN "TempGroupsAccessAll" "TG" ON "GU"."GroupId" = "TG"."GroupId"
UNION
-- Step 2
SELECT "OrganizationUserId"
FROM "TempUsersAccessAll"
UNION
-- Step 3
SELECT "OrganizationUserId"
FROM "TempUserManagers"
) AS "CombinedOrgUsers" ON "OU"."Id" = "CombinedOrgUsers"."OrganizationUserId"
);
-- Step 5
-- Set "FlexibleCollections" = 1 for all organizations that have not yet been migrated.
UPDATE "Organization"
SET "FlexibleCollections" = 1
WHERE "FlexibleCollections" = 0;
-- Step 6: Drop the temporary tables
DROP TABLE IF EXISTS "TempGroupsAccessAll";
DROP TABLE IF EXISTS "TempUsersAccessAll";
DROP TABLE IF EXISTS "TempUserManagers";

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
using Bit.Core.Utilities;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Bit.SqliteMigrations.Migrations
{
public partial class EnableOrgsCollectionEnhancements : Migration
{
private const string _enableOrgsCollectionEnhancementsScript = "SqliteMigrations.HelperScripts.2024-03-22_00_EnableOrgsCollectionEnhancements.sql";
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(CoreHelpers.GetEmbeddedResourceContentsAsync(_enableOrgsCollectionEnhancementsScript));
}
protected override void Down(MigrationBuilder migrationBuilder)
{
throw new Exception("Irreversible migration");
}
}
}

View File

@ -24,6 +24,7 @@
<ItemGroup>
<EmbeddedResource Include="HelperScripts\2023-12-04_00_Up_GrantIndexes.sql" />
<EmbeddedResource Include="HelperScripts\2023-12-04_00_Down_GrantIndexes.sql" />
<EmbeddedResource Include="HelperScripts\2024-03-22_00_EnableOrgsCollectionEnhancements.sql" />
</ItemGroup>
</Project>