fix: Better error reporting & some fixes to deleteUser API (#12439)

This commit is contained in:
Alex van Andel 2023-11-20 13:28:25 +00:00 committed by GitHub
parent 608b891536
commit 8e7785ca64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 21 deletions

View File

@ -1,5 +1,6 @@
import type { NextApiRequest } from "next";
import { deleteUser } from "@calcom/features/users/lib/userDeletionService";
import { HttpError } from "@calcom/lib/http-error";
import { defaultResponder } from "@calcom/lib/server";
@ -41,10 +42,18 @@ export async function deleteHandler(req: NextApiRequest) {
// Here we only check for ownership of the user if the user is not admin, otherwise we let ADMIN's edit any user
if (!isAdmin && query.userId !== req.userId) throw new HttpError({ statusCode: 403, message: "Forbidden" });
const user = await prisma.user.findUnique({ where: { id: query.userId } });
const user = await prisma.user.findUnique({
where: { id: query.userId },
select: {
id: true,
email: true,
metadata: true,
},
});
if (!user) throw new HttpError({ statusCode: 404, message: "User not found" });
await prisma.user.delete({ where: { id: user.id } });
await deleteUser(user);
return { message: `User with id: ${user.id} deleted successfully` };
}

View File

@ -0,0 +1,20 @@
import type { User } from "@prisma/client";
import { deleteStripeCustomer } from "@calcom/app-store/stripepayment/lib/customer";
import { deleteWebUser as syncServicesDeleteWebUser } from "@calcom/lib/sync/SyncServiceManager";
import prisma from "@calcom/prisma";
export async function deleteUser(user: Pick<User, "id" | "email" | "metadata">) {
// If 2FA is disabled or totpCode is valid then delete the user from stripe and database
await deleteStripeCustomer(user).catch(console.warn);
// Remove my account
// TODO: Move this to Repository pattern.
const deletedUser = await prisma.user.delete({
where: {
id: user.id,
},
});
// Sync Services
syncServicesDeleteWebUser(deletedUser);
}

View File

@ -1,8 +1,8 @@
import { deleteStripeCustomer } from "@calcom/app-store/stripepayment/lib/customer";
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
import { verifyPassword } from "@calcom/features/auth/lib/verifyPassword";
import { deleteUser } from "@calcom/features/users/lib/userDeletionService";
import { symmetricDecrypt } from "@calcom/lib/crypto";
import { deleteWebUser as syncServicesDeleteWebUser } from "@calcom/lib/sync/SyncServiceManager";
import { HttpError } from "@calcom/lib/http-error";
import { totpAuthenticatorCheck } from "@calcom/lib/totp";
import { prisma } from "@calcom/prisma";
import { IdentityProvider } from "@calcom/prisma/enums";
@ -18,32 +18,43 @@ type DeleteMeOptions = {
};
export const deleteMeHandler = async ({ ctx, input }: DeleteMeOptions) => {
// TODO: First check password is part of input and meets requirements.
// Check if input.password is correct
const user = await prisma.user.findUnique({
where: {
email: ctx.user.email.toLowerCase(),
},
select: {
identityProvider: true,
twoFactorEnabled: true,
twoFactorSecret: true,
password: true,
email: true,
metadata: true,
id: true,
},
});
if (!user) {
throw new Error(ErrorCode.UserNotFound);
throw new HttpError({ statusCode: 404, message: ErrorCode.UserNotFound });
}
if (user.identityProvider !== IdentityProvider.CAL) {
throw new Error(ErrorCode.ThirdPartyIdentityProviderEnabled);
throw new HttpError({ statusCode: 400, message: ErrorCode.ThirdPartyIdentityProviderEnabled });
}
if (!user.password) {
throw new Error(ErrorCode.UserMissingPassword);
throw new HttpError({ statusCode: 400, message: ErrorCode.UserMissingPassword });
}
const isCorrectPassword = await verifyPassword(input.password, user.password);
if (!isCorrectPassword) {
throw new Error(ErrorCode.IncorrectPassword);
throw new HttpError({ statusCode: 403, message: ErrorCode.IncorrectPassword });
}
if (user.twoFactorEnabled) {
if (!input.totpCode) {
throw new Error(ErrorCode.SecondFactorRequired);
throw new HttpError({ statusCode: 400, message: ErrorCode.SecondFactorRequired });
}
if (!user.twoFactorSecret) {
@ -67,20 +78,10 @@ export const deleteMeHandler = async ({ ctx, input }: DeleteMeOptions) => {
// If user has 2fa enabled, check if input.totpCode is correct
const isValidToken = totpAuthenticatorCheck(input.totpCode, secret);
if (!isValidToken) {
throw new Error(ErrorCode.IncorrectTwoFactorCode);
throw new HttpError({ statusCode: 403, message: ErrorCode.IncorrectTwoFactorCode });
}
}
// If 2FA is disabled or totpCode is valid then delete the user from stripe and database
await deleteStripeCustomer(user).catch(console.warn);
// Remove my account
const deletedUser = await prisma.user.delete({
where: {
id: ctx.user.id,
},
});
// Sync Services
syncServicesDeleteWebUser(deletedUser);
await deleteUser(user);
return;
};