diff --git a/keyserver/src/scripts/add-leave-thread-permissions.js b/keyserver/src/scripts/add-leave-thread-permissions.js index b35f59d4c..f44891b6f 100644 --- a/keyserver/src/scripts/add-leave-thread-permissions.js +++ b/keyserver/src/scripts/add-leave-thread-permissions.js @@ -1,32 +1,32 @@ // @flow import { threadPermissions } from 'lib/types/thread-permission-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import { endScript } from './utils.js'; import { dbQuery, SQL } from '../database/database.js'; import { DEPRECATED_recalculateAllThreadPermissions } from '../updaters/thread-permission-updaters.js'; async function main() { try { await addLeaveThreadPermissions(); await DEPRECATED_recalculateAllThreadPermissions(); } catch (e) { console.warn(e); } finally { endScript(); } } async function addLeaveThreadPermissions() { const leaveThreadString = `$.${threadPermissions.LEAVE_THREAD}`; const updateAllRoles = SQL` UPDATE roles r LEFT JOIN threads t ON t.id = r.thread SET r.permissions = JSON_SET(permissions, ${leaveThreadString}, TRUE) WHERE t.type != ${threadTypes.PERSONAL} `; await dbQuery(updateAllRoles); } -main(); +void main(); diff --git a/keyserver/src/scripts/create-friend-relationships.js b/keyserver/src/scripts/create-friend-relationships.js index ad6c4f262..61fd0f315 100644 --- a/keyserver/src/scripts/create-friend-relationships.js +++ b/keyserver/src/scripts/create-friend-relationships.js @@ -1,31 +1,31 @@ // @flow import { undirectedStatus } from 'lib/types/relationship-types.js'; import { endScript } from './utils.js'; import { createUndirectedRelationships } from '../creators/relationship-creators.js'; import { dbQuery, SQL } from '../database/database.js'; async function main() { try { await createFriendRelationshipsForThreadMembers(); endScript(); } catch (e) { endScript(); console.warn(e); } } async function createFriendRelationshipsForThreadMembers() { const [result] = await dbQuery(SQL` SELECT m.thread, m.user FROM memberships m LEFT JOIN users u ON u.id = m.user WHERE m.role > 0 AND u.id IS NOT NULL ORDER BY m.user ASC `); await createUndirectedRelationships(result, undirectedStatus.FRIEND); } -main(); +void main(); diff --git a/keyserver/src/scripts/create-relationships.js b/keyserver/src/scripts/create-relationships.js index 1cf330c82..446874606 100644 --- a/keyserver/src/scripts/create-relationships.js +++ b/keyserver/src/scripts/create-relationships.js @@ -1,69 +1,69 @@ // @flow import { undirectedStatus } from 'lib/types/relationship-types.js'; import { endScript } from './utils.js'; import { createUndirectedRelationships } from '../creators/relationship-creators.js'; import { dbQuery, SQL } from '../database/database.js'; import { saveMemberships } from '../updaters/thread-permission-updaters.js'; async function main() { try { await alterMemberships(); await createMembershipsForFormerMembers(); await createKnowOfRelationships(); endScript(); } catch (e) { endScript(); console.warn(e); } } async function alterMemberships() { await dbQuery( SQL`ALTER TABLE memberships CHANGE permissions permissions json DEFAULT NULL`, ); } async function createMembershipsForFormerMembers() { const [result] = await dbQuery(SQL` SELECT DISTINCT thread, user FROM messages m WHERE NOT EXISTS ( SELECT thread, user FROM memberships mm WHERE m.thread = mm.thread AND m.user = mm.user ) `); const rowsToSave = []; for (const row of result) { rowsToSave.push({ operation: 'save', userID: row.user.toString(), threadID: row.thread.toString(), userNeedsFullThreadDetails: false, intent: 'none', permissions: null, permissionsForChildren: null, role: '-1', oldRole: '-1', }); } await saveMemberships({ toSave: rowsToSave, updateMembershipsLastMessage: false, }); } async function createKnowOfRelationships() { const [result] = await dbQuery(SQL` SELECT thread, user FROM memberships UNION SELECT thread, user FROM messages ORDER BY user ASC `); await createUndirectedRelationships(result, undirectedStatus.KNOW_OF); } -main(); +void main(); diff --git a/keyserver/src/scripts/create-sidebar-permissions.js b/keyserver/src/scripts/create-sidebar-permissions.js index 0c842c972..817c0ac87 100644 --- a/keyserver/src/scripts/create-sidebar-permissions.js +++ b/keyserver/src/scripts/create-sidebar-permissions.js @@ -1,42 +1,42 @@ // @flow import { threadPermissionPropagationPrefixes, threadPermissions, } from 'lib/types/thread-permission-types.js'; import { endScript } from './utils.js'; import { dbQuery, SQL } from '../database/database.js'; import { DEPRECATED_recalculateAllThreadPermissions } from '../updaters/thread-permission-updaters.js'; async function main() { try { await createSidebarPermissions(); await DEPRECATED_recalculateAllThreadPermissions(); } catch (e) { console.warn(e); } finally { endScript(); } } async function createSidebarPermissions() { const createSidebarsString = `$.${threadPermissions.CREATE_SIDEBARS}`; const updateAllRoles = SQL` UPDATE roles SET permissions = JSON_SET(permissions, ${createSidebarsString}, TRUE) `; await dbQuery(updateAllRoles); const descendantSidebarsString = `$.${threadPermissionPropagationPrefixes.DESCENDANT}` + threadPermissions.CREATE_SIDEBARS; const updateAdminRoles = SQL` UPDATE roles SET permissions = JSON_SET(permissions, ${descendantSidebarsString}, TRUE) WHERE name = 'Admins' `; await dbQuery(updateAdminRoles); } -main(); +void main(); diff --git a/keyserver/src/scripts/delete-unread-column.js b/keyserver/src/scripts/delete-unread-column.js index c6fa84686..e233cd24e 100644 --- a/keyserver/src/scripts/delete-unread-column.js +++ b/keyserver/src/scripts/delete-unread-column.js @@ -1,19 +1,19 @@ // @flow import { endScript } from './utils.js'; import { dbQuery, SQL } from '../database/database.js'; async function deleteUnreadColumn() { try { await dbQuery(SQL` ALTER TABLE memberships DROP COLUMN unread `); } catch (e) { console.warn(e); } finally { endScript(); } } -deleteUnreadColumn(); +void deleteUnreadColumn(); diff --git a/keyserver/src/scripts/image-size.js b/keyserver/src/scripts/image-size.js index d4e11571e..0e7ea96c5 100644 --- a/keyserver/src/scripts/image-size.js +++ b/keyserver/src/scripts/image-size.js @@ -1,36 +1,36 @@ // @flow import sizeOf from 'buffer-image-size'; import { endScript } from './utils.js'; import { dbQuery, SQL } from '../database/database.js'; async function main() { try { await addImageSizeToUploadsTable(); endScript(); } catch (e) { endScript(); console.warn(e); } } async function addImageSizeToUploadsTable() { await dbQuery(SQL`ALTER TABLE uploads ADD extra JSON NULL AFTER secret;`); const [result] = await dbQuery(SQL` SELECT id, content FROM uploads WHERE type = "photo" AND extra IS NULL `); for (const row of result) { const { height, width } = sizeOf(row.content); const dimensions = JSON.stringify({ height, width }); await dbQuery(SQL` UPDATE uploads SET extra = ${dimensions} WHERE id = ${row.id} `); } } -main(); +void main(); diff --git a/keyserver/src/scripts/make-notif-columns-optional.js b/keyserver/src/scripts/make-notif-columns-optional.js index e3cd919ab..f55a26bb8 100644 --- a/keyserver/src/scripts/make-notif-columns-optional.js +++ b/keyserver/src/scripts/make-notif-columns-optional.js @@ -1,24 +1,24 @@ // @flow import { endScript } from './utils.js'; import { dbQuery, SQL } from '../database/database.js'; async function main() { try { await makeNotifColumnsOptional(); } catch (e) { console.warn(e); } finally { endScript(); } } async function makeNotifColumnsOptional() { await dbQuery(SQL` ALTER TABLE notifications CHANGE thread thread BIGINT(20) NULL DEFAULT NULL, CHANGE message message BIGINT(20) NULL DEFAULT NULL `); } -main(); +void main(); diff --git a/keyserver/src/scripts/merge-users.js b/keyserver/src/scripts/merge-users.js index 2efd9df85..aa5a61352 100644 --- a/keyserver/src/scripts/merge-users.js +++ b/keyserver/src/scripts/merge-users.js @@ -1,195 +1,195 @@ // @flow import type { ServerThreadInfo } from 'lib/types/thread-types.js'; import { updateTypes } from 'lib/types/update-types-enum.js'; import { type UpdateData } from 'lib/types/update-types.js'; import { endScript } from './utils.js'; import { createUpdates } from '../creators/update-creator.js'; import { dbQuery, SQL } from '../database/database.js'; import type { SQLStatementType } from '../database/types.js'; import { deleteAccount } from '../deleters/account-deleters.js'; import { fetchServerThreadInfos } from '../fetchers/thread-fetchers.js'; import { createScriptViewer } from '../session/scripts.js'; import { changeRole, commitMembershipChangeset, type MembershipRow, } from '../updaters/thread-permission-updaters.js'; import RelationshipChangeset from '../utils/relationship-changeset.js'; async function main() { try { await mergeUsers('7147', '15972', { username: true, password: true }); endScript(); } catch (e) { endScript(); console.warn(e); } } type ReplaceUserInfo = Partial<{ +username: boolean, +password: boolean, }>; async function mergeUsers( fromUserID: string, toUserID: string, replaceUserInfo?: ReplaceUserInfo, ) { let updateUserRowQuery: ?SQLStatementType = null; let updateDatas: UpdateData[] = []; if (replaceUserInfo) { const replaceUserResult = await replaceUser( fromUserID, toUserID, replaceUserInfo, ); ({ sql: updateUserRowQuery, updateDatas } = replaceUserResult); } const usersGettingUpdate = new Set(); const usersNeedingUpdate = new Set(); const needUserInfoUpdate = replaceUserInfo && replaceUserInfo.username; const setGettingUpdate = (threadInfo: ServerThreadInfo) => { if (!needUserInfoUpdate) { return; } for (const { id } of threadInfo.members) { usersGettingUpdate.add(id); usersNeedingUpdate.delete(id); } }; const setNeedingUpdate = (threadInfo: ServerThreadInfo) => { if (!needUserInfoUpdate) { return; } for (const { id } of threadInfo.members) { if (!usersGettingUpdate.has(id)) { usersNeedingUpdate.add(id); } } }; const newThreadRolePairs = []; const { threadInfos } = await fetchServerThreadInfos(); for (const threadID in threadInfos) { const threadInfo = threadInfos[threadID]; const fromUserExistingMember = threadInfo.members.find( memberInfo => memberInfo.id === fromUserID, ); if (!fromUserExistingMember) { setNeedingUpdate(threadInfo); continue; } const { role } = fromUserExistingMember; if (!role) { // Only transfer explicit memberships setNeedingUpdate(threadInfo); continue; } const toUserExistingMember = threadInfo.members.find( memberInfo => memberInfo.id === toUserID, ); if (!toUserExistingMember || !toUserExistingMember.role) { setGettingUpdate(threadInfo); newThreadRolePairs.push([threadID, role]); } else { setNeedingUpdate(threadInfo); } } const fromViewer = createScriptViewer(fromUserID); await deleteAccount(fromViewer); if (updateUserRowQuery) { await dbQuery(updateUserRowQuery); } const time = Date.now(); for (const userID of usersNeedingUpdate) { updateDatas.push({ type: updateTypes.UPDATE_USER, userID, time, updatedUserID: toUserID, }); } await createUpdates(updateDatas); const changesets = await Promise.all( newThreadRolePairs.map(([threadID, role]) => changeRole(threadID, [toUserID], role), ), ); const membershipRows: Array = []; const relationshipChangeset = new RelationshipChangeset(); for (const currentChangeset of changesets) { const { membershipRows: currentMembershipRows, relationshipChangeset: currentRelationshipChangeset, } = currentChangeset; membershipRows.push(...currentMembershipRows); relationshipChangeset.addAll(currentRelationshipChangeset); } if (membershipRows.length > 0 || relationshipChangeset.getRowCount() > 0) { const toViewer = createScriptViewer(toUserID); const changeset = { membershipRows, relationshipChangeset }; await commitMembershipChangeset(toViewer, changeset); } } type ReplaceUserResult = { sql: ?SQLStatementType, updateDatas: UpdateData[], }; async function replaceUser( fromUserID: string, toUserID: string, replaceUserInfo: ReplaceUserInfo, ): Promise { if (Object.keys(replaceUserInfo).length === 0) { return { sql: null, updateDatas: [], }; } const fromUserQuery = SQL` SELECT username, hash FROM users WHERE id = ${fromUserID} `; const [fromUserResult] = await dbQuery(fromUserQuery); const [firstResult] = fromUserResult; if (!firstResult) { throw new Error(`couldn't fetch fromUserID ${fromUserID}`); } const changedFields: { [string]: string } = {}; if (replaceUserInfo.username) { changedFields.username = firstResult.username; } if (replaceUserInfo.password) { changedFields.hash = firstResult.hash; } const updateUserRowQuery = SQL` UPDATE users SET ${changedFields} WHERE id = ${toUserID} `; const updateDatas: UpdateData[] = []; if (replaceUserInfo.username) { updateDatas.push({ type: updateTypes.UPDATE_CURRENT_USER, userID: toUserID, time: Date.now(), }); } return { sql: updateUserRowQuery, updateDatas, }; } -main(); +void main(); diff --git a/keyserver/src/scripts/set-last-read-messages.js b/keyserver/src/scripts/set-last-read-messages.js index eb4d149fe..a80b5b249 100644 --- a/keyserver/src/scripts/set-last-read-messages.js +++ b/keyserver/src/scripts/set-last-read-messages.js @@ -1,130 +1,130 @@ // @flow import { messageTypes } from 'lib/types/message-types-enum.js'; import { threadPermissions } from 'lib/types/thread-permission-types.js'; import { endScript } from './utils.js'; import { dbQuery, SQL } from '../database/database.js'; async function main() { try { await createLastMessageColumn(); await setLastReadMessage(); } catch (e) { console.warn(e); } finally { endScript(); } } async function createLastMessageColumn() { try { await dbQuery(SQL` ALTER TABLE memberships ADD last_read_message bigint(20) NOT NULL DEFAULT 0, ADD last_message bigint(20) NOT NULL DEFAULT 0 `); } catch (e) { console.info('Column probably exists', e); } } async function setLastReadMessage() { const knowOfExtractString = `$.${threadPermissions.KNOW_OF}.value`; const [result] = await dbQuery(SQL` SELECT MAX(msg.id) AS message, msg.thread, stm.user FROM messages msg LEFT JOIN memberships stm ON msg.type = ${messageTypes.CREATE_SUB_THREAD} AND stm.thread = msg.content WHERE msg.type != ${messageTypes.CREATE_SUB_THREAD} OR JSON_EXTRACT(stm.permissions, ${knowOfExtractString}) IS TRUE GROUP BY msg.thread, stm.user `); const lastMessages = []; const userSpecificLastMessages = []; for (const row of result) { if (row.user) { userSpecificLastMessages.push({ message: row.message, thread: row.thread, user: row.user, }); } else { lastMessages.push({ message: row.message, thread: row.thread, }); } } if (lastMessages.length > 0) { const lastMessageExpression = SQL`last_message = CASE `; const lastReadMessageExpression = SQL`last_read_message = CASE `; for (const entry of lastMessages) { lastMessageExpression.append(SQL` WHEN thread = ${entry.thread} THEN ${entry.message} `); lastReadMessageExpression.append(SQL` WHEN thread = ${entry.thread} AND unread = 0 THEN ${entry.message} `); } lastMessageExpression.append(SQL` ELSE last_message END, `); lastReadMessageExpression.append(SQL` ELSE last_read_message END `); const query = SQL` UPDATE memberships SET `; query.append(lastMessageExpression); query.append(lastReadMessageExpression); await dbQuery(query); } if (userSpecificLastMessages.length > 0) { const lastMessageExpression = SQL` last_message = GREATEST(last_message, CASE `; const lastReadMessageExpression = SQL` last_read_message = GREATEST(last_read_message, CASE `; for (const entry of userSpecificLastMessages) { lastMessageExpression.append(SQL` WHEN thread = ${entry.thread} AND user = ${entry.user} THEN ${entry.message} `); lastReadMessageExpression.append(SQL` WHEN thread = ${entry.thread} AND unread = 0 AND user = ${entry.user} THEN ${entry.message} `); } lastMessageExpression.append(SQL` ELSE last_message END), `); lastReadMessageExpression.append(SQL` ELSE last_read_message END) `); const query = SQL` UPDATE memberships SET `; query.append(lastMessageExpression); query.append(lastReadMessageExpression); await dbQuery(query); } } -main(); +void main(); diff --git a/keyserver/src/scripts/utils.js b/keyserver/src/scripts/utils.js index 09379e936..1c6430129 100644 --- a/keyserver/src/scripts/utils.js +++ b/keyserver/src/scripts/utils.js @@ -1,28 +1,30 @@ // @flow import { endPool } from '../database/database.js'; import { endFirebase, endAPNs } from '../push/providers.js'; import { publisher } from '../socket/redis.js'; import { prefetchAllURLFacts } from '../utils/urls.js'; function endScript() { endPool(); publisher.end(); endFirebase(); endAPNs(); } -async function main(functions: $ReadOnlyArray<() => Promise>) { - await prefetchAllURLFacts(); - try { - for (const f of functions) { - await f(); +function main(functions: $ReadOnlyArray<() => Promise>) { + void (async () => { + await prefetchAllURLFacts(); + try { + for (const f of functions) { + await f(); + } + } catch (e) { + console.warn(e); + } finally { + endScript(); } - } catch (e) { - console.warn(e); - } finally { - endScript(); - } + })(); } export { endScript, main };