diff --git a/keyserver/src/creators/farcaster-channel-tag-creator.js b/keyserver/src/creators/farcaster-channel-tag-creator.js --- a/keyserver/src/creators/farcaster-channel-tag-creator.js +++ b/keyserver/src/creators/farcaster-channel-tag-creator.js @@ -12,10 +12,17 @@ } from 'lib/types/community-types.js'; import { ServerError } from 'lib/utils/errors.js'; +import { + dbQuery, + SQL, + MYSQL_DUPLICATE_ENTRY_FOR_KEY_ERROR_CODE, +} from '../database/database.js'; +import { fetchCommunityInfos } from '../fetchers/community-fetchers.js'; import { uploadBlob, assignHolder, download, + deleteBlob, type BlobOperationResult, type BlobDownloadResult, } from '../services/blob.js'; @@ -25,13 +32,27 @@ viewer: Viewer, request: CreateOrUpdateFarcasterChannelTagRequest, ): Promise { - const { commCommunityID, farcasterChannelID } = request; - if (DISABLE_TAGGING_FARCASTER_CHANNEL) { throw new ServerError('internal_error'); } - const blobDownload = await getFarcasterChannelTagBlob(farcasterChannelID); + const fetchCommunityInfosPromise = fetchCommunityInfos(viewer); + const blobDownloadPromise = getFarcasterChannelTagBlob( + request.farcasterChannelID, + ); + + const [serverCommunityInfos, blobDownload] = await Promise.all([ + fetchCommunityInfosPromise, + blobDownloadPromise, + ]); + + const communityInfo = serverCommunityInfos.find( + community => community.id === request.commCommunityID, + ); + + if (!communityInfo) { + throw new ServerError('invalid_parameters'); + } if (blobDownload.found) { throw new ServerError('already_in_use'); @@ -40,8 +61,8 @@ const blobHolder = uuid.v4(); const blobResult = await uploadFarcasterChannelTagBlob( - commCommunityID, - farcasterChannelID, + request.commCommunityID, + request.farcasterChannelID, blobHolder, ); @@ -53,9 +74,46 @@ } } + const query = SQL` + UPDATE communities + SET farcaster_channel_id = ${request.farcasterChannelID}, + blob_holder = ${blobHolder} + WHERE id = ${request.commCommunityID} + `; + + try { + await dbQuery(query); + + const channelID = communityInfo.farcasterChannelID; + const holder = communityInfo.blobHolder; + + if (channelID && holder) { + await deleteBlob( + { + hash: farcasterChannelTagBlobHash(channelID), + holder, + }, + true, + ); + } + } catch (error) { + await deleteBlob( + { + hash: farcasterChannelTagBlobHash(request.farcasterChannelID), + holder: blobHolder, + }, + true, + ); + + if (error.errno === MYSQL_DUPLICATE_ENTRY_FOR_KEY_ERROR_CODE) { + throw new ServerError('already_in_use'); + } + throw new ServerError('invalid_parameters'); + } + return { - commCommunityID, - blobHolder, + commCommunityID: request.commCommunityID, + farcasterChannelID: request.farcasterChannelID, }; } diff --git a/keyserver/src/responders/farcaster-channel-tag-responders.js b/keyserver/src/responders/farcaster-channel-tag-responders.js --- a/keyserver/src/responders/farcaster-channel-tag-responders.js +++ b/keyserver/src/responders/farcaster-channel-tag-responders.js @@ -22,7 +22,7 @@ const createOrUpdateFarcasterChannelTagResponseValidator: TInterface = tShape({ commCommunityID: tID, - blobHolder: t.String, + farcasterChannelID: t.String, }); async function createOrUpdateFarcasterChannelTagResponder( diff --git a/lib/actions/community-actions.js b/lib/actions/community-actions.js --- a/lib/actions/community-actions.js +++ b/lib/actions/community-actions.js @@ -48,7 +48,7 @@ return { commCommunityID: response.commCommunityID, - blobHolder: response.blobHolder, + farcasterChannelID: response.farcasterChannelID, }; }; diff --git a/lib/types/community-types.js b/lib/types/community-types.js --- a/lib/types/community-types.js +++ b/lib/types/community-types.js @@ -22,7 +22,7 @@ export type CreateOrUpdateFarcasterChannelTagResponse = { +commCommunityID: string, - +blobHolder: string, + +farcasterChannelID: string, }; export type DeleteFarcasterChannelTagRequest = {