Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrated to Integration-Test : Test/routes/graphql/Mutation/deletePost : #3289

Merged
merged 14 commits into from
Feb 25, 2025
238 changes: 126 additions & 112 deletions src/graphql/types/Mutation/deletePost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,145 +2,159 @@ import { eq } from "drizzle-orm";
import { z } from "zod";
import { postsTable } from "~/src/drizzle/tables/posts";
import { builder } from "~/src/graphql/builder";
import type { GraphQLContext } from "~/src/graphql/context";
import {
MutationDeletePostInput,
mutationDeletePostInputSchema,
} from "~/src/graphql/inputs/MutationDeletePostInput";
import { Post } from "~/src/graphql/types/Post/Post";
import { TalawaGraphQLError } from "~/src/utilities/TalawaGraphQLError";

// Schema for the arguments object
const mutationDeletePostArgumentsSchema = z.object({
input: mutationDeletePostInputSchema,
});

// Extract and export the resolver logic so it can be imported in your tests.
export async function deletePostResolver(
_parent: unknown,
args: z.infer<typeof mutationDeletePostArgumentsSchema>,
ctx: GraphQLContext,
) {
if (!ctx.currentClient.isAuthenticated) {
throw new TalawaGraphQLError({
extensions: { code: "unauthenticated" },
});
}
builder.mutationField("deletePost", (t) =>
t.field({
args: {
input: t.arg({
description: "",
required: true,
type: MutationDeletePostInput,
}),
},
description: "Mutation field to delete a post.",
resolve: async (_parent, args, ctx) => {
if (!ctx.currentClient.isAuthenticated) {
throw new TalawaGraphQLError({
extensions: {
code: "unauthenticated",
},
});
}

const {
data: parsedArgs,
error,
success,
} = mutationDeletePostArgumentsSchema.safeParse(args);
const {
data: parsedArgs,
error,
success,
} = mutationDeletePostArgumentsSchema.safeParse(args);

if (!success) {
throw new TalawaGraphQLError({
extensions: {
code: "invalid_arguments",
issues: error.issues.map((issue) => ({
argumentPath: issue.path,
message: issue.message,
})),
},
});
}
if (!success) {
throw new TalawaGraphQLError({
extensions: {
code: "invalid_arguments",
issues: error.issues.map((issue) => ({
argumentPath: issue.path,
message: issue.message,
})),
},
});
}

const currentUserId = ctx.currentClient.user.id;
const currentUserId = ctx.currentClient.user.id;

const [currentUser, existingPost] = await Promise.all([
ctx.drizzleClient.query.usersTable.findFirst({
columns: { role: true },
where: (fields, operators: { eq: typeof eq }) =>
operators.eq(fields.id, currentUserId),
}),
ctx.drizzleClient.query.postsTable.findFirst({
columns: { creatorId: true },
with: {
attachmentsWherePost: true,
organization: {
columns: { countryCode: true },
const [currentUser, existingPost] = await Promise.all([
ctx.drizzleClient.query.usersTable.findFirst({
columns: {
role: true,
},
where: (fields, operators) => operators.eq(fields.id, currentUserId),
}),
ctx.drizzleClient.query.postsTable.findFirst({
columns: {
creatorId: true,
},
with: {
membershipsWhereOrganization: {
columns: { role: true },
where: (fields, operators: { eq: typeof eq }) =>
operators.eq(fields.memberId, currentUserId),
attachmentsWherePost: true,
organization: {
columns: {
countryCode: true,
},
with: {
membershipsWhereOrganization: {
columns: {
role: true,
},
where: (fields, operators) =>
operators.eq(fields.memberId, currentUserId),
},
},
},
},
},
},
where: eq(postsTable.id, parsedArgs.input.id),
}),
]);
where: (fields, operators) =>
operators.eq(fields.id, parsedArgs.input.id),
}),
]);

if (currentUser === undefined) {
throw new TalawaGraphQLError({
extensions: { code: "unauthenticated" },
});
}

if (existingPost === undefined) {
throw new TalawaGraphQLError({
extensions: {
code: "arguments_associated_resources_not_found",
issues: [{ argumentPath: ["input", "id"] }],
},
});
}
if (currentUser === undefined) {
throw new TalawaGraphQLError({
extensions: {
code: "unauthenticated",
},
});
}

if (currentUser.role !== "administrator") {
const currentUserOrganizationMembership =
existingPost.organization.membershipsWhereOrganization[0];
if (existingPost === undefined) {
throw new TalawaGraphQLError({
extensions: {
code: "arguments_associated_resources_not_found",
issues: [
{
argumentPath: ["input", "id"],
},
],
},
});
}

if (
currentUserOrganizationMembership === undefined ||
(currentUserOrganizationMembership.role !== "administrator" &&
existingPost.creatorId !== currentUserId)
) {
throw new TalawaGraphQLError({
extensions: {
code: "unauthorized_action_on_arguments_associated_resources",
issues: [{ argumentPath: ["input", "id"] }],
},
});
}
}
if (currentUser.role !== "administrator") {
const currentUserOrganizationMembership =
existingPost.organization.membershipsWhereOrganization[0];

return await ctx.drizzleClient.transaction(async (tx) => {
const [deletedPost] = await tx
.delete(postsTable)
.where(eq(postsTable.id, parsedArgs.input.id))
.returning();
if (
currentUserOrganizationMembership === undefined ||
(currentUserOrganizationMembership.role !== "administrator" &&
existingPost.creatorId !== currentUserId)
) {
throw new TalawaGraphQLError({
extensions: {
code: "unauthorized_action_on_arguments_associated_resources",
issues: [
{
argumentPath: ["input", "id"],
},
],
},
});
}
}

if (deletedPost === undefined) {
throw new TalawaGraphQLError({
extensions: { code: "unexpected" },
});
}
return await ctx.drizzleClient.transaction(async (tx) => {
const [deletedPost] = await tx
.delete(postsTable)
.where(eq(postsTable.id, parsedArgs.input.id))
.returning();

await ctx.minio.client.removeObjects(
ctx.minio.bucketName,
existingPost.attachmentsWherePost.map(
(attachment: { name: string }) => attachment.name,
),
);
// Deleted post not being returned means that either it was deleted or its `id` column was changed by external entities before this delete operation.
if (deletedPost === undefined) {
throw new TalawaGraphQLError({
extensions: {
code: "unexpected",
},
});
}

return Object.assign(deletedPost, {
attachments: existingPost.attachmentsWherePost,
});
});
}
await ctx.minio.client.removeObjects(
ctx.minio.bucketName,
existingPost.attachmentsWherePost.map(
(attachment) => attachment.name,
),
);

builder.mutationField("deletePost", (t) =>
t.field({
args: {
input: t.arg({
description: "",
required: true,
type: MutationDeletePostInput,
}),
return Object.assign(deletedPost, {
attachments: existingPost.attachmentsWherePost,
});
});
},
description: "Mutation field to delete a post.",
resolve: deletePostResolver,
type: Post,
}),
);
Loading
Loading