delete user

main
alex 2024-02-18 13:57:50 +01:00
parent a662087197
commit 65938e3147
4 changed files with 187 additions and 15 deletions

View File

@ -8,7 +8,7 @@ import {
} from "../utils/constants";
import UserPendingPayment from "../models/userPendingPayment";
import User from "../models/user";
import { getUserSession } from "../utils/utils";
import { getUserSession, stripe } from "../utils/utils";
import Store from "../models/store";
import Session from "../models/session";
@ -17,7 +17,6 @@ const ZeitAdlerBasicYearly = "zeitadler-basic-yearly";
const ZeitAdlerPremiumMonthly = "zeitadler-premium-monthly";
const ZeitAdlerPremiumYearly = "zeitadler-premium-yearly";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string);
let cachedPrices = [] as any[];
export async function loadPrices() {

View File

@ -4,6 +4,7 @@ import User from "../models/user";
import {
isCompanyNameValid,
isEmailValid,
isFeedbackValid,
isLanguageCodeValid,
isPasswordValid,
isPaymentIntervalValid,
@ -33,6 +34,7 @@ import {
newStoreId,
newUserId,
saveSession,
stripe,
} from "../utils/utils";
import Store from "../models/store";
import Session from "../models/session";
@ -44,6 +46,13 @@ import EmailVerification from "../models/emailVerification";
import UserPendingEmailChange from "../models/userPendingEmailChange";
import { CreateCheckoutSession, getPriceId } from "./paymentController";
import UserPendingPayment from "../models/userPendingPayment";
import StoreServiceActivity from "../models/storeServiceActivity";
import StoreService from "../models/storeService";
import StoreServiceActivityUsers from "../models/storeServiceActivityUsers";
import {
isTerminPlanerGoogleCalendarConnected,
terminPlanerRequest,
} from "../utils/terminPlaner";
export async function SignUp(req: Request, res: Response) {
try {
@ -799,7 +808,8 @@ export async function DeleteUserProfile(req: Request, res: Response) {
try {
const { reason, feedback, password } = req.body;
if (!reason || !feedback || !password) {
if (!reason || !feedback || !password || !isFeedbackValid(feedback)) {
console.log("invalid request");
return res.status(400).send({ err: "invalid request" });
}
@ -813,7 +823,7 @@ export async function DeleteUserProfile(req: Request, res: Response) {
where: {
user_id: session.user_id,
},
attributes: ["password"],
attributes: ["password", "stripe_customer_id"],
});
if (!user) {
@ -828,18 +838,176 @@ export async function DeleteUserProfile(req: Request, res: Response) {
return res.status(400).send({ err: "invalid request" });
}
// set user state to pending deletion
// delete stripe subscription
await User.update(
{
state: ACCOUNT_STATE.PENDING_DELETION,
},
{
where: {
user_id: session.user_id,
},
if (user.stripe_customer_id) {
const subscription = await stripe.subscriptions.list({
customer: user.stripe_customer_id,
});
if (subscription.data.length > 0) {
const subscriptionId = subscription.data[0].id;
userLogger.info(
session.user_id,
"Canceling stripe subscription id:",
subscriptionId
);
await stripe.subscriptions.cancel(subscriptionId);
}
);
await stripe.customers.del(user.stripe_customer_id);
userLogger.info(
session.user_id,
"Deleted stripe customer id:",
user.stripe_customer_id
);
}
// delete store if user is a store owner
const store = await Store.findOne({
where: {
owner_user_id: session.user_id,
},
attributes: ["store_id"],
});
// user is a store owner
if (store) {
await Store.destroy({
where: {
store_id: store.store_id,
},
});
userLogger.info(session.user_id, "Deleted store id:", store.store_id);
// delete all employees of this store
const employees = await User.findAll({
where: {
store_id: store.store_id,
},
attributes: ["user_id"],
});
if (employees) {
for (const employee of employees) {
const googleCalendarConnected =
await isTerminPlanerGoogleCalendarConnected(employee.user_id);
if (googleCalendarConnected) {
await terminPlanerRequest("/api/v1/removeGoogleAccount", "POST", {
userId: employee.user_id,
});
}
await Session.destroy({
where: {
user_id: employee.user_id,
},
});
userLogger.info(
session.user_id,
"Deleted store employee id:",
employee.user_id
);
}
await User.destroy({
where: {
user_id: employees.map((employee) => employee.user_id),
},
});
userLogger.info(
session.user_id,
"Deleted store employees, count:",
employees.length.toString()
);
}
// delete all store services, store service activities, and store service activity users
const storeServices = await StoreService.findAll({
where: {
store_id: store.store_id,
},
attributes: ["service_id"],
});
if (storeServices) {
const storeServiceActivities = await StoreServiceActivity.findAll({
where: {
service_id: storeServices.map((service) => service.service_id),
},
});
if (storeServiceActivities) {
const storeServiceActivityUsers =
await StoreServiceActivityUsers.findAll({
where: {
activity_id: storeServiceActivities.map(
(activity) => activity.activity_id
),
},
});
if (storeServiceActivityUsers) {
await StoreServiceActivityUsers.destroy({
where: {
activity_id: storeServiceActivityUsers.map(
(activity) => activity.activity_id
),
},
});
userLogger.info(
session.user_id,
"Deleted store service activity users, count:",
storeServiceActivityUsers.length.toString()
);
}
await StoreServiceActivity.destroy({
where: {
activity_id: storeServiceActivities.map(
(activity) => activity.activity_id
),
},
});
userLogger.info(
session.user_id,
"Deleted store service activities, count:",
storeServiceActivities.length.toString()
);
await StoreService.destroy({
where: {
service_id: storeServices.map((service) => service.service_id),
},
});
userLogger.info(
session.user_id,
"Deleted store services, count:",
storeServices.length.toString()
);
}
}
}
// destroy user
await User.destroy({
where: {
user_id: session.user_id,
},
});
// delete all sessions of this user by deleting all sessions with this user_id
@ -857,7 +1025,7 @@ export async function DeleteUserProfile(req: Request, res: Response) {
feedback: `${reason} - ${feedback}`,
});
userLogger.info(session.user_id, "User deleted profile");
userLogger.info(session.user_id, "Deleted user account");
res.status(200).send({ msg: "user deleted" });
} catch (error) {

View File

@ -1,3 +1,5 @@
import Stripe from "stripe";
export const DEFAULT_SESSION_EXPIRY = 365 * 24 * 60 * 60 * 1000; // 365 days
export const SESSION_EXPIRY_NOT_REMEMBER_ME = 60 * 60 * 1000; // 1 hour
export const USER_SESSION_LENGTH = 32;

View File

@ -10,6 +10,7 @@ import {
SESSION_EXPIRY_NOT_REMEMBER_ME,
USER_SESSION_LENGTH,
} from "./constants";
import Stripe from "stripe";
export async function matchPassword(decodedPassword: string, password: string) {
return await bcrypt.compare(decodedPassword, password);
@ -115,3 +116,5 @@ export function getEmailVerificationUrl(
) {
return `${DASHBOARD_URL}/verify/${String(state)}/${emailVerificationId}`;
}
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string);