@internetderdinge/api 1.229.0 → 1.229.1
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.controller.js +89 -0
- package/dist/src/accounts/accounts.route.js +101 -0
- package/dist/src/accounts/accounts.schemas.js +12 -0
- package/dist/src/accounts/accounts.service.js +65 -0
- package/dist/src/accounts/accounts.validation.js +99 -0
- package/dist/src/accounts/auth0.service.js +188 -0
- package/dist/src/config/config.js +48 -0
- package/dist/src/config/logger.js +27 -0
- package/dist/src/config/morgan.js +16 -0
- package/dist/src/config/passport.cjs +28 -0
- package/dist/src/config/roles.js +11 -0
- package/dist/src/config/tokens.cjs +10 -0
- package/dist/src/devices/devices.controller.js +172 -0
- package/dist/src/devices/devices.model.js +94 -0
- package/dist/src/devices/devices.route.js +153 -0
- package/dist/src/devices/devices.schemas.js +84 -0
- package/dist/src/devices/devices.service.js +198 -0
- package/dist/src/devices/devices.types.js +1 -0
- package/dist/src/devices/devices.validation.js +257 -0
- package/dist/src/devicesNotifications/devicesNotifications.controller.js +69 -0
- package/dist/src/devicesNotifications/devicesNotifications.model.js +39 -0
- package/dist/src/devicesNotifications/devicesNotifications.route.js +124 -0
- package/dist/src/devicesNotifications/devicesNotifications.schemas.js +10 -0
- package/dist/src/devicesNotifications/devicesNotifications.service.js +181 -0
- package/dist/src/devicesNotifications/devicesNotifications.validation.js +46 -0
- package/dist/src/email/email.service.js +580 -0
- package/dist/src/files/upload.service.js +124 -0
- package/dist/src/i18n/i18n.js +38 -0
- package/dist/src/i18n/saveMissingLocalJsonBackend.js +53 -0
- package/dist/src/i18n/types.js +1 -0
- package/dist/src/index.js +48 -0
- package/dist/src/iotdevice/iotdevice.controller.js +96 -0
- package/dist/src/iotdevice/iotdevice.model.js +17 -0
- package/dist/src/iotdevice/iotdevice.route.js +143 -0
- package/dist/src/iotdevice/iotdevice.schemas.js +60 -0
- package/dist/src/iotdevice/iotdevice.service.js +579 -0
- package/dist/src/iotdevice/iotdevice.types.js +1 -0
- package/dist/src/iotdevice/iotdevice.validation.js +54 -0
- package/dist/src/middlewares/auth.js +75 -0
- package/dist/src/middlewares/checkJwt.cjs +17 -0
- package/dist/src/middlewares/error.js +36 -0
- package/dist/src/middlewares/mongooseValidations/ensureSameOrganization.js +13 -0
- package/dist/src/middlewares/rateLimiter.js +7 -0
- package/dist/src/middlewares/validate.js +18 -0
- package/dist/src/middlewares/validateAction.js +35 -0
- package/dist/src/middlewares/validateAdmin.js +18 -0
- package/dist/src/middlewares/validateAi.js +16 -0
- package/dist/src/middlewares/validateCurrentAuthUser.js +17 -0
- package/dist/src/middlewares/validateCurrentUser.js +20 -0
- package/dist/src/middlewares/validateDevice.js +98 -0
- package/dist/src/middlewares/validateDeviceUserOrganization.js +26 -0
- package/dist/src/middlewares/validateOrganization.js +63 -0
- package/dist/src/middlewares/validateQuerySearchUserAndOrganization.js +44 -0
- package/dist/src/middlewares/validateTokens.js +23 -0
- package/dist/src/middlewares/validateUser.js +38 -0
- package/dist/src/middlewares/validateZod.js +33 -0
- package/dist/src/models/plugins/index.js +4 -0
- package/dist/src/models/plugins/paginate.plugin.js +117 -0
- package/dist/src/models/plugins/paginateNew.plugin.js +185 -0
- package/dist/src/models/plugins/simplePopulate.js +16 -0
- package/dist/src/models/plugins/toJSON.plugin.js +35 -0
- package/dist/src/organizations/organizations.controller.js +64 -0
- package/dist/src/organizations/organizations.model.js +41 -0
- package/dist/src/organizations/organizations.route.js +98 -0
- package/dist/src/organizations/organizations.schemas.js +7 -0
- package/dist/src/organizations/organizations.service.js +59 -0
- package/dist/src/organizations/organizations.validation.js +62 -0
- package/dist/src/pdf/pdf.controller.js +24 -0
- package/dist/src/pdf/pdf.route.js +22 -0
- package/dist/src/pdf/pdf.schemas.js +6 -0
- package/dist/src/pdf/pdf.service.js +65 -0
- package/dist/src/pdf/pdf.validation.js +27 -0
- package/dist/src/tokens/tokens.controller.js +60 -0
- package/dist/src/tokens/tokens.model.js +18 -0
- package/dist/src/tokens/tokens.route.js +52 -0
- package/dist/src/tokens/tokens.schemas.js +14 -0
- package/dist/src/tokens/tokens.service.js +30 -0
- package/dist/src/tokens/tokens.validation.js +9 -0
- package/dist/src/types/routeSpec.js +1 -0
- package/dist/src/users/users.controller.js +147 -0
- package/dist/src/users/users.model.js +50 -0
- package/dist/src/users/users.route.js +137 -0
- package/dist/src/users/users.schemas.js +69 -0
- package/dist/src/users/users.service.js +295 -0
- package/dist/src/users/users.types.js +1 -0
- package/dist/src/users/users.validation.js +144 -0
- package/dist/src/utils/ApiError.js +16 -0
- package/dist/src/utils/buildRouterAndDocs.js +72 -0
- package/dist/src/utils/catchAsync.js +4 -0
- package/dist/src/utils/comparePapers.service.js +32 -0
- package/dist/src/utils/deviceUtils.js +63 -0
- package/dist/src/utils/filterOptions.js +24 -0
- package/dist/src/utils/medicationName.js +10 -0
- package/dist/src/utils/pick.js +16 -0
- package/dist/src/utils/registerOpenApi.js +28 -0
- package/dist/src/utils/urlUtils.js +15 -0
- package/dist/src/utils/userName.js +22 -0
- package/dist/src/utils/zValidations.js +124 -0
- package/dist/src/validations/auth.validation.cjs +53 -0
- package/dist/src/validations/custom.validation.js +19 -0
- package/dist/src/validations/index.cjs +3 -0
- package/package.json +13 -3
- package/scripts/release-and-sync-paperless.mjs +135 -0
- package/src/accounts/accounts.controller.ts +1 -0
- package/src/accounts/accounts.service.ts +1 -0
- package/src/accounts/accounts.validation.ts +6 -3
- package/src/accounts/auth0.service.ts +55 -28
- package/src/config/config.ts +6 -0
- package/src/config/logger.ts +15 -9
- package/src/devices/devices.controller.ts +7 -1
- package/src/devices/devices.model.ts +4 -1
- package/src/devices/devices.schemas.ts +10 -8
- package/src/devices/devices.service.ts +1 -0
- package/src/devices/devices.types.ts +1 -0
- package/src/devices/devices.validation.ts +85 -23
- package/src/devicesNotifications/devicesNotifications.controller.ts +57 -28
- package/src/devicesNotifications/devicesNotifications.model.ts +20 -12
- package/src/devicesNotifications/devicesNotifications.service.ts +35 -17
- package/src/files/upload.service.ts +52 -28
- package/src/i18n/i18n.ts +1 -1
- package/src/i18n/types.ts +1 -0
- package/src/index.ts +47 -0
- package/src/iotdevice/iotdevice.controller.ts +1 -0
- package/src/iotdevice/iotdevice.model.ts +6 -3
- package/src/iotdevice/iotdevice.route.ts +85 -76
- package/src/iotdevice/iotdevice.service.ts +4 -3
- package/src/iotdevice/iotdevice.types.ts +6 -0
- package/src/middlewares/auth.ts +2 -8
- package/src/middlewares/error.ts +26 -12
- package/src/middlewares/mongooseValidations/ensureSameOrganization.ts +4 -3
- package/src/middlewares/validateAi.ts +17 -9
- package/src/middlewares/validateDevice.ts +1 -0
- package/src/middlewares/validateDeviceUserOrganization.ts +1 -0
- package/src/middlewares/validateOrganization.ts +1 -1
- package/src/middlewares/validateQuerySearchUserAndOrganization.ts +1 -0
- package/src/middlewares/validateTokens.ts +2 -1
- package/src/middlewares/validateUser.ts +1 -0
- package/src/models/plugins/index.ts +5 -4
- package/src/models/plugins/paginate.plugin.ts +26 -16
- package/src/models/plugins/paginateNew.plugin.ts +33 -21
- package/src/models/plugins/simplePopulate.ts +8 -3
- package/src/models/plugins/toJSON.plugin.ts +12 -5
- package/src/organizations/organizations.controller.ts +1 -2
- package/src/organizations/organizations.model.ts +4 -4
- package/src/organizations/organizations.route.ts +1 -1
- package/src/organizations/organizations.service.ts +15 -6
- package/src/pdf/pdf.controller.ts +18 -1
- package/src/pdf/pdf.service.ts +25 -16
- package/src/tokens/tokens.controller.ts +6 -8
- package/src/tokens/tokens.model.ts +3 -1
- package/src/tokens/tokens.service.ts +3 -2
- package/src/types/express.d.ts +17 -0
- package/src/types/mongoose.d.ts +22 -0
- package/src/users/users.controller.ts +8 -9
- package/src/users/users.model.ts +6 -5
- package/src/users/users.route.ts +0 -1
- package/src/users/users.service.ts +16 -0
- package/src/users/users.types.ts +1 -0
- package/src/users/users.validation.ts +6 -2
- package/src/utils/ApiError.ts +8 -1
- package/src/utils/buildRouterAndDocs.ts +56 -21
- package/src/utils/catchAsync.ts +27 -3
- package/src/utils/medicationName.ts +5 -4
- package/src/utils/pick.ts +5 -1
- package/src/utils/userName.ts +1 -0
- package/src/utils/zValidations.ts +78 -26
- package/tsconfig.json +13 -4
package/src/pdf/pdf.service.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import puppeteer from
|
|
2
|
-
import { v4 as uuidv4 } from
|
|
3
|
-
import AWS from
|
|
4
|
-
import path from
|
|
1
|
+
import puppeteer from "puppeteer";
|
|
2
|
+
import { v4 as uuidv4 } from "uuid";
|
|
3
|
+
import AWS from "aws-sdk";
|
|
4
|
+
import path from "path";
|
|
5
5
|
|
|
6
6
|
// Configure AWS SDK
|
|
7
7
|
const s3 = new AWS.S3({
|
|
@@ -11,13 +11,16 @@ const s3 = new AWS.S3({
|
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
// Function to upload a file to S3
|
|
14
|
-
const uploadBuffer = async (
|
|
14
|
+
const uploadBuffer = async (
|
|
15
|
+
buffer: Buffer,
|
|
16
|
+
fileName: string,
|
|
17
|
+
): Promise<string> => {
|
|
15
18
|
const params = {
|
|
16
19
|
Bucket: process.env.AWS_S3_BUCKET_NAME!,
|
|
17
20
|
Key: fileName,
|
|
18
21
|
Body: buffer,
|
|
19
|
-
ContentType:
|
|
20
|
-
ACL:
|
|
22
|
+
ContentType: "application/pdf",
|
|
23
|
+
ACL: "private",
|
|
21
24
|
};
|
|
22
25
|
|
|
23
26
|
const data = await s3.upload(params).promise();
|
|
@@ -32,7 +35,7 @@ const generateSignedUrl = (fileName: string): string => {
|
|
|
32
35
|
Expires: 60 * 60, // URL expiration time in seconds
|
|
33
36
|
};
|
|
34
37
|
|
|
35
|
-
return s3.getSignedUrl(
|
|
38
|
+
return s3.getSignedUrl("getObject", params);
|
|
36
39
|
};
|
|
37
40
|
|
|
38
41
|
interface GeneratePdfOptions {
|
|
@@ -40,7 +43,10 @@ interface GeneratePdfOptions {
|
|
|
40
43
|
token: string;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
const generatePdfFromUrl = async ({
|
|
46
|
+
const generatePdfFromUrl = async ({
|
|
47
|
+
urlPath,
|
|
48
|
+
token,
|
|
49
|
+
}: GeneratePdfOptions): Promise<string> => {
|
|
44
50
|
const domain = process.env.FRONTEND_URL!;
|
|
45
51
|
const browser = await puppeteer.launch({
|
|
46
52
|
defaultViewport: {
|
|
@@ -49,7 +55,7 @@ const generatePdfFromUrl = async ({ urlPath, token }: GeneratePdfOptions): Promi
|
|
|
49
55
|
deviceScaleFactor: 1,
|
|
50
56
|
},
|
|
51
57
|
executablePath: process.env.CHROME_BIN,
|
|
52
|
-
args: [
|
|
58
|
+
args: ["--no-sandbox"],
|
|
53
59
|
});
|
|
54
60
|
|
|
55
61
|
const page = await browser.newPage();
|
|
@@ -58,22 +64,25 @@ const generatePdfFromUrl = async ({ urlPath, token }: GeneratePdfOptions): Promi
|
|
|
58
64
|
|
|
59
65
|
// Set the token in local storage
|
|
60
66
|
await page.evaluate((token) => {
|
|
61
|
-
localStorage.setItem(
|
|
67
|
+
localStorage.setItem("print-token", token);
|
|
62
68
|
}, token);
|
|
63
69
|
|
|
64
|
-
await page.goto(domain + urlPath, { waitUntil:
|
|
70
|
+
await page.goto(domain + urlPath, { waitUntil: "networkidle2" });
|
|
65
71
|
|
|
66
|
-
await page.waitForSelector(
|
|
72
|
+
await page.waitForSelector(".pdf-render-complete");
|
|
67
73
|
|
|
68
|
-
const pdf = await page.pdf({ format:
|
|
74
|
+
const pdf = await page.pdf({ format: "A4", printBackground: true });
|
|
69
75
|
|
|
70
76
|
await page.evaluate(() => {
|
|
71
|
-
localStorage.setItem(
|
|
77
|
+
localStorage.setItem("print-token", "");
|
|
72
78
|
});
|
|
73
79
|
|
|
74
80
|
await browser.close();
|
|
75
81
|
|
|
76
|
-
const fileUrl = await uploadBuffer(
|
|
82
|
+
const fileUrl = await uploadBuffer(
|
|
83
|
+
Buffer.from(pdf),
|
|
84
|
+
`download-${uuidv4()}.pdf`,
|
|
85
|
+
);
|
|
77
86
|
|
|
78
87
|
console.log(`File uploaded successfully. File URL: ${fileUrl}`);
|
|
79
88
|
|
|
@@ -38,16 +38,15 @@ export const createToken = async (
|
|
|
38
38
|
|
|
39
39
|
// Get a token by ID
|
|
40
40
|
export const getToken = async (
|
|
41
|
-
req: Request
|
|
41
|
+
req: Request<{ tokenId: string }>,
|
|
42
42
|
res: Response,
|
|
43
43
|
next: NextFunction,
|
|
44
44
|
): Promise<void> => {
|
|
45
45
|
try {
|
|
46
46
|
const token = await tokensService.getTokenById(req.params.tokenId);
|
|
47
47
|
if (!token) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.send({ message: "Token not found" });
|
|
48
|
+
res.status(httpStatus.NOT_FOUND).send({ message: "Token not found" });
|
|
49
|
+
return;
|
|
51
50
|
}
|
|
52
51
|
res.send(token);
|
|
53
52
|
} catch (error) {
|
|
@@ -57,16 +56,15 @@ export const getToken = async (
|
|
|
57
56
|
|
|
58
57
|
// Delete a token by ID
|
|
59
58
|
export const deleteToken = async (
|
|
60
|
-
req: Request
|
|
59
|
+
req: Request<{ tokenId: string }>,
|
|
61
60
|
res: Response,
|
|
62
61
|
next: NextFunction,
|
|
63
62
|
): Promise<void> => {
|
|
64
63
|
try {
|
|
65
64
|
const token = await tokensService.deleteTokenById(req.params.tokenId);
|
|
66
65
|
if (!token) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.send({ message: "Token not found" });
|
|
66
|
+
res.status(httpStatus.NOT_FOUND).send({ message: "Token not found" });
|
|
67
|
+
return;
|
|
70
68
|
}
|
|
71
69
|
res.status(httpStatus.NO_CONTENT).send();
|
|
72
70
|
} catch (error) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import mongoose, { Schema, Model } from "mongoose";
|
|
2
3
|
import crypto from "crypto";
|
|
3
4
|
import { toJSON, paginate } from "../models/plugins/index.js";
|
|
@@ -19,6 +20,7 @@ const tokenSchema: Schema = new mongoose.Schema(
|
|
|
19
20
|
tokenSchema.plugin(toJSON, true);
|
|
20
21
|
tokenSchema.plugin(paginate);
|
|
21
22
|
|
|
22
|
-
const Token: Model<any> =
|
|
23
|
+
const Token: Model<any> =
|
|
24
|
+
(mongoose.models.Token as Model<any>) || mongoose.model("Token", tokenSchema);
|
|
23
25
|
|
|
24
26
|
export default Token;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import crypto from "crypto";
|
|
2
2
|
import type { Document } from "mongoose";
|
|
3
3
|
import Token from "./tokens.model.js";
|
|
4
|
+
import type { QueryResult } from "../models/plugins/paginate.plugin.js";
|
|
4
5
|
|
|
5
6
|
export const queryTokens = async (
|
|
6
7
|
filter: Record<string, any>,
|
|
7
8
|
options: { sortBy?: string; limit?: number; page?: number },
|
|
8
|
-
): Promise<QueryResult
|
|
9
|
-
return Token.paginate(filter, options);
|
|
9
|
+
): Promise<QueryResult<any>> => {
|
|
10
|
+
return (Token as any).paginate(filter, options);
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
export const createToken = async (
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
declare module "mongoose" {
|
|
2
|
+
const mongoose: any;
|
|
3
|
+
export default mongoose;
|
|
4
|
+
|
|
5
|
+
export type ObjectId = any;
|
|
6
|
+
export type Document = any;
|
|
7
|
+
export type Model<T = any> = any;
|
|
8
|
+
export type Schema<T = any> = any;
|
|
9
|
+
export type Query<T = any> = any;
|
|
10
|
+
export type FilterQuery<T = any> = any;
|
|
11
|
+
export type PaginateOptions = any;
|
|
12
|
+
export type PaginateModel<T = any> = any;
|
|
13
|
+
export type PipelineStage = any;
|
|
14
|
+
|
|
15
|
+
export const Schema: any;
|
|
16
|
+
export const Types: any;
|
|
17
|
+
export function model<T = any>(...args: any[]): Model<T>;
|
|
18
|
+
|
|
19
|
+
export namespace Types {
|
|
20
|
+
type ObjectId = any;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -18,13 +18,13 @@ export const createUser = catchAsync(
|
|
|
18
18
|
async (req: AuthRequest<{}, any, {}>, res: Response) => {
|
|
19
19
|
const { body } = req;
|
|
20
20
|
if (body.email) {
|
|
21
|
-
const
|
|
21
|
+
const auth0users = await auth0Service.getUserIdByEmail(body.email);
|
|
22
22
|
body.status = "invited";
|
|
23
23
|
body.inviteCode = crypto.randomBytes(48).toString("base64url");
|
|
24
24
|
|
|
25
|
-
if (
|
|
25
|
+
if (auth0users[0]) {
|
|
26
26
|
const userFound = await userService.getUserByOwner(
|
|
27
|
-
|
|
27
|
+
auth0users[0].user_id,
|
|
28
28
|
body.organization,
|
|
29
29
|
);
|
|
30
30
|
if (userFound) {
|
|
@@ -101,10 +101,8 @@ export const getCurrentUser = catchAsync(
|
|
|
101
101
|
req: AuthRequest<{}, any, { organization?: string }>,
|
|
102
102
|
res: Response,
|
|
103
103
|
) => {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
req.query.organization,
|
|
107
|
-
);
|
|
104
|
+
const organization = req.query.organization as string;
|
|
105
|
+
const result = await userService.getUserByOwner(req.auth.sub, organization);
|
|
108
106
|
res.send(result);
|
|
109
107
|
},
|
|
110
108
|
);
|
|
@@ -181,9 +179,10 @@ export const getInvite = catchAsync(
|
|
|
181
179
|
`User not found token: ${authReq.params.inviteCode}`,
|
|
182
180
|
);
|
|
183
181
|
}
|
|
182
|
+
const organizationId = String(user.organization);
|
|
184
183
|
const already = await userService.getUserByOwner(
|
|
185
184
|
authReq.auth.sub,
|
|
186
|
-
|
|
185
|
+
organizationId,
|
|
187
186
|
);
|
|
188
187
|
if (already) {
|
|
189
188
|
throw new ApiError(httpStatus.CONFLICT, "User already in organization");
|
|
@@ -222,7 +221,7 @@ export const organizationRemove = catchAsync(
|
|
|
222
221
|
export const cleanup = catchAsync(async (_req: Request, res: Response) => {
|
|
223
222
|
const all = await userService.queryAllCalendars();
|
|
224
223
|
const filtered = all.filter((e) => e.organizationData === null);
|
|
225
|
-
const ids = filtered.map((e) => e._id);
|
|
224
|
+
const ids = filtered.map((e) => String(e._id));
|
|
226
225
|
const deleted = await userService.deleteMany(ids);
|
|
227
226
|
res.send({
|
|
228
227
|
deleted,
|
package/src/users/users.model.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import mongoose, { Schema, Document, Model, Types } from "mongoose";
|
|
2
3
|
import validator from "validator";
|
|
3
4
|
import { toJSON, paginate } from "../models/plugins/index.js";
|
|
@@ -9,9 +10,10 @@ export interface IUser {
|
|
|
9
10
|
timezone: string;
|
|
10
11
|
owner?: string;
|
|
11
12
|
organization?: Types.ObjectId;
|
|
13
|
+
organizationData?: any;
|
|
12
14
|
inviteCode?: string;
|
|
13
15
|
email?: string;
|
|
14
|
-
role:
|
|
16
|
+
role: (typeof roles)[number];
|
|
15
17
|
category: string;
|
|
16
18
|
status?: string;
|
|
17
19
|
meta?: Record<string, any>;
|
|
@@ -83,7 +85,6 @@ userSchema.methods.isPasswordMatch = async function (
|
|
|
83
85
|
return false;
|
|
84
86
|
};
|
|
85
87
|
|
|
86
|
-
export const User =
|
|
87
|
-
|
|
88
|
-
userSchema
|
|
89
|
-
);
|
|
88
|
+
export const User =
|
|
89
|
+
(mongoose.models.User as IUserModel) ||
|
|
90
|
+
mongoose.model<IUserDocument, IUserModel>("User", userSchema);
|
package/src/users/users.route.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import httpStatus from "http-status";
|
|
2
3
|
import type { FilterQuery, PaginateOptions } from "mongoose";
|
|
3
4
|
import { User } from "./users.model.js";
|
|
@@ -315,6 +316,18 @@ export const updateInvite = async (params: {
|
|
|
315
316
|
return user;
|
|
316
317
|
};
|
|
317
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Update a user's organization membership (placeholder for legacy callers)
|
|
321
|
+
*/
|
|
322
|
+
export const organizationUpdate = async (
|
|
323
|
+
_body: any,
|
|
324
|
+
): Promise<IUserDocument> => {
|
|
325
|
+
throw new ApiError(
|
|
326
|
+
httpStatus.NOT_IMPLEMENTED,
|
|
327
|
+
"organizationUpdate not implemented",
|
|
328
|
+
);
|
|
329
|
+
};
|
|
330
|
+
|
|
318
331
|
/**
|
|
319
332
|
* Remove a user from an organization
|
|
320
333
|
*/
|
|
@@ -383,6 +396,7 @@ export default {
|
|
|
383
396
|
organizationInvite,
|
|
384
397
|
getInvite,
|
|
385
398
|
updateInvite,
|
|
399
|
+
organizationUpdate,
|
|
386
400
|
organizationRemove,
|
|
387
401
|
queryUsers,
|
|
388
402
|
queryAllCalendars,
|
|
@@ -391,3 +405,5 @@ export default {
|
|
|
391
405
|
populateAuth0User,
|
|
392
406
|
populateAuth0Users,
|
|
393
407
|
};
|
|
408
|
+
|
|
409
|
+
export type UserService = typeof import("./users.service");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type User = any;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
|
|
3
4
|
import { objectId, password } from "../validations/custom.validation.js";
|
|
@@ -5,6 +6,7 @@ import {
|
|
|
5
6
|
zPagination,
|
|
6
7
|
zGet,
|
|
7
8
|
zObjectId,
|
|
9
|
+
zObjectIdFor,
|
|
8
10
|
zPatchBody,
|
|
9
11
|
zUpdate,
|
|
10
12
|
zDelete,
|
|
@@ -49,9 +51,11 @@ export const createCurrentUserSchema = createUserSchema;
|
|
|
49
51
|
export const queryUsersSchema = {
|
|
50
52
|
...zPagination,
|
|
51
53
|
query: zPagination.query.extend({
|
|
52
|
-
organization:
|
|
54
|
+
organization: zObjectIdFor("organization").openapi({
|
|
53
55
|
description: "Filter users by organization ObjectId",
|
|
54
|
-
example:
|
|
56
|
+
example:
|
|
57
|
+
process.env.SCHEMA_EXAMPLE_ORGANIZATION_ID ||
|
|
58
|
+
"60c72b2f9b1e8d001c8e4f3a",
|
|
55
59
|
}),
|
|
56
60
|
}),
|
|
57
61
|
};
|
package/src/utils/ApiError.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
export class ApiError extends Error {
|
|
2
3
|
statusCode: number;
|
|
3
4
|
isOperational: boolean;
|
|
4
5
|
|
|
5
|
-
constructor(
|
|
6
|
+
constructor(
|
|
7
|
+
statusCode: number,
|
|
8
|
+
message: string,
|
|
9
|
+
isOperational = true,
|
|
10
|
+
stack = "",
|
|
11
|
+
raw: any = null,
|
|
12
|
+
) {
|
|
6
13
|
super(message);
|
|
7
14
|
this.statusCode = statusCode;
|
|
8
15
|
this.isOperational = isOperational;
|
|
@@ -1,28 +1,40 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { RequestHandler, Router } from "express";
|
|
2
|
+
import { registry } from "../utils/registerOpenApi";
|
|
2
3
|
|
|
3
|
-
import { validateZod } from
|
|
4
|
-
import { bearerAuth, xApiKey } from
|
|
4
|
+
import { validateZod } from "../middlewares/validateZod";
|
|
5
|
+
import { bearerAuth, xApiKey } from "../utils/registerOpenApi";
|
|
5
6
|
|
|
6
|
-
import { extendZodWithOpenApi } from
|
|
7
|
-
import { z } from
|
|
7
|
+
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import type { ZodTypeAny } from "zod";
|
|
8
10
|
|
|
9
11
|
extendZodWithOpenApi(z);
|
|
10
12
|
|
|
11
|
-
const roleValidatorNames = [
|
|
13
|
+
const roleValidatorNames = ["validateAiRole", "validateAdmin"];
|
|
12
14
|
function hasRoleValidation(validators: Function[] = []): boolean {
|
|
13
15
|
return validators.some((fn) => roleValidatorNames.includes(fn.name));
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export type RouteSpec = {
|
|
17
|
-
method:
|
|
19
|
+
method: "get" | "post" | "put" | "patch" | "delete" | "options" | "head";
|
|
18
20
|
path: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
validate?: RequestHandler<any, any, any, any, any>[];
|
|
22
|
+
validateWithRequestSchema?: RequestHandler<any, any, any, any, any>[];
|
|
23
|
+
requestSchema?: Partial<Record<string, ZodTypeAny>>;
|
|
24
|
+
responseSchema?: ZodTypeAny;
|
|
25
|
+
handler: RequestHandler<any, any, any, any, any>;
|
|
22
26
|
summary: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
privateDocs?: boolean;
|
|
29
|
+
memoOnly?: boolean;
|
|
23
30
|
};
|
|
24
31
|
|
|
25
|
-
export default function buildAiRouterAndDocs(
|
|
32
|
+
export default function buildAiRouterAndDocs(
|
|
33
|
+
router: Router,
|
|
34
|
+
routeSpecs: any,
|
|
35
|
+
basePath = "/",
|
|
36
|
+
tags: string[] = [],
|
|
37
|
+
) {
|
|
26
38
|
routeSpecs.forEach((spec) => {
|
|
27
39
|
// mount Express
|
|
28
40
|
|
|
@@ -31,11 +43,18 @@ export default function buildAiRouterAndDocs(router: Router, routeSpecs: any, ba
|
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
if (spec.requestSchema) {
|
|
34
|
-
spec.validateWithRequestSchema = [
|
|
46
|
+
spec.validateWithRequestSchema = [
|
|
47
|
+
validateZod(spec.requestSchema),
|
|
48
|
+
...spec.validate,
|
|
49
|
+
];
|
|
35
50
|
}
|
|
36
51
|
|
|
37
52
|
if (spec.validateWithRequestSchema) {
|
|
38
|
-
router[spec.method](
|
|
53
|
+
router[spec.method](
|
|
54
|
+
spec.path,
|
|
55
|
+
...spec.validateWithRequestSchema,
|
|
56
|
+
spec.handler,
|
|
57
|
+
);
|
|
39
58
|
}
|
|
40
59
|
|
|
41
60
|
var { body, ...rest } = spec.requestSchema || {};
|
|
@@ -43,7 +62,7 @@ export default function buildAiRouterAndDocs(router: Router, routeSpecs: any, ba
|
|
|
43
62
|
if (body) {
|
|
44
63
|
rest.body = {
|
|
45
64
|
content: {
|
|
46
|
-
|
|
65
|
+
"application/json": {
|
|
47
66
|
schema: body,
|
|
48
67
|
},
|
|
49
68
|
},
|
|
@@ -52,28 +71,44 @@ export default function buildAiRouterAndDocs(router: Router, routeSpecs: any, ba
|
|
|
52
71
|
|
|
53
72
|
// console.log('spec.requestSchema', body);
|
|
54
73
|
|
|
55
|
-
if (
|
|
74
|
+
if (
|
|
75
|
+
spec.responseSchema &&
|
|
76
|
+
!hasRoleValidation(spec.validate) &&
|
|
77
|
+
spec.privateDocs !== true &&
|
|
78
|
+
spec.memoOnly !== true
|
|
79
|
+
) {
|
|
56
80
|
// collect all middleware fn names (falls back to '<anonymous>' if unnamed)
|
|
57
|
-
const middlewareNames = (spec.validate || []).map(
|
|
81
|
+
const middlewareNames = (spec.validate || []).map(
|
|
82
|
+
(fn) => `\`${fn.name}\`` || "<anonymous>",
|
|
83
|
+
);
|
|
84
|
+
const openApiPath = (basePath + spec.path).replace(
|
|
85
|
+
/:([A-Za-z0-9_]+)/g,
|
|
86
|
+
"{$1}",
|
|
87
|
+
);
|
|
58
88
|
|
|
59
89
|
registry.registerPath({
|
|
60
90
|
method: spec.method,
|
|
61
|
-
path:
|
|
91
|
+
path: openApiPath,
|
|
62
92
|
summary: spec.summary,
|
|
63
93
|
request: rest,
|
|
64
94
|
|
|
65
95
|
// append middleware names to the description
|
|
66
|
-
description: [
|
|
96
|
+
description: [
|
|
97
|
+
spec.description,
|
|
98
|
+
`\n\nMiddlewares: ${middlewareNames.join(", ")}`,
|
|
99
|
+
]
|
|
100
|
+
.filter(Boolean)
|
|
101
|
+
.join("\n"),
|
|
67
102
|
|
|
68
103
|
// (optionally) expose them as a custom extension instead:
|
|
69
|
-
|
|
104
|
+
"x-middlewares": middlewareNames,
|
|
70
105
|
|
|
71
106
|
security: [{ [bearerAuth.name]: [] }, { [xApiKey.name]: [] }],
|
|
72
107
|
responses: {
|
|
73
108
|
200: {
|
|
74
|
-
description:
|
|
109
|
+
description: "Object with user data.",
|
|
75
110
|
content: {
|
|
76
|
-
|
|
111
|
+
"application/json": { schema: spec.responseSchema },
|
|
77
112
|
},
|
|
78
113
|
},
|
|
79
114
|
},
|
package/src/utils/catchAsync.ts
CHANGED
|
@@ -1,8 +1,32 @@
|
|
|
1
|
-
import type { Request, Response, NextFunction } from
|
|
1
|
+
import type { Request, Response, NextFunction } from "express";
|
|
2
|
+
|
|
3
|
+
type AsyncRequestHandler<
|
|
4
|
+
P = any,
|
|
5
|
+
ResBody = any,
|
|
6
|
+
ReqBody = any,
|
|
7
|
+
ReqQuery = any,
|
|
8
|
+
Locals extends Record<string, any> = Record<string, any>,
|
|
9
|
+
> = (
|
|
10
|
+
req: Request<P, ResBody, ReqBody, ReqQuery, Locals>,
|
|
11
|
+
res: Response<ResBody, Locals>,
|
|
12
|
+
next: NextFunction,
|
|
13
|
+
) => Promise<any>;
|
|
2
14
|
|
|
3
15
|
const catchAsync =
|
|
4
|
-
|
|
5
|
-
|
|
16
|
+
<
|
|
17
|
+
P = any,
|
|
18
|
+
ResBody = any,
|
|
19
|
+
ReqBody = any,
|
|
20
|
+
ReqQuery = any,
|
|
21
|
+
Locals extends Record<string, any> = Record<string, any>,
|
|
22
|
+
>(
|
|
23
|
+
fn: AsyncRequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>,
|
|
24
|
+
) =>
|
|
25
|
+
(
|
|
26
|
+
req: Request<P, ResBody, ReqBody, ReqQuery, Locals>,
|
|
27
|
+
res: Response<ResBody, Locals>,
|
|
28
|
+
next: NextFunction,
|
|
29
|
+
): void => {
|
|
6
30
|
Promise.resolve(fn(req, res, next)).catch((err) => next(err));
|
|
7
31
|
};
|
|
8
32
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import i18n from "../i18n/i18n";
|
|
3
|
+
import type { MedicationEntry } from "../types/MedicationEntry";
|
|
3
4
|
|
|
4
5
|
export const medicationName = (entry: MedicationEntry, lng: string): string => {
|
|
5
6
|
const name = entry.medicationData?.Kurzname
|
|
6
7
|
? entry.medicationData.Kurzname
|
|
7
8
|
: entry.localMedicationData?.meta?.name
|
|
8
|
-
? entry.localMedicationData.meta.name.replace(/ .*/,
|
|
9
|
-
: i18n.t(
|
|
9
|
+
? entry.localMedicationData.meta.name.replace(/ .*/, "")
|
|
10
|
+
: i18n.t("A medication", { lng });
|
|
10
11
|
|
|
11
12
|
return name;
|
|
12
13
|
};
|
package/src/utils/pick.ts
CHANGED
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
* @param {string[]} keys - The keys to pick
|
|
5
5
|
* @returns {Partial<Record<string, any>>} - The new object with picked properties
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
// @ts-nocheck
|
|
8
|
+
const pick = <T extends Record<string, any>>(
|
|
9
|
+
object: T,
|
|
10
|
+
keys: string[],
|
|
11
|
+
): Partial<T> => {
|
|
8
12
|
return keys.reduce((obj, key) => {
|
|
9
13
|
if (object && Object.prototype.hasOwnProperty.call(object, key)) {
|
|
10
14
|
obj[key] = object[key];
|
package/src/utils/userName.ts
CHANGED