diff --git a/keyserver/src/deleters/farcaster-channel-tag-deleters.js b/keyserver/src/deleters/farcaster-channel-tag-deleters.js index 877b26127..0ab4ce518 100644 --- a/keyserver/src/deleters/farcaster-channel-tag-deleters.js +++ b/keyserver/src/deleters/farcaster-channel-tag-deleters.js @@ -1,32 +1,61 @@ // @flow import { DISABLE_TAGGING_FARCASTER_CHANNEL, farcasterChannelTagBlobHash, } from 'lib/shared/community-utils.js'; import type { DeleteFarcasterChannelTagRequest } from 'lib/types/community-types'; import { ServerError } from 'lib/utils/errors.js'; +import { dbQuery, SQL } from '../database/database.js'; import { deleteBlob } from '../services/blob.js'; import type { Viewer } from '../session/viewer'; async function deleteFarcasterChannelTag( viewer: Viewer, request: DeleteFarcasterChannelTagRequest, ): Promise { - const { farcasterChannelID, blobHolder } = request; - if (DISABLE_TAGGING_FARCASTER_CHANNEL) { throw new ServerError('internal_error'); } - await deleteBlob( - { - hash: farcasterChannelTagBlobHash(farcasterChannelID), - holder: blobHolder, - }, - true, - ); + const query = SQL` + START TRANSACTION; + + SELECT blob_holder INTO @currentBlobHolder + FROM communities + WHERE id = ${request.commCommunityID} + AND farcaster_channel_id = ${request.farcasterChannelID} + FOR UPDATE; + + UPDATE communities + SET + farcaster_channel_id = NULL, + blob_holder = NULL + WHERE id = ${request.commCommunityID} + AND farcaster_channel_id = ${request.farcasterChannelID}; + + COMMIT; + + SELECT @currentBlobHolder AS blobHolder; + `; + + const [transactionResult] = await dbQuery(query, { + multipleStatements: true, + }); + + const selectResult = transactionResult.pop(); + const [row] = selectResult; + + if (row?.blobHolder) { + await deleteBlob( + { + hash: farcasterChannelTagBlobHash(request.farcasterChannelID), + holder: row.blobHolder, + }, + true, + ); + } } export { deleteFarcasterChannelTag }; diff --git a/keyserver/src/responders/farcaster-channel-tag-responders.js b/keyserver/src/responders/farcaster-channel-tag-responders.js index 77e268eff..09970e381 100644 --- a/keyserver/src/responders/farcaster-channel-tag-responders.js +++ b/keyserver/src/responders/farcaster-channel-tag-responders.js @@ -1,48 +1,47 @@ // @flow import t, { type TInterface } from 'tcomb'; import type { CreateOrUpdateFarcasterChannelTagRequest, CreateOrUpdateFarcasterChannelTagResponse, DeleteFarcasterChannelTagRequest, } from 'lib/types/community-types'; import { tShape, tID } from 'lib/utils/validation-utils.js'; import { createOrUpdateFarcasterChannelTag } from '../creators/farcaster-channel-tag-creator.js'; import { deleteFarcasterChannelTag } from '../deleters/farcaster-channel-tag-deleters.js'; import type { Viewer } from '../session/viewer'; const createOrUpdateFarcasterChannelTagInputValidator: TInterface = tShape({ commCommunityID: tID, farcasterChannelID: t.String, }); async function createOrUpdateFarcasterChannelTagResponder( viewer: Viewer, request: CreateOrUpdateFarcasterChannelTagRequest, ): Promise { return await createOrUpdateFarcasterChannelTag(viewer, request); } const deleteFarcasterChannelTagInputValidator: TInterface = tShape({ commCommunityID: tID, farcasterChannelID: t.String, - blobHolder: t.String, }); async function deleteFarcasterChannelTagResponder( viewer: Viewer, request: DeleteFarcasterChannelTagRequest, ): Promise { await deleteFarcasterChannelTag(viewer, request); } export { createOrUpdateFarcasterChannelTagResponder, createOrUpdateFarcasterChannelTagInputValidator, deleteFarcasterChannelTagResponder, deleteFarcasterChannelTagInputValidator, }; diff --git a/lib/actions/community-actions.js b/lib/actions/community-actions.js index 4aba97a69..8aee00895 100644 --- a/lib/actions/community-actions.js +++ b/lib/actions/community-actions.js @@ -1,107 +1,106 @@ // @flow import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js'; import { useKeyserverCall } from '../keyserver-conn/keyserver-call.js'; import type { CallKeyserverEndpoint } from '../keyserver-conn/keyserver-conn-types.js'; import type { CreateOrUpdateFarcasterChannelTagRequest, CreateOrUpdateFarcasterChannelTagResponse, DeleteFarcasterChannelTagRequest, DeleteFarcasterChannelTagPayload, } from '../types/community-types.js'; const updateCalendarCommunityFilter = 'UPDATE_CALENDAR_COMMUNITY_FILTER'; const clearCalendarCommunityFilter = 'CLEAR_CALENDAR_COMMUNITY_FILTER'; const updateChatCommunityFilter = 'UPDATE_CHAT_COMMUNITY_FILTER'; const clearChatCommunityFilter = 'CLEAR_CHAT_COMMUNITY_FILTER'; const addCommunityActionType = 'ADD_COMMUNITY'; const createOrUpdateFarcasterChannelTagActionTypes = Object.freeze({ started: 'CREATE_OR_UPDATE_FARCASTER_CHANNEL_TAG_STARTED', success: 'CREATE_OR_UPDATE_FARCASTER_CHANNEL_TAG_SUCCESS', failed: 'CREATE_OR_UPDATE_FARCASTER_CHANNEL_TAG_FAILED', }); const createOrUpdateFarcasterChannelTag = ( callKeyserverEndpoint: CallKeyserverEndpoint, ): (( input: CreateOrUpdateFarcasterChannelTagRequest, ) => Promise) => async input => { const keyserverID = extractKeyserverIDFromID(input.commCommunityID); const requests = { [keyserverID]: { commCommunityID: input.commCommunityID, farcasterChannelID: input.farcasterChannelID, }, }; const responses = await callKeyserverEndpoint( 'create_or_update_farcaster_channel_tag', requests, ); const response = responses[keyserverID]; return { commCommunityID: response.commCommunityID, farcasterChannelID: response.farcasterChannelID, }; }; function useCreateOrUpdateFarcasterChannelTag(): ( input: CreateOrUpdateFarcasterChannelTagRequest, ) => Promise { return useKeyserverCall(createOrUpdateFarcasterChannelTag); } const deleteFarcasterChannelTagActionTypes = Object.freeze({ started: 'DELETE_FARCASTER_CHANNEL_TAG_STARTED', success: 'DELETE_FARCASTER_CHANNEL_TAG_SUCCESS', failed: 'DELETE_FARCASTER_CHANNEL_TAG_FAILED', }); const deleteFarcasterChannelTag = ( callKeyserverEndpoint: CallKeyserverEndpoint, ): (( input: DeleteFarcasterChannelTagRequest, ) => Promise) => async input => { const keyserverID = extractKeyserverIDFromID(input.commCommunityID); const requests = { [keyserverID]: { commCommunityID: input.commCommunityID, farcasterChannelID: input.farcasterChannelID, - blobHolder: input.blobHolder, }, }; await callKeyserverEndpoint('delete_farcaster_channel_tag', requests); return { commCommunityID: input.commCommunityID, }; }; function useDeleteFarcasterChannelTag(): ( input: DeleteFarcasterChannelTagRequest, ) => Promise { return useKeyserverCall(deleteFarcasterChannelTag); } export { updateCalendarCommunityFilter, clearCalendarCommunityFilter, updateChatCommunityFilter, clearChatCommunityFilter, addCommunityActionType, createOrUpdateFarcasterChannelTagActionTypes, useCreateOrUpdateFarcasterChannelTag, deleteFarcasterChannelTagActionTypes, useDeleteFarcasterChannelTag, }; diff --git a/lib/types/community-types.js b/lib/types/community-types.js index 2d875953a..753c289ae 100644 --- a/lib/types/community-types.js +++ b/lib/types/community-types.js @@ -1,36 +1,35 @@ // @flow export type CommunityInfo = { +farcasterChannelID: ?string, }; export type CommunityInfos = { +[threadID: string]: CommunityInfo }; export type CommunityStore = { +communityInfos: CommunityInfos, }; export type AddCommunityPayload = { +id: string, +newCommunityInfo: CommunityInfo, }; export type CreateOrUpdateFarcasterChannelTagRequest = { +commCommunityID: string, +farcasterChannelID: string, }; export type CreateOrUpdateFarcasterChannelTagResponse = { +commCommunityID: string, +farcasterChannelID: string, }; export type DeleteFarcasterChannelTagRequest = { +commCommunityID: string, +farcasterChannelID: string, - +blobHolder: string, }; export type DeleteFarcasterChannelTagPayload = { +commCommunityID: string, };