@internetderdinge/api 1.229.31 → 1.229.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/accounts/accounts.route.js +18 -5
- package/dist/src/admin/adminSearch.controller.js +0 -19
- package/dist/src/admin/adminSearch.route.js +5 -5
- package/dist/src/devices/devices.controller.js +1 -6
- package/dist/src/devices/devices.route.js +13 -13
- package/dist/src/devices/devices.validation.js +0 -47
- package/dist/src/email/email.service.js +6 -6
- package/dist/src/index.js +5 -1
- package/dist/src/iotdevice/iotdevice.route.js +3 -1
- package/dist/src/middlewares/validateAdminOrSupport.js +20 -0
- package/dist/src/organizations/organizations.controller.js +17 -6
- package/dist/src/organizations/organizations.route.js +2 -1
- package/dist/src/users/users.model.js +4 -2
- package/dist/src/users/users.route.js +2 -2
- package/dist/src/users/users.service.js +26 -10
- package/dist/src/users/users.validation.js +60 -61
- package/dist/src/utils/buildRouterAndDocs.js +7 -4
- package/package.json +5 -2
- package/scripts/release-and-sync-paperless.mjs +60 -28
- package/scripts/release-version.mjs +21 -2
- package/src/accounts/accounts.route.ts +21 -5
- package/src/admin/adminSearch.controller.ts +0 -35
- package/src/admin/adminSearch.route.ts +8 -6
- package/src/admin/adminSearch.service.ts +6 -10
- package/src/devices/devices.controller.ts +0 -12
- package/src/devices/devices.route.ts +13 -14
- package/src/devices/devices.validation.ts +0 -47
- package/src/email/email.service.ts +15 -7
- package/src/index.ts +5 -1
- package/src/iotdevice/iotdevice.route.ts +3 -1
- package/src/middlewares/validateAdminOrSupport.ts +34 -0
- package/src/organizations/organizations.controller.ts +38 -7
- package/src/organizations/organizations.route.ts +3 -1
- package/src/users/users.model.ts +7 -3
- package/src/users/users.route.ts +3 -2
- package/src/users/users.service.ts +50 -14
- package/src/users/users.validation.ts +62 -60
- package/src/utils/buildRouterAndDocs.ts +14 -5
- package/dist/src/pdf/pdf.controller.js +0 -24
- package/dist/src/pdf/pdf.route.js +0 -22
- package/dist/src/pdf/pdf.schemas.js +0 -6
- package/dist/src/pdf/pdf.service.js +0 -64
- package/dist/src/pdf/pdf.validation.js +0 -27
- package/src/pdf/pdf.controller.ts +0 -35
- package/src/pdf/pdf.route.ts +0 -28
- package/src/pdf/pdf.schemas.ts +0 -7
- package/src/pdf/pdf.service.ts +0 -103
- package/src/pdf/pdf.validation.ts +0 -30
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import puppeteer from "puppeteer";
|
|
2
|
-
import { v4 as uuidv4 } from "uuid";
|
|
3
|
-
import { GetObjectCommand, PutObjectCommand, S3Client, } from "@aws-sdk/client-s3";
|
|
4
|
-
import { getSignedUrl as getS3SignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
5
|
-
import path from "path";
|
|
6
|
-
const s3 = new S3Client({
|
|
7
|
-
region: process.env.AWS_REGION,
|
|
8
|
-
credentials: process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY
|
|
9
|
-
? {
|
|
10
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
11
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
12
|
-
}
|
|
13
|
-
: undefined,
|
|
14
|
-
});
|
|
15
|
-
// Function to upload a file to S3
|
|
16
|
-
const uploadBuffer = async (buffer, fileName) => {
|
|
17
|
-
await s3.send(new PutObjectCommand({
|
|
18
|
-
Bucket: process.env.AWS_S3_BUCKET_NAME,
|
|
19
|
-
Key: fileName,
|
|
20
|
-
Body: buffer,
|
|
21
|
-
ContentType: "application/pdf",
|
|
22
|
-
}));
|
|
23
|
-
};
|
|
24
|
-
// Generate a signed URL
|
|
25
|
-
const generateSignedUrl = async (fileName) => {
|
|
26
|
-
return getS3SignedUrl(s3, new GetObjectCommand({
|
|
27
|
-
Bucket: process.env.AWS_S3_BUCKET_NAME,
|
|
28
|
-
Key: fileName,
|
|
29
|
-
}), { expiresIn: 60 * 60 });
|
|
30
|
-
};
|
|
31
|
-
const generatePdfFromUrl = async ({ urlPath, token, }) => {
|
|
32
|
-
const domain = process.env.FRONTEND_URL;
|
|
33
|
-
const browser = await puppeteer.launch({
|
|
34
|
-
defaultViewport: {
|
|
35
|
-
width: 1300,
|
|
36
|
-
height: 1200,
|
|
37
|
-
deviceScaleFactor: 1,
|
|
38
|
-
},
|
|
39
|
-
executablePath: process.env.CHROME_BIN,
|
|
40
|
-
args: ["--no-sandbox"],
|
|
41
|
-
});
|
|
42
|
-
const page = await browser.newPage();
|
|
43
|
-
await page.goto(domain);
|
|
44
|
-
// Set the token in local storage
|
|
45
|
-
await page.evaluate((token) => {
|
|
46
|
-
localStorage.setItem("print-token", token);
|
|
47
|
-
}, token);
|
|
48
|
-
await page.goto(domain + urlPath, { waitUntil: "networkidle2" });
|
|
49
|
-
await page.waitForSelector(".pdf-render-complete");
|
|
50
|
-
const pdf = await page.pdf({ format: "A4", printBackground: true });
|
|
51
|
-
await page.evaluate(() => {
|
|
52
|
-
localStorage.setItem("print-token", "");
|
|
53
|
-
});
|
|
54
|
-
await browser.close();
|
|
55
|
-
const fileName = `download-${uuidv4()}.pdf`;
|
|
56
|
-
await uploadBuffer(Buffer.from(pdf), fileName);
|
|
57
|
-
console.log(`File uploaded successfully. File Name: ${fileName}`);
|
|
58
|
-
const signedUrl = await generateSignedUrl(path.basename(fileName));
|
|
59
|
-
console.log(`Signed URL: ${signedUrl}`);
|
|
60
|
-
return signedUrl;
|
|
61
|
-
};
|
|
62
|
-
export default {
|
|
63
|
-
generatePdfFromUrl,
|
|
64
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
extendZodWithOpenApi(z);
|
|
4
|
-
export const generatePdfSchema = {
|
|
5
|
-
query: z.object({
|
|
6
|
-
urlPath: z
|
|
7
|
-
.string()
|
|
8
|
-
/* .url()
|
|
9
|
-
.refine(
|
|
10
|
-
(value) =>
|
|
11
|
-
value.startsWith('https://memo.wirewire.de') ||
|
|
12
|
-
value.startsWith('https://web.wirewire.de') ||
|
|
13
|
-
(process.env.NODE_ENV !== 'production' && value.startsWith('http://localhost:3200')),
|
|
14
|
-
{
|
|
15
|
-
message:
|
|
16
|
-
process.env.NODE_ENV !== 'production'
|
|
17
|
-
? 'urlPath must start with https://memo.wirewire.de, https://web.wirewire.de, or http://localhost:3200'
|
|
18
|
-
: 'urlPath must start with https://memo.wirewire.de or https://web.wirewire.de',
|
|
19
|
-
}
|
|
20
|
-
) */
|
|
21
|
-
.openapi({
|
|
22
|
-
example: 'https://memo.wirewire.de/example.pdf',
|
|
23
|
-
description: 'URL path to the PDF generation endpoint. Allowed domains: https://memo.wirewire.de, https://web.wirewire.de' +
|
|
24
|
-
(process.env.NODE_ENV !== 'production' ? ', or http://localhost:3200 (dev)' : ''),
|
|
25
|
-
}),
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import httpStatus from "http-status";
|
|
2
|
-
import catchAsync from "../utils/catchAsync.js";
|
|
3
|
-
import pdfService from "./pdf.service.js";
|
|
4
|
-
import ApiError from "../utils/ApiError.js";
|
|
5
|
-
|
|
6
|
-
export const generatePdfFromUrl = catchAsync(async (req, res) => {
|
|
7
|
-
const fileName = "memo-print";
|
|
8
|
-
|
|
9
|
-
const authHeader = req.headers["authorization"];
|
|
10
|
-
if (!authHeader) {
|
|
11
|
-
throw new ApiError(httpStatus.UNAUTHORIZED, "Missing Authorization header");
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const token = authHeader.split(" ")[1];
|
|
15
|
-
if (!token) {
|
|
16
|
-
throw new ApiError(httpStatus.UNAUTHORIZED, "Missing bearer token");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const urlPath =
|
|
20
|
-
typeof req.query.urlPath === "string" ? req.query.urlPath : undefined;
|
|
21
|
-
if (!urlPath) {
|
|
22
|
-
throw new ApiError(
|
|
23
|
-
httpStatus.BAD_REQUEST,
|
|
24
|
-
"Missing urlPath query parameter",
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const result = await pdfService.generatePdfFromUrl({ urlPath, token });
|
|
29
|
-
|
|
30
|
-
res.status(httpStatus.CREATED).send({ signed: result });
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
export default {
|
|
34
|
-
generatePdfFromUrl,
|
|
35
|
-
};
|
package/src/pdf/pdf.route.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Router } from "express";
|
|
2
|
-
import buildRouterAndDocs from "../utils/buildRouterAndDocs.js";
|
|
3
|
-
import { generatePdfSchema } from "./pdf.validation.js";
|
|
4
|
-
import { pdfResponseSchema } from "./pdf.schemas.js";
|
|
5
|
-
import { generatePdfFromUrl } from "./pdf.controller.js";
|
|
6
|
-
import type { RouteSpec } from "../types/routeSpec";
|
|
7
|
-
import auth from "../middlewares/auth.js";
|
|
8
|
-
|
|
9
|
-
export const pdfRouteSpecs: RouteSpec[] = [
|
|
10
|
-
{
|
|
11
|
-
method: "get",
|
|
12
|
-
path: "/",
|
|
13
|
-
validate: [auth("manageUsers")],
|
|
14
|
-
requestSchema: generatePdfSchema,
|
|
15
|
-
responseSchema: pdfResponseSchema,
|
|
16
|
-
handler: generatePdfFromUrl,
|
|
17
|
-
summary: "Generate a PDF from a provided URL",
|
|
18
|
-
description:
|
|
19
|
-
"This endpoint allows users to generate a PDF document from a specified URL.",
|
|
20
|
-
memoOnly: true,
|
|
21
|
-
},
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
const router: Router = Router();
|
|
25
|
-
|
|
26
|
-
buildRouterAndDocs(router, pdfRouteSpecs, "/pdf", ["PDF"]);
|
|
27
|
-
|
|
28
|
-
export default router;
|
package/src/pdf/pdf.schemas.ts
DELETED
package/src/pdf/pdf.service.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import puppeteer from "puppeteer";
|
|
2
|
-
import { v4 as uuidv4 } from "uuid";
|
|
3
|
-
import {
|
|
4
|
-
GetObjectCommand,
|
|
5
|
-
PutObjectCommand,
|
|
6
|
-
S3Client,
|
|
7
|
-
} from "@aws-sdk/client-s3";
|
|
8
|
-
import { getSignedUrl as getS3SignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
9
|
-
import path from "path";
|
|
10
|
-
|
|
11
|
-
const s3 = new S3Client({
|
|
12
|
-
region: process.env.AWS_REGION,
|
|
13
|
-
credentials:
|
|
14
|
-
process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY
|
|
15
|
-
? {
|
|
16
|
-
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
17
|
-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
18
|
-
}
|
|
19
|
-
: undefined,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
// Function to upload a file to S3
|
|
23
|
-
const uploadBuffer = async (
|
|
24
|
-
buffer: Buffer,
|
|
25
|
-
fileName: string,
|
|
26
|
-
): Promise<void> => {
|
|
27
|
-
await s3.send(
|
|
28
|
-
new PutObjectCommand({
|
|
29
|
-
Bucket: process.env.AWS_S3_BUCKET_NAME!,
|
|
30
|
-
Key: fileName,
|
|
31
|
-
Body: buffer,
|
|
32
|
-
ContentType: "application/pdf",
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Generate a signed URL
|
|
38
|
-
const generateSignedUrl = async (fileName: string): Promise<string> => {
|
|
39
|
-
return getS3SignedUrl(
|
|
40
|
-
s3,
|
|
41
|
-
new GetObjectCommand({
|
|
42
|
-
Bucket: process.env.AWS_S3_BUCKET_NAME!,
|
|
43
|
-
Key: fileName,
|
|
44
|
-
}),
|
|
45
|
-
{ expiresIn: 60 * 60 },
|
|
46
|
-
);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
interface GeneratePdfOptions {
|
|
50
|
-
urlPath: string;
|
|
51
|
-
token: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const generatePdfFromUrl = async ({
|
|
55
|
-
urlPath,
|
|
56
|
-
token,
|
|
57
|
-
}: GeneratePdfOptions): Promise<string> => {
|
|
58
|
-
const domain = process.env.FRONTEND_URL!;
|
|
59
|
-
const browser = await puppeteer.launch({
|
|
60
|
-
defaultViewport: {
|
|
61
|
-
width: 1300,
|
|
62
|
-
height: 1200,
|
|
63
|
-
deviceScaleFactor: 1,
|
|
64
|
-
},
|
|
65
|
-
executablePath: process.env.CHROME_BIN,
|
|
66
|
-
args: ["--no-sandbox"],
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const page = await browser.newPage();
|
|
70
|
-
|
|
71
|
-
await page.goto(domain);
|
|
72
|
-
|
|
73
|
-
// Set the token in local storage
|
|
74
|
-
await page.evaluate((token) => {
|
|
75
|
-
localStorage.setItem("print-token", token);
|
|
76
|
-
}, token);
|
|
77
|
-
|
|
78
|
-
await page.goto(domain + urlPath, { waitUntil: "networkidle2" });
|
|
79
|
-
|
|
80
|
-
await page.waitForSelector(".pdf-render-complete");
|
|
81
|
-
|
|
82
|
-
const pdf = await page.pdf({ format: "A4", printBackground: true });
|
|
83
|
-
|
|
84
|
-
await page.evaluate(() => {
|
|
85
|
-
localStorage.setItem("print-token", "");
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
await browser.close();
|
|
89
|
-
|
|
90
|
-
const fileName = `download-${uuidv4()}.pdf`;
|
|
91
|
-
await uploadBuffer(Buffer.from(pdf), fileName);
|
|
92
|
-
|
|
93
|
-
console.log(`File uploaded successfully. File Name: ${fileName}`);
|
|
94
|
-
|
|
95
|
-
const signedUrl = await generateSignedUrl(path.basename(fileName));
|
|
96
|
-
console.log(`Signed URL: ${signedUrl}`);
|
|
97
|
-
|
|
98
|
-
return signedUrl;
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
export default {
|
|
102
|
-
generatePdfFromUrl,
|
|
103
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
|
|
4
|
-
extendZodWithOpenApi(z);
|
|
5
|
-
|
|
6
|
-
export const generatePdfSchema = {
|
|
7
|
-
query: z.object({
|
|
8
|
-
urlPath: z
|
|
9
|
-
.string()
|
|
10
|
-
/* .url()
|
|
11
|
-
.refine(
|
|
12
|
-
(value) =>
|
|
13
|
-
value.startsWith('https://memo.wirewire.de') ||
|
|
14
|
-
value.startsWith('https://web.wirewire.de') ||
|
|
15
|
-
(process.env.NODE_ENV !== 'production' && value.startsWith('http://localhost:3200')),
|
|
16
|
-
{
|
|
17
|
-
message:
|
|
18
|
-
process.env.NODE_ENV !== 'production'
|
|
19
|
-
? 'urlPath must start with https://memo.wirewire.de, https://web.wirewire.de, or http://localhost:3200'
|
|
20
|
-
: 'urlPath must start with https://memo.wirewire.de or https://web.wirewire.de',
|
|
21
|
-
}
|
|
22
|
-
) */
|
|
23
|
-
.openapi({
|
|
24
|
-
example: 'https://memo.wirewire.de/example.pdf',
|
|
25
|
-
description:
|
|
26
|
-
'URL path to the PDF generation endpoint. Allowed domains: https://memo.wirewire.de, https://web.wirewire.de' +
|
|
27
|
-
(process.env.NODE_ENV !== 'production' ? ', or http://localhost:3200 (dev)' : ''),
|
|
28
|
-
}),
|
|
29
|
-
}),
|
|
30
|
-
};
|