diff --git a/keyserver/src/database/migration-config.js b/keyserver/src/database/migration-config.js --- a/keyserver/src/database/migration-config.js +++ b/keyserver/src/database/migration-config.js @@ -2,6 +2,8 @@ import fs from 'fs'; +import { updateRolesAndPermissionsForAllThreads } from '../updaters/thread-permission-updaters'; + const migrations: $ReadOnlyMap Promise> = new Map([ [ 0, @@ -25,6 +27,8 @@ await fixBaseRoutePathForLocalhost('facts/squadcal_url.json'); }, ], + + [3, updateRolesAndPermissionsForAllThreads], ]); const newDatabaseVersion: number = Math.max(...migrations.keys()); diff --git a/keyserver/src/updaters/thread-permission-updaters.js b/keyserver/src/updaters/thread-permission-updaters.js --- a/keyserver/src/updaters/thread-permission-updaters.js +++ b/keyserver/src/updaters/thread-permission-updaters.js @@ -38,6 +38,7 @@ import { rescindPushNotifs } from '../push/rescind'; import { createScriptViewer } from '../session/scripts'; import type { Viewer } from '../session/viewer'; +import { updateRoles } from '../updaters/role-updaters'; import DepthQueue from '../utils/depth-queue'; import RelationshipChangeset from '../utils/relationship-changeset'; import { updateChangedUndirectedRelationships } from './relationship-updaters'; @@ -1238,6 +1239,51 @@ } } +async function updateRolesAndPermissionsForAllThreads() { + const batchSize = 10; + const fetchThreads = SQL`SELECT id, type, depth FROM threads`; + const [result] = await dbQuery(fetchThreads); + const allThreads = result.map(row => { + return { + id: row.id.toString(), + type: assertThreadType(row.type), + depth: row.depth, + }; + }); + + const viewer = createScriptViewer(bots.commbot.userID); + + const maxDepth = Math.max(...allThreads.map(row => row.depth)); + + for (let depth = 0; depth <= maxDepth; depth++) { + const threads = allThreads.filter(row => row.depth === depth); + console.log(`recalculating permissions for threads with depth ${depth}`); + while (threads.length > 0) { + const batch = threads.splice(0, batchSize); + const membershipRows = []; + const relationshipChangeset = new RelationshipChangeset(); + await Promise.all( + batch.map(async thread => { + console.log(`updating roles for ${thread.id}`); + await updateRoles(viewer, thread.id, thread.type); + console.log(`recalculating permissions for ${thread.id}`); + const { + membershipRows: threadMembershipRows, + relationshipChangeset: threadRelationshipChangeset, + } = await recalculateThreadPermissions(thread.id); + membershipRows.push(...threadMembershipRows); + relationshipChangeset.addAll(threadRelationshipChangeset); + }), + ); + console.log(`committing batch ${JSON.stringify(batch)}`); + await commitMembershipChangeset(viewer, { + membershipRows, + relationshipChangeset, + }); + } + } +} + export { changeRole, recalculateThreadPermissions, @@ -1245,4 +1291,5 @@ saveMemberships, commitMembershipChangeset, recalculateAllThreadPermissions, + updateRolesAndPermissionsForAllThreads, };