@internetderdinge/api 1.229.3 → 1.229.4
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 +7 -5
- package/dist/src/accounts/accounts.validation.js +4 -12
- package/dist/src/accounts/auth0.service.js +14 -13
- package/dist/src/devices/devices.route.js +12 -2
- package/dist/src/devicesNotifications/devicesNotifications.controller.js +1 -0
- package/dist/src/middlewares/auth.js +2 -0
- package/dist/src/middlewares/validateAdmin.js +7 -5
- package/dist/src/users/users.route.js +0 -2
- package/dist/src/users/users.service.js +2 -0
- package/dist/src/users/users.validation.js +10 -16
- package/dist/src/utils/userName.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/accounts/accounts.controller.ts +8 -5
- package/src/accounts/accounts.validation.ts +19 -24
- package/src/accounts/auth0.service.ts +9 -5
- package/src/devices/devices.route.ts +11 -0
- package/src/devicesNotifications/devicesNotifications.controller.ts +2 -0
- package/src/middlewares/auth.ts +3 -1
- package/src/middlewares/validateAdmin.ts +18 -7
- package/src/users/users.route.ts +0 -2
- package/src/users/users.service.ts +14 -0
- package/src/users/users.validation.ts +10 -17
- package/src/utils/userName.ts +1 -1
package/package.json
CHANGED
|
@@ -36,7 +36,7 @@ const getAccountById = catchAsync(
|
|
|
36
36
|
throw new ApiError(httpStatus.NOT_FOUND, "Account not found");
|
|
37
37
|
}
|
|
38
38
|
res.send({
|
|
39
|
-
...account
|
|
39
|
+
...account,
|
|
40
40
|
notification: entryDeviceNotifications?.settings,
|
|
41
41
|
});
|
|
42
42
|
},
|
|
@@ -46,7 +46,7 @@ const setDeviceToken = catchAsync(
|
|
|
46
46
|
async (req: AuthenticatedRequest, res: Response): Promise<void> => {
|
|
47
47
|
const account = await accountsService.getAccountById(req.auth.sub);
|
|
48
48
|
|
|
49
|
-
const devices: Device[] = account.
|
|
49
|
+
const devices: Device[] = account.app_metadata.devices || [];
|
|
50
50
|
const alreadyExisting = devices.find((d) => d.fck === req.body.token);
|
|
51
51
|
if (!alreadyExisting) {
|
|
52
52
|
devices.push({ fck: req.body.token });
|
|
@@ -74,7 +74,9 @@ const updateEntry = catchAsync(
|
|
|
74
74
|
async (req: AuthenticatedRequest, res: Response): Promise<void> => {
|
|
75
75
|
const account = await accountsService.getAccountById(req.auth.sub);
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
console.log("account", account);
|
|
78
|
+
|
|
79
|
+
const { isSocial } = account.identities[0];
|
|
78
80
|
|
|
79
81
|
const {
|
|
80
82
|
given_name,
|
|
@@ -93,7 +95,7 @@ const updateEntry = catchAsync(
|
|
|
93
95
|
|
|
94
96
|
const update = isSocial
|
|
95
97
|
? {
|
|
96
|
-
...account.
|
|
98
|
+
...account.app_metadata,
|
|
97
99
|
...updateBody,
|
|
98
100
|
...(hasGivenName ? { first_name: trimmedGivenName } : {}),
|
|
99
101
|
...(hasFamilyName ? { last_name: trimmedFamilyName } : {}),
|
|
@@ -136,7 +138,8 @@ const deleteCurrent = catchAsync(
|
|
|
136
138
|
const current = catchAsync(
|
|
137
139
|
async (req: AuthenticatedRequest, res: Response): Promise<void> => {
|
|
138
140
|
const user = await accountsService.getAccountById(req.auth.sub);
|
|
139
|
-
|
|
141
|
+
console.log("user", user);
|
|
142
|
+
res.send(user);
|
|
140
143
|
},
|
|
141
144
|
);
|
|
142
145
|
|
|
@@ -35,25 +35,21 @@ export const getUsersSchema = zPagination;
|
|
|
35
35
|
|
|
36
36
|
export const getAccountSchema = {
|
|
37
37
|
params: z.object({
|
|
38
|
-
accountId: z
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
description: "Auth Account ID",
|
|
44
|
-
}),
|
|
38
|
+
accountId: z.string().openapi({
|
|
39
|
+
example:
|
|
40
|
+
process.env.SCHEMA_EXAMPLE_ACCOUNT_ID || "auth0|60452f4c0dc85b0062326",
|
|
41
|
+
description: "Auth Account ID",
|
|
42
|
+
}),
|
|
45
43
|
}),
|
|
46
44
|
};
|
|
47
45
|
|
|
48
46
|
export const updateAccountSchema = {
|
|
49
47
|
params: z.object({
|
|
50
|
-
accountId: z
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
description: "Auth Account ID",
|
|
56
|
-
}),
|
|
48
|
+
accountId: z.string().openapi({
|
|
49
|
+
example:
|
|
50
|
+
process.env.SCHEMA_EXAMPLE_ACCOUNT_ID || "auth0|60452f4c0dc85b0062326",
|
|
51
|
+
description: "Auth Account ID",
|
|
52
|
+
}),
|
|
57
53
|
}),
|
|
58
54
|
body: zPatchBody({
|
|
59
55
|
language: z
|
|
@@ -67,9 +63,10 @@ export const updateAccountSchema = {
|
|
|
67
63
|
.optional()
|
|
68
64
|
.openapi({ example: "female", description: "Gender" }),
|
|
69
65
|
email: z
|
|
70
|
-
.
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
.preprocess(
|
|
67
|
+
(value) => (value === "" ? undefined : value),
|
|
68
|
+
z.string().email().optional(),
|
|
69
|
+
)
|
|
73
70
|
.openapi({ description: "User email address" }),
|
|
74
71
|
given_name: z
|
|
75
72
|
.string()
|
|
@@ -90,13 +87,11 @@ export const updateAccountSchema = {
|
|
|
90
87
|
|
|
91
88
|
export const deleteEntrySchema = {
|
|
92
89
|
params: z.object({
|
|
93
|
-
accountId: z
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
description: "Auth Account ID",
|
|
99
|
-
}),
|
|
90
|
+
accountId: z.string().openapi({
|
|
91
|
+
example:
|
|
92
|
+
process.env.SCHEMA_EXAMPLE_ACCOUNT_ID || "auth0|60452f4c0dc85b0062326",
|
|
93
|
+
description: "Auth Account ID",
|
|
94
|
+
}),
|
|
100
95
|
}),
|
|
101
96
|
};
|
|
102
97
|
|
|
@@ -21,6 +21,7 @@ let tokenManagementClient: TokenManagementClient = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
//if (config.env !== 'production') {
|
|
24
|
+
/*
|
|
24
25
|
try {
|
|
25
26
|
console.warn("Auth0 client: use local token from cache try");
|
|
26
27
|
const token = readFileSync("./token.txt", "utf8");
|
|
@@ -28,7 +29,7 @@ try {
|
|
|
28
29
|
tokenManagementClient = { token };
|
|
29
30
|
} catch (error) {
|
|
30
31
|
console.log("Auth0 Client: use new token");
|
|
31
|
-
}
|
|
32
|
+
} */
|
|
32
33
|
//}
|
|
33
34
|
|
|
34
35
|
// IoT Api
|
|
@@ -123,12 +124,12 @@ export const getAuth0Token = async (): Promise<string> => {
|
|
|
123
124
|
pendingTokenPromise = null;
|
|
124
125
|
return cachedToken;
|
|
125
126
|
}
|
|
126
|
-
//}
|
|
127
127
|
|
|
128
|
+
console.warn("Auth0 Client: Requesting new token from Auth0");
|
|
128
129
|
const tokenResponse =
|
|
129
130
|
await auth0AuthClient.oauth.clientCredentialsGrant(grantOpts);
|
|
130
|
-
const expiresIn = tokenResponse.
|
|
131
|
-
cachedToken = tokenResponse.
|
|
131
|
+
const expiresIn = tokenResponse.expires_in || 3600;
|
|
132
|
+
cachedToken = tokenResponse.access_token;
|
|
132
133
|
tokenExpiresAt = now + expiresIn;
|
|
133
134
|
|
|
134
135
|
// if (process.env.NODE_ENV !== 'production') {
|
|
@@ -159,6 +160,7 @@ export const getAuth0ManagementToken = async (): Promise<string> => {
|
|
|
159
160
|
|
|
160
161
|
pendingManagementTokenPromise = (async () => {
|
|
161
162
|
const fileToken = await loadTokenFromFile(MANAGEMENT_TOKEN_FILE_PATH);
|
|
163
|
+
|
|
162
164
|
if (fileToken && fileToken.expiresAt > now + TOKEN_BUFFER_SECONDS) {
|
|
163
165
|
cachedManagementToken = fileToken.token;
|
|
164
166
|
managementTokenExpiresAt = fileToken.expiresAt;
|
|
@@ -166,8 +168,10 @@ export const getAuth0ManagementToken = async (): Promise<string> => {
|
|
|
166
168
|
return cachedManagementToken;
|
|
167
169
|
}
|
|
168
170
|
|
|
171
|
+
console.warn("Auth0 Management Client: Requesting new token from Auth0");
|
|
169
172
|
const tokenResponse =
|
|
170
173
|
await auth0AuthClient.oauth.clientCredentialsGrant(grantOpts);
|
|
174
|
+
|
|
171
175
|
const expiresIn = tokenResponse.data.expires_in || 3600;
|
|
172
176
|
cachedManagementToken = tokenResponse.data.access_token;
|
|
173
177
|
managementTokenExpiresAt = now + expiresIn;
|
|
@@ -238,7 +242,7 @@ export const getUsersByIds = async (postIDs: string[]): Promise<User[]> => {
|
|
|
238
242
|
};
|
|
239
243
|
|
|
240
244
|
const page = await auth0.users.list(params);
|
|
241
|
-
return page
|
|
245
|
+
return page || [];
|
|
242
246
|
};
|
|
243
247
|
|
|
244
248
|
export default {
|
|
@@ -94,6 +94,17 @@ export const devicesRouteSpecs: RouteSpec[] = [
|
|
|
94
94
|
{
|
|
95
95
|
method: "post",
|
|
96
96
|
path: "/:deviceId",
|
|
97
|
+
validate: [auth("manageUsers"), validateDevice, validateOrganizationUpdate],
|
|
98
|
+
requestSchema: updateDeviceSchema,
|
|
99
|
+
responseSchema: deviceResponseSchema,
|
|
100
|
+
handler: devicesController.updateEntry,
|
|
101
|
+
summary: "Update a device",
|
|
102
|
+
description:
|
|
103
|
+
"Modify the properties of an existing device identified by its ID.",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
method: "delete",
|
|
107
|
+
path: "/:deviceId",
|
|
97
108
|
handler: devicesController.deleteEntry,
|
|
98
109
|
summary: "Delete a device",
|
|
99
110
|
description: "Remove the specified device from the system.",
|
package/src/middlewares/auth.ts
CHANGED
|
@@ -36,17 +36,18 @@ const verifyCallback: VerifyCallback =
|
|
|
36
36
|
return reject(new ApiError(httpStatus.FORBIDDEN, "Forbidden"));
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
|
|
40
39
|
resolve();
|
|
41
40
|
};
|
|
42
41
|
|
|
43
42
|
const auth = function authFactory(...requiredRights: string[]) {
|
|
43
|
+
console.log("Creating auth middleware with required rights:", requiredRights);
|
|
44
44
|
return async function authMiddleware(
|
|
45
45
|
req: AuthRequest,
|
|
46
46
|
res: Response,
|
|
47
47
|
next: NextFunction,
|
|
48
48
|
): Promise<void> {
|
|
49
49
|
try {
|
|
50
|
+
console.log("Authenticating request:");
|
|
50
51
|
// Check for custom token in X-API-Key header
|
|
51
52
|
const apiKey = req.headers["x-api-key"] as string | undefined;
|
|
52
53
|
if (apiKey && apiKey.length === 64) {
|
|
@@ -93,6 +94,7 @@ const auth = function authFactory(...requiredRights: string[]) {
|
|
|
93
94
|
err.message || "Sorry we were unable to process your request.";
|
|
94
95
|
return res.status(status).send({ message });
|
|
95
96
|
}
|
|
97
|
+
|
|
96
98
|
next();
|
|
97
99
|
});
|
|
98
100
|
} catch (error) {
|
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
import httpStatus from
|
|
2
|
-
import ApiError from
|
|
3
|
-
import type { Request, Response, NextFunction } from
|
|
1
|
+
import httpStatus from "http-status";
|
|
2
|
+
import ApiError from "../utils/ApiError";
|
|
3
|
+
import type { Request, Response, NextFunction } from "express";
|
|
4
4
|
|
|
5
5
|
const isAdmin = (user: Record<string, any> | undefined): boolean => {
|
|
6
|
-
|
|
6
|
+
return false;
|
|
7
7
|
if (!user) return false;
|
|
8
8
|
|
|
9
9
|
// return false; // TODO: Remove this line when the user object is properly defined
|
|
10
|
-
return user[
|
|
10
|
+
return user["https://memo.wirewire.de/roles"]
|
|
11
|
+
? user["https://memo.wirewire.de/roles"].includes("admin")
|
|
12
|
+
: false;
|
|
11
13
|
};
|
|
12
14
|
|
|
13
|
-
const validateAdmin = async (
|
|
15
|
+
const validateAdmin = async (
|
|
16
|
+
req: Request,
|
|
17
|
+
res: Response,
|
|
18
|
+
next: NextFunction,
|
|
19
|
+
): Promise<void> => {
|
|
14
20
|
if (isAdmin(req.auth)) {
|
|
15
21
|
next();
|
|
16
22
|
} else {
|
|
17
|
-
next(
|
|
23
|
+
next(
|
|
24
|
+
new ApiError(
|
|
25
|
+
httpStatus.FORBIDDEN,
|
|
26
|
+
"User is not part of the admin group (validateAdmin)",
|
|
27
|
+
),
|
|
28
|
+
);
|
|
18
29
|
}
|
|
19
30
|
};
|
|
20
31
|
|
package/src/users/users.route.ts
CHANGED
|
@@ -138,7 +138,6 @@ export const userRouteSpecs: RouteSpec[] = [
|
|
|
138
138
|
handler: userController.updateUser,
|
|
139
139
|
summary: "Update a user by ID",
|
|
140
140
|
description: "Replaces a user’s full record with the provided data.",
|
|
141
|
-
memoOnly: true,
|
|
142
141
|
},
|
|
143
142
|
{
|
|
144
143
|
method: "patch",
|
|
@@ -149,7 +148,6 @@ export const userRouteSpecs: RouteSpec[] = [
|
|
|
149
148
|
handler: userController.updateUser,
|
|
150
149
|
summary: "Partially update a user by ID",
|
|
151
150
|
description: "Applies partial updates to a user’s record by ID.",
|
|
152
|
-
memoOnly: true,
|
|
153
151
|
},
|
|
154
152
|
{
|
|
155
153
|
method: "delete",
|
|
@@ -149,7 +149,21 @@ export const getUserByOwner = async (
|
|
|
149
149
|
): Promise<any | null> => {
|
|
150
150
|
const user = await User.findOne({ owner, organization });
|
|
151
151
|
if (!user) return null;
|
|
152
|
+
|
|
153
|
+
console.log(
|
|
154
|
+
"Found user for owner and organization:",
|
|
155
|
+
owner,
|
|
156
|
+
organization,
|
|
157
|
+
user,
|
|
158
|
+
);
|
|
152
159
|
const auth0User = await populateAuth0User(user);
|
|
160
|
+
|
|
161
|
+
console.log(
|
|
162
|
+
"Found user for owner and organizationddddddd:",
|
|
163
|
+
owner,
|
|
164
|
+
organization,
|
|
165
|
+
user,
|
|
166
|
+
);
|
|
153
167
|
const json = user.toJSON();
|
|
154
168
|
json.auth0User = auth0User;
|
|
155
169
|
return json;
|
|
@@ -71,21 +71,6 @@ export const getCurrentUserSchema = {
|
|
|
71
71
|
export const updateUserSchema = {
|
|
72
72
|
...zUpdate("userId"),
|
|
73
73
|
body: zPatchBody({
|
|
74
|
-
password: z
|
|
75
|
-
.string()
|
|
76
|
-
.refine(
|
|
77
|
-
(val) => {
|
|
78
|
-
try {
|
|
79
|
-
password(val);
|
|
80
|
-
return true;
|
|
81
|
-
} catch {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
{ message: "Invalid password format" },
|
|
86
|
-
)
|
|
87
|
-
.optional()
|
|
88
|
-
.openapi({ description: "New user password" }),
|
|
89
74
|
name: z.string().optional().openapi({ description: "User full name" }),
|
|
90
75
|
timezone: z.string().optional().openapi({ description: "IANA timezone" }),
|
|
91
76
|
avatar: z.string().optional().openapi({ description: "Avatar URL" }),
|
|
@@ -107,7 +92,11 @@ export const updateUserSchema = {
|
|
|
107
92
|
.enum(["user", "admin", "patient", "onlyself"])
|
|
108
93
|
.optional()
|
|
109
94
|
.openapi({ description: "User role" }),
|
|
110
|
-
inviteCode: z
|
|
95
|
+
inviteCode: z
|
|
96
|
+
.string()
|
|
97
|
+
.nullable()
|
|
98
|
+
.optional()
|
|
99
|
+
.openapi({ description: "Invite code" }),
|
|
111
100
|
organization: zObjectId
|
|
112
101
|
.optional()
|
|
113
102
|
.openapi({ description: "Organization ObjectId" }),
|
|
@@ -128,7 +117,11 @@ export const updateInviteSchema = {
|
|
|
128
117
|
body: z.object({
|
|
129
118
|
organization: zObjectId.openapi({ description: "Organization ObjectId" }),
|
|
130
119
|
status: z.enum(["accepted"]).openapi({ description: "Invite status" }),
|
|
131
|
-
inviteCode: z
|
|
120
|
+
inviteCode: z
|
|
121
|
+
.string()
|
|
122
|
+
.nullable()
|
|
123
|
+
.optional()
|
|
124
|
+
.openapi({ description: "Invite code" }),
|
|
132
125
|
}),
|
|
133
126
|
};
|
|
134
127
|
|
package/src/utils/userName.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { Patient } from "../types/patient"; // Assuming a `Patient` type ex
|
|
|
5
5
|
const generateUserName = async (patient: Patient): Promise<string | null> => {
|
|
6
6
|
if (patient.owner) {
|
|
7
7
|
const auth0UserById = await getUserById(patient.owner);
|
|
8
|
-
patient.auth0User = auth0UserById
|
|
8
|
+
patient.auth0User = auth0UserById;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
if (patient?.auth0User?.app_metadata?.first_name) {
|