export account
parent
76f2eddd40
commit
3128b50540
10
env.example
10
env.example
|
@ -20,4 +20,12 @@ TERMIN_PLANNER_URL=your_termin_planner_url
|
|||
WEBSITE_BUILDER_TEMPLATE_REPOSITORY_URL=https://your-git-repo.com/website-template.git
|
||||
WEBSITE_BUILDER_TMP_DIR=./tmp
|
||||
WEBSITE_BUILDER_TMP_DIR_WEBSITE_TEMPLATE=./tmp/website-template
|
||||
WEBSITE_BUILDER_TMP_CUSTOMER_WEBSITES_DIR=./customer-websites
|
||||
WEBSITE_BUILDER_TMP_CUSTOMER_WEBSITES_DIR=./customer-websites
|
||||
|
||||
RABBITMQ_HOST=
|
||||
RABBITMQ_PORT=
|
||||
RABBITMQ_USERNAME=
|
||||
RABBITMQ_PASSWORD=
|
||||
RABBITMQ_MAIL_QUEUE=
|
||||
|
||||
ACCOUNT_EXPORT_URL=
|
|
@ -9,6 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"amqplib": "^0.10.3",
|
||||
"axios": "^1.6.5",
|
||||
"bcrypt": "^5.1.1",
|
||||
"body-parser": "^1.20.2",
|
||||
|
@ -32,6 +33,7 @@
|
|||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/amqplib": "^0.10.4",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/cookie-parser": "^1.4.6",
|
||||
"@types/cors": "^2.8.17",
|
||||
|
@ -46,6 +48,45 @@
|
|||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@acuminous/bitsyntax": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz",
|
||||
"integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==",
|
||||
"dependencies": {
|
||||
"buffer-more-ints": "~1.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"safe-buffer": "~5.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@acuminous/bitsyntax/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@acuminous/bitsyntax/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/@acuminous/bitsyntax/node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"node_modules/@apidevtools/json-schema-ref-parser": {
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
|
||||
|
@ -121,6 +162,15 @@
|
|||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/amqplib": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.4.tgz",
|
||||
"integrity": "sha512-Y5Sqquh/LqDxSgxYaAAFNM0M7GyONtSDCcFMJk+DQwYEjibPyW6y+Yu9H9omdkKc3epyXULmFN3GTaeBHhn2Hg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/bcrypt": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz",
|
||||
|
@ -431,6 +481,36 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/amqplib": {
|
||||
"version": "0.10.3",
|
||||
"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.3.tgz",
|
||||
"integrity": "sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw==",
|
||||
"dependencies": {
|
||||
"@acuminous/bitsyntax": "^0.1.2",
|
||||
"buffer-more-ints": "~1.0.0",
|
||||
"readable-stream": "1.x >=1.1.9",
|
||||
"url-parse": "~1.5.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/amqplib/node_modules/readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"node_modules/amqplib/node_modules/string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
|
@ -603,6 +683,11 @@
|
|||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-more-ints": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
||||
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
|
@ -812,6 +897,11 @@
|
|||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||
},
|
||||
"node_modules/cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
|
@ -1509,6 +1599,11 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
|
||||
},
|
||||
"node_modules/joycon": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
|
||||
|
@ -2114,6 +2209,11 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
|
||||
},
|
||||
"node_modules/quick-format-unescaped": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
|
||||
|
@ -2188,6 +2288,11 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||
},
|
||||
"node_modules/retry-as-promised": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz",
|
||||
|
@ -2708,6 +2813,15 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/url-parse": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dependencies": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
"scripts": {
|
||||
"build": "npx tsc",
|
||||
"start": "node build/server.js",
|
||||
"dev": "concurrently \"npx tsc --watch\" \"nodemon --ignore ./tmp/ --ignore ./customer-websites/ -q build/server.js | pino-pretty\""
|
||||
"dev": "concurrently \"npx tsc --watch\" \"nodemon --ignore ./tmp/ --ignore ./customer-websites/ --ignore ./user-profile-exports/ -q build/server.js | pino-pretty\""
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"amqplib": "^0.10.3",
|
||||
"axios": "^1.6.5",
|
||||
"bcrypt": "^5.1.1",
|
||||
"body-parser": "^1.20.2",
|
||||
|
@ -34,6 +35,7 @@
|
|||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/amqplib": "^0.10.4",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/cookie-parser": "^1.4.6",
|
||||
"@types/cors": "^2.8.17",
|
||||
|
|
|
@ -7,6 +7,7 @@ import GoogleStrategy from "passport-google-oauth20";
|
|||
import cookieParser from "cookie-parser";
|
||||
import session from "express-session";
|
||||
import useragent from "express-useragent";
|
||||
import rabbitmq from "./src/rabbitmq/rabbitmq";
|
||||
|
||||
import calendarRoutes from "./src/routes/calendarRoutes";
|
||||
import storeRoutes from "./src/routes/storeRoutes";
|
||||
|
@ -23,6 +24,7 @@ import logger from "./src/logger/logger";
|
|||
import passport from "passport";
|
||||
import fs from "fs-extra";
|
||||
import { cloneWebsiteTemplate } from "./src/controllers/websiteController";
|
||||
import { connect } from "amqplib";
|
||||
const app: Express = express();
|
||||
const host = process.env.HOST || "localhost";
|
||||
const port = Number(process.env.PORT) || 3000;
|
||||
|
@ -156,6 +158,13 @@ if (
|
|||
|
||||
// start server
|
||||
|
||||
rabbitmq(
|
||||
process.env.RABBITMQ_USERNAME as string,
|
||||
process.env.RABBITMQ_PASSWORD as string,
|
||||
process.env.RABBITMQ_HOST as string,
|
||||
process.env.RABBITMQ_PORT as string
|
||||
);
|
||||
|
||||
app.listen(port, host, () =>
|
||||
logger.info(`⚡️[server]: Server is running at http://${host}:${port}`)
|
||||
);
|
||||
|
|
|
@ -4,6 +4,7 @@ import User from "../models/user";
|
|||
import {
|
||||
isAccountNameValid,
|
||||
isCompanyNameValid,
|
||||
isEmailValid,
|
||||
isLanguageCodeValid,
|
||||
isPasswordValid,
|
||||
isUsernameValid,
|
||||
|
@ -29,6 +30,8 @@ import {
|
|||
import Store from "../models/store";
|
||||
import Session from "../models/session";
|
||||
import Feedback from "../models/feedback";
|
||||
import fs from "fs-extra";
|
||||
import { channel } from "../rabbitmq/rabbitmq";
|
||||
|
||||
export async function SignUp(req: Request, res: Response) {
|
||||
try {
|
||||
|
@ -644,3 +647,123 @@ export async function DeleteUserProfile(req: Request, res: Response) {
|
|||
res.status(500).send({ err: "invalid request" });
|
||||
}
|
||||
}
|
||||
|
||||
export async function ExportUserAccount(req: Request, res: Response) {
|
||||
try {
|
||||
const { email, password } = req.body;
|
||||
|
||||
if (
|
||||
!email ||
|
||||
!password ||
|
||||
!isEmailValid(email) ||
|
||||
!isPasswordValid(password)
|
||||
) {
|
||||
return res.status(400).send({ err: "invalid request" });
|
||||
}
|
||||
|
||||
const session = await getUserSession(req);
|
||||
|
||||
if (!session) {
|
||||
return res.status(401).send({ err: "unauthorized" });
|
||||
}
|
||||
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
user_id: session.user_id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(401).send({ err: "unauthorized" });
|
||||
}
|
||||
|
||||
const decodedPassword = decodeBase64(password);
|
||||
|
||||
const match = await matchPassword(decodedPassword, user.password);
|
||||
|
||||
if (!match) {
|
||||
return res.status(400).send({ err: "invalid request" });
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
// send email with user data
|
||||
console.log("email");
|
||||
|
||||
// simulate delay
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
|
||||
// create json file with user data
|
||||
|
||||
console.log("file");
|
||||
|
||||
const exportData = {
|
||||
user: {
|
||||
user_id: user.user_id,
|
||||
username: user.username,
|
||||
account_name: user.account_name,
|
||||
calendar_max_future_booking_days:
|
||||
user.calendar_max_future_booking_days,
|
||||
calendar_min_earliest_booking_time:
|
||||
user.calendar_min_earliest_booking_time,
|
||||
calendar_using_primary_calendar:
|
||||
user.calendar_using_primary_calendar,
|
||||
language: user.language,
|
||||
analytics_enabled: user.analytics_enabled,
|
||||
},
|
||||
};
|
||||
|
||||
fs.writeJson(`./user-profile-exports/${user.user_id}.json`, exportData);
|
||||
|
||||
// send email with file
|
||||
|
||||
channel.sendToQueue(
|
||||
process.env.RABBITMQ_MAIL_QUEUE as string,
|
||||
Buffer.from(
|
||||
JSON.stringify({
|
||||
m: "test@roese.dev", // UserMail
|
||||
t: "userAccountExportFinish", // TemplateId
|
||||
l: "de", // LanguageId
|
||||
// BodyData
|
||||
b: {
|
||||
accountExportDownloadUrl: `${
|
||||
process.env.ACCOUNT_EXPORT_URL as string
|
||||
}${user.user_id}`,
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
})();
|
||||
|
||||
res.status(200).json({});
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
res.status(500).send({ err: "invalid request" });
|
||||
}
|
||||
}
|
||||
|
||||
export function GetExportedUserAccount(req: Request, res: Response) {
|
||||
try {
|
||||
const { userId } = req.params;
|
||||
|
||||
if (!userId) {
|
||||
return res.status(400).send({ err: "invalid request" });
|
||||
}
|
||||
|
||||
const file = `./user-profile-exports/${userId}.json`;
|
||||
|
||||
res.download(file, (err) => {
|
||||
if (err) {
|
||||
logger.error(err);
|
||||
res.status(500).send({ err: "invalid request" });
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
res.status(500).send({ err: "invalid request" });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import amqplib from "amqplib";
|
||||
|
||||
export let channel: amqplib.Channel;
|
||||
|
||||
async function connect(
|
||||
RABBITMQ_USERNAME: string,
|
||||
RABBITMQ_PASSWORD: string,
|
||||
RABBITMQ_HOST: string,
|
||||
RABBITMQ_PORT: string
|
||||
) {
|
||||
const open = await amqplib.connect(
|
||||
`amqp://${RABBITMQ_USERNAME}:${RABBITMQ_PASSWORD}@${RABBITMQ_HOST}:${RABBITMQ_PORT}`
|
||||
);
|
||||
|
||||
if (!open) {
|
||||
console.log("RabbitMQ connection failed");
|
||||
return;
|
||||
}
|
||||
|
||||
channel = await open.createChannel();
|
||||
|
||||
if (!channel) {
|
||||
console.log("RabbitMQ channel failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export default connect;
|
|
@ -39,5 +39,11 @@ router.delete(
|
|||
sessionProtection,
|
||||
userController.DeleteUserProfile
|
||||
);
|
||||
router.post(
|
||||
"/profile/export",
|
||||
sessionProtection,
|
||||
userController.ExportUserAccount
|
||||
);
|
||||
router.get("/profile/export/:id", userController.GetExportedUserAccount);
|
||||
|
||||
export default router;
|
||||
|
|
|
@ -63,6 +63,11 @@ export function isPasswordValid(password: string) {
|
|||
);
|
||||
}
|
||||
|
||||
// TODO: regex for email
|
||||
export function isEmailValid(email: string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isUserIdValid(userId: string) {
|
||||
return userId.length === USER_ID_LENGTH;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"user":{"user_id":"4417984c-de81-4930-8ae7-9f178d98ddf7","username":"Alexander","account_name":"alex","calendar_max_future_booking_days":13,"calendar_min_earliest_booking_time":8,"calendar_using_primary_calendar":true,"language":"de","analytics_enabled":false}}
|
Loading…
Reference in New Issue