diff --git a/keyserver/src/creators/invite-link-creator.js b/keyserver/src/creators/invite-link-creator.js --- a/keyserver/src/creators/invite-link-creator.js +++ b/keyserver/src/creators/invite-link-creator.js @@ -27,6 +27,7 @@ assignHolder, uploadBlob, deleteBlob, + type BlobOperationResult, } from '../services/blob.js'; import { Viewer } from '../session/viewer.js'; import { fetchIdentityInfo } from '../user/identity.js'; @@ -58,7 +59,7 @@ const fetchThreadInfoPromise = fetchServerThreadInfos({ threadID: request.communityID, }); - const blobDownloadPromise = getInviteLinkBlob(request); + const blobDownloadPromise = getInviteLinkBlob(request.name); const [ hasPermission, existingPrimaryLinks, @@ -200,14 +201,15 @@ }; } -function getInviteLinkBlob( - request: CreateOrUpdatePublicLinkRequest, -): Promise { - const hash = inviteLinkBlobHash(request.name); +function getInviteLinkBlob(secret: string): Promise { + const hash = inviteLinkBlobHash(secret); return download(hash); } -async function uploadInviteLinkBlob(linkSecret: string, holder: string) { +async function uploadInviteLinkBlob( + linkSecret: string, + holder: string, +): Promise { const identityInfo = await fetchIdentityInfo(); const keyserverID = identityInfo?.userId; if (!keyserverID) { @@ -233,4 +235,4 @@ return await assignHolder({ holder, hash: key }); } -export { createOrUpdatePublicLink }; +export { createOrUpdatePublicLink, uploadInviteLinkBlob, getInviteLinkBlob }; diff --git a/keyserver/src/services/blob.js b/keyserver/src/services/blob.js --- a/keyserver/src/services/blob.js +++ b/keyserver/src/services/blob.js @@ -35,7 +35,7 @@ +holder: string, }; -type BlobOperationResult = +export type BlobOperationResult = | { +success: true, } diff --git a/keyserver/src/updaters/link-updaters.js b/keyserver/src/updaters/link-updaters.js --- a/keyserver/src/updaters/link-updaters.js +++ b/keyserver/src/updaters/link-updaters.js @@ -11,4 +11,13 @@ await dbQuery(query); } -export { reportLinkUsage }; +async function setLinkHolder(secret: string, holder: string): Promise { + const query = SQL` + UPDATE invite_links + SET blob_holder = ${holder} + WHERE name = ${secret} + `; + await dbQuery(query); +} + +export { reportLinkUsage, setLinkHolder }; diff --git a/keyserver/src/utils/synchronizeInviteLinksWithBlobs.js b/keyserver/src/utils/synchronizeInviteLinksWithBlobs.js new file mode 100644 --- /dev/null +++ b/keyserver/src/utils/synchronizeInviteLinksWithBlobs.js @@ -0,0 +1,44 @@ +// @flow + +import uuid from 'uuid'; + +import { inviteLinkBlobHash } from 'lib/shared/invite-links.js'; +import type { InviteLinkWithHolder } from 'lib/types/link-types.js'; + +import { + getInviteLinkBlob, + uploadInviteLinkBlob, +} from '../creators/invite-link-creator.js'; +import { fetchAllPrimaryInviteLinks } from '../fetchers/link-fetchers.js'; +import { setLinkHolder } from '../updaters/link-updaters.js'; + +async function synchronizeInviteLinksWithBlobs() { + const links = await fetchAllPrimaryInviteLinks(); + const promises = []; + for (const link: InviteLinkWithHolder of links) { + promises.push( + (async () => { + const isHolderPresent = !!link.blobHolder; + const holder = link.blobHolder ?? uuid.v4(); + if (isHolderPresent) { + const blobFetchResult = await getInviteLinkBlob( + inviteLinkBlobHash(link.name), + ); + if (blobFetchResult.found) { + return; + } + } + const uploadResult = await uploadInviteLinkBlob( + inviteLinkBlobHash(link.name), + holder, + ); + if (uploadResult.success && !isHolderPresent) { + await setLinkHolder(link.name, holder); + } + })(), + ); + } + await Promise.all(promises); +} + +export { synchronizeInviteLinksWithBlobs };