diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index c2a8d83a3..bb23933e5 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -153,6 +153,7 @@ import { } from './index' import { createPostResolver, + deletePostResolver, postResolver, postsResolver, updatePostResolver, @@ -325,6 +326,7 @@ export const functionResolvers = { deleteFolderPolicy: deleteFolderPolicyResolver, createPost: createPostResolver, updatePost: updatePostResolver, + deletePost: deletePostResolver, }, Query: { me: getMeUserResolver, @@ -913,4 +915,5 @@ export const functionResolvers = { ...resultResolveTypeResolver('Post'), ...resultResolveTypeResolver('CreatePost'), ...resultResolveTypeResolver('UpdatePost'), + ...resultResolveTypeResolver('DeletePost'), } diff --git a/packages/api/src/resolvers/posts/index.ts b/packages/api/src/resolvers/posts/index.ts index e76ed3dd4..88704bc0c 100644 --- a/packages/api/src/resolvers/posts/index.ts +++ b/packages/api/src/resolvers/posts/index.ts @@ -3,7 +3,11 @@ import { CreatePostError, CreatePostErrorCode, CreatePostSuccess, + DeletePostError, + DeletePostErrorCode, + DeletePostSuccess, MutationCreatePostArgs, + MutationDeletePostArgs, MutationUpdatePostArgs, PostEdge, PostErrorCode, @@ -19,6 +23,7 @@ import { } from '../../generated/graphql' import { createPublicPost, + deletePosts, findPublicPostById, findPublicPostsByUserId, updatePost, @@ -193,3 +198,31 @@ export const updatePostResolver = authorized< post, } }) + +export const deletePostResolver = authorized< + DeletePostSuccess, + DeletePostError, + MutationDeletePostArgs +>(async (_, { id }, { uid, log }) => { + if (!id) { + log.error('Invalid args', { id }) + + return { + errorCodes: [DeletePostErrorCode.BadRequest], + } + } + + const result = await deletePosts(uid, [id]) + + if (!result.affected) { + log.error('Failed to delete post', { id }) + + return { + errorCodes: [DeletePostErrorCode.Unauthorized], + } + } + + return { + success: true, + } +}) diff --git a/packages/api/src/services/post.ts b/packages/api/src/services/post.ts index f51b95f27..6a2be8715 100644 --- a/packages/api/src/services/post.ts +++ b/packages/api/src/services/post.ts @@ -61,14 +61,9 @@ export const createPosts = async ( } export const deletePosts = async (userId: string, postIds: string[]) => { - return authTrx( - async (trx) => { - await trx.getRepository(Post).delete(postIds) - }, - { - uid: userId, - } - ) + return authTrx(async (trx) => trx.getRepository(Post).delete(postIds), { + uid: userId, + }) } export const findPublicPostById = async (id: string) => { diff --git a/packages/api/test/resolvers/post.test.ts b/packages/api/test/resolvers/post.test.ts index 0c28a0621..99e9e51f6 100644 --- a/packages/api/test/resolvers/post.test.ts +++ b/packages/api/test/resolvers/post.test.ts @@ -383,4 +383,75 @@ describe('Post Resolvers', () => { expect(post?.title).to.eql('Updated Post') }) }) + + describe('deletePostResolver', () => { + const mutation = ` + mutation DeletePost($id: ID!) { + deletePost(id: $id) { + ... on DeletePostSuccess { + success + } + ... on DeletePostError { + errorCodes + } + } + } + ` + + let postId: string + + before(async () => { + const post = { + title: 'Post', + content: 'Content', + user: loginUser, + } + const newPost = await createPosts(loginUser.id, [post]) + + postId = newPost[0].id + }) + + it('should return an error if the args are invalid', async () => { + const response = await graphqlRequest(mutation, authToken, { + id: '', + }) + + expect(response.body.data.deletePost.errorCodes).to.eql(['BAD_REQUEST']) + }) + + it('should return an error if the post is not found', async () => { + const response = await graphqlRequest(mutation, authToken, { + id: generateFakeUuid(), + }) + + expect(response.body.data.deletePost.errorCodes).to.eql(['UNAUTHORIZED']) + }) + + it('should return an error if the user is not the owner of the post', async () => { + const notOwner = await createTestUser('notOwner') + const notOwnerToken = await loginAndGetAuthToken(notOwner.email) + + const response = await graphqlRequest(mutation, notOwnerToken, { + id: postId, + }) + + expect(response.body.data.deletePost.errorCodes).to.eql(['UNAUTHORIZED']) + + const post = await findPublicPostById(postId) + expect(post).to.exist + + await deleteUser(notOwner.id) + }) + + it('should delete the post', async () => { + const response = await graphqlRequest(mutation, authToken, { + id: postId, + }) + + expect(response.body.data.deletePost.success).to.be.true + + const post = await findPublicPostById(postId) + expect(post).to.not.exist + }) + }) })