@flowerforce/flowerbase 1.7.3-beta.3 → 1.7.3
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/CHANGELOG.md +9 -0
- package/dist/auth/controller.d.ts.map +1 -1
- package/dist/auth/controller.js +1 -1
- package/dist/auth/plugins/jwt.d.ts.map +1 -1
- package/dist/auth/plugins/jwt.js +8 -5
- package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
- package/dist/auth/providers/custom-function/controller.js +8 -4
- package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
- package/dist/auth/providers/local-userpass/controller.js +1 -1
- package/dist/monitoring/utils.d.ts.map +1 -1
- package/dist/monitoring/utils.js +3 -2
- package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
- package/dist/services/mongodb-atlas/index.js +11 -10
- package/package.json +1 -1
- package/src/auth/controller.ts +3 -0
- package/src/auth/plugins/jwt.test.ts +35 -2
- package/src/auth/plugins/jwt.ts +15 -9
- package/src/auth/providers/custom-function/controller.ts +14 -2
- package/src/auth/providers/local-userpass/controller.ts +6 -1
- package/src/monitoring/utils.ts +3 -2
- package/src/services/mongodb-atlas/__tests__/realmCompatibility.test.ts +18 -0
- package/src/services/mongodb-atlas/index.ts +13 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 1.7.3 (2026-02-17)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### 🩹 Fixes
|
|
5
|
+
|
|
6
|
+
- response EJSON in function ([fa70c11](https://github.com/flowerforce/flowerbase/commit/fa70c11))
|
|
7
|
+
|
|
8
|
+
- issues #5 #6 #7 #8 #10 #11 #12 #13 #14 ([#5](https://github.com/flowerforce/flowerbase/issues/5), [#6](https://github.com/flowerforce/flowerbase/issues/6), [#7](https://github.com/flowerforce/flowerbase/issues/7), [#8](https://github.com/flowerforce/flowerbase/issues/8), [#10](https://github.com/flowerforce/flowerbase/issues/10), [#11](https://github.com/flowerforce/flowerbase/issues/11), [#12](https://github.com/flowerforce/flowerbase/issues/12), [#13](https://github.com/flowerforce/flowerbase/issues/13), [#14](https://github.com/flowerforce/flowerbase/issues/14))
|
|
9
|
+
|
|
1
10
|
## 1.7.2 (2026-02-12)
|
|
2
11
|
|
|
3
12
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/auth/controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAQzC;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/auth/controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAQzC;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,eAAe,iBA2KxD"}
|
package/dist/auth/controller.js
CHANGED
|
@@ -111,7 +111,7 @@ function authController(app) {
|
|
|
111
111
|
: {};
|
|
112
112
|
res.status(201);
|
|
113
113
|
return {
|
|
114
|
-
access_token: this.createAccessToken(Object.assign(Object.assign({}, auth_user), { user_data: Object.assign(Object.assign({}, user), { id: req.user.sub }) }))
|
|
114
|
+
access_token: this.createAccessToken(Object.assign(Object.assign({}, auth_user), { user_data: Object.assign(Object.assign({}, user), { id: req.user.sub }), custom_data: Object.assign({}, user) }))
|
|
115
115
|
};
|
|
116
116
|
});
|
|
117
117
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/jwt.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/jwt.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAkBD;;;;;;;GAOG;iUAC8C,OAAO;AAAxD,wBA+GE"}
|
package/dist/auth/plugins/jwt.js
CHANGED
|
@@ -16,6 +16,7 @@ const jwt_1 = __importDefault(require("@fastify/jwt"));
|
|
|
16
16
|
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
|
|
17
17
|
const mongodb_1 = require("mongodb");
|
|
18
18
|
const constants_1 = require("../../constants");
|
|
19
|
+
const isRecord = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
19
20
|
const unauthorizedSessionError = {
|
|
20
21
|
message: 'Unauthorized',
|
|
21
22
|
error: 'unauthorized',
|
|
@@ -94,14 +95,16 @@ exports.default = (0, fastify_plugin_1.default)(function (fastify, opts) {
|
|
|
94
95
|
});
|
|
95
96
|
fastify.decorate('createAccessToken', function (user) {
|
|
96
97
|
const id = user._id.toString();
|
|
97
|
-
|
|
98
|
-
const
|
|
98
|
+
const userData = isRecord(user.user_data) ? Object.assign({}, user.user_data) : {};
|
|
99
|
+
const customData = isRecord(user.custom_data)
|
|
100
|
+
? Object.assign({}, user.custom_data) : Object.assign({}, userData);
|
|
101
|
+
const mergedUserData = Object.assign(Object.assign(Object.assign({}, customData), userData), { _id: id, id, email: typeof user.email === 'string' ? user.email : userData.email });
|
|
99
102
|
return this.jwt.sign({
|
|
100
103
|
typ: 'access',
|
|
101
104
|
id,
|
|
102
|
-
data:
|
|
103
|
-
user_data:
|
|
104
|
-
custom_data:
|
|
105
|
+
data: mergedUserData,
|
|
106
|
+
user_data: mergedUserData,
|
|
107
|
+
custom_data: customData
|
|
105
108
|
}, {
|
|
106
109
|
iss: BAAS_ID,
|
|
107
110
|
jti: BAAS_ID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AASzC;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AASzC;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,eAAe,iBAiHlE"}
|
|
@@ -26,7 +26,7 @@ function customFunctionController(app) {
|
|
|
26
26
|
const functionsList = state_1.StateManager.select('functions');
|
|
27
27
|
const services = state_1.StateManager.select('services');
|
|
28
28
|
const db = app.mongo.client.db(constants_1.DB_NAME);
|
|
29
|
-
const { authCollection, refreshTokensCollection } = constants_1.AUTH_CONFIG;
|
|
29
|
+
const { authCollection, refreshTokensCollection, userCollection, user_id_field } = constants_1.AUTH_CONFIG;
|
|
30
30
|
const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
|
|
31
31
|
/**
|
|
32
32
|
* Endpoint for user login.
|
|
@@ -80,11 +80,15 @@ function customFunctionController(app) {
|
|
|
80
80
|
reply.code(401).send({ message: 'Unauthorized' });
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
|
+
const user = user_id_field && userCollection
|
|
84
|
+
? yield db
|
|
85
|
+
.collection(userCollection)
|
|
86
|
+
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
87
|
+
: {};
|
|
83
88
|
const currentUserData = {
|
|
84
89
|
_id: authUser._id,
|
|
85
|
-
user_data: {
|
|
86
|
-
|
|
87
|
-
}
|
|
90
|
+
user_data: Object.assign(Object.assign({}, (user || {})), { id: authUser._id.toString(), email: authUser.email }),
|
|
91
|
+
custom_data: Object.assign({}, (user || {}))
|
|
88
92
|
};
|
|
89
93
|
const refreshToken = this.createRefreshToken(currentUserData);
|
|
90
94
|
const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAqCzC;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAqCzC;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,iBAoXjE"}
|
|
@@ -209,7 +209,7 @@ function localUserPassController(app) {
|
|
|
209
209
|
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
210
210
|
: {};
|
|
211
211
|
authUser === null || authUser === void 0 ? true : delete authUser.password;
|
|
212
|
-
const userWithCustomData = Object.assign(Object.assign({}, authUser), { user_data: Object.assign(Object.assign({}, (user || {})), {
|
|
212
|
+
const userWithCustomData = Object.assign(Object.assign({}, authUser), { user_data: Object.assign(Object.assign({}, (user || {})), { id: authUser._id.toString(), email: authUser.email }), custom_data: Object.assign({}, (user || {})), data: { email: authUser.email }, id: authUser._id.toString() });
|
|
213
213
|
if (authUser && authUser.status !== 'confirmed') {
|
|
214
214
|
throw new Error(utils_1.AUTH_ERRORS.USER_NOT_CONFIRMED);
|
|
215
215
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/monitoring/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAG9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AAIxD,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,EAAE,CAAA;IACf,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,OAAO,GAAG,WAAW,CAAA;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;IAClC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,KAAK,YAAY,EAAE,CAAA;IAC5C,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,eAAO,MAAM,MAAM,QAAsB,CAAA;AACzC,eAAO,MAAM,SAAS,KAAK,CAAA;AAC3B,eAAO,MAAM,SAAS,KAAK,CAAA;AAC3B,eAAO,MAAM,UAAU,MAAM,CAAA;AAC7B,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC,eAAO,MAAM,SAAS,eACuD,CAAA;AAE7E,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,OAAO,CAAC,OAAO,CAC2B,CAAA;AAElG,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACf,CAAA;AAE/D,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,WAc3C,CAAA;AAeD,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,WAWzC,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,4BAOlE,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAS3E,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAuCvG,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,EAAE,cAAS,KAAG,OAqCpD,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO;;;;;;CAc7C,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,SAAS,cAAc,CAAC,SAAS,CAAC,YAQ7D,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,KAAG,UAqCtE,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,uEAS1C,CAAA;AAED,eAAO,MAAM,aAAa,cAC8C,CAAA;AAExE,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS;;;;;;;;;;;;;;;;aA2B9C,CAAA;AAED,eAAO,MAAM,4BAA4B,GACvC,OAAO,KAAK,GAAG,SAAS,EACxB,YAAY,MAAM,EAClB,OAAO,OAAO,EACd,cAAc,OAAO,6DAItB,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,EAAE,QAAQ,MAAM,aAiBtE,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,UAAU,MAAM,EAAE,QAAQ,MAAM,WAYzD,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC7B,KAAK,eAAe,EACpB,SAAS,MAAM,EACf,cAAc,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/monitoring/utils.ts"],"names":[],"mappings":"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"}
|
package/dist/monitoring/utils.js
CHANGED
|
@@ -354,14 +354,15 @@ const resolveUserContext = (app, userId, userPayload) => __awaiter(void 0, void
|
|
|
354
354
|
: (customUser && typeof customUser[userIdField] !== 'undefined'
|
|
355
355
|
? String(customUser[userIdField])
|
|
356
356
|
: normalizedUserId);
|
|
357
|
-
const
|
|
357
|
+
const custom_data = customUser ? (0, exports.stripSensitiveFields)(customUser) : {};
|
|
358
|
+
const user_data = Object.assign(Object.assign({}, custom_data), { id, _id: id, email: authUser && typeof authUser.email === 'string'
|
|
358
359
|
? authUser.email
|
|
359
360
|
: undefined });
|
|
360
361
|
const user = {
|
|
361
362
|
id,
|
|
362
363
|
user_data,
|
|
363
364
|
data: user_data,
|
|
364
|
-
custom_data
|
|
365
|
+
custom_data
|
|
365
366
|
};
|
|
366
367
|
if (isObjectId) {
|
|
367
368
|
user._id = new mongodb_1.ObjectId(id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAuBA,OAAO,EAGL,oBAAoB,EAErB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAuBA,OAAO,EAGL,oBAAoB,EAErB,MAAM,SAAS,CAAA;AA6tChB,QAAA,MAAM,YAAY,EAAE,oBA6BlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
|
|
@@ -112,6 +112,7 @@ const normalizeFindOneAndUpdateOptions = (options) => {
|
|
|
112
112
|
}
|
|
113
113
|
return Object.assign(Object.assign({}, rest), { returnDocument: returnNewDocument ? 'after' : 'before' });
|
|
114
114
|
};
|
|
115
|
+
const buildAndQuery = (clauses) => clauses.length ? { $and: clauses } : {};
|
|
115
116
|
const hasAtomicOperators = (data) => Object.keys(data).some((key) => key.startsWith('$'));
|
|
116
117
|
const normalizeUpdatePayload = (data) => hasAtomicOperators(data) ? data : { $set: data };
|
|
117
118
|
const hasOperatorExpressions = (value) => isPlainObject(value) && Object.keys(value).some((key) => key.startsWith('$'));
|
|
@@ -356,7 +357,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
356
357
|
logService('findOne query', { collName, formattedQuery });
|
|
357
358
|
const safeQuery = (0, utils_3.normalizeQuery)(formattedQuery);
|
|
358
359
|
logService('findOne normalizedQuery', { collName, safeQuery });
|
|
359
|
-
const result = yield collection.findOne(
|
|
360
|
+
const result = yield collection.findOne(buildAndQuery(safeQuery), resolvedOptions);
|
|
360
361
|
logDebug('findOne result', {
|
|
361
362
|
collection: collName,
|
|
362
363
|
result
|
|
@@ -417,7 +418,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
417
418
|
// Apply access control filters
|
|
418
419
|
const formattedQuery = (0, utils_3.getFormattedQuery)(filters, query, user);
|
|
419
420
|
// Retrieve the document to check permissions before deleting
|
|
420
|
-
const result = yield collection.findOne(
|
|
421
|
+
const result = yield collection.findOne(buildAndQuery(formattedQuery));
|
|
421
422
|
const winningRole = (0, utils_2.getWinningRole)(result, user, roles);
|
|
422
423
|
logDebug('delete winningRole', {
|
|
423
424
|
collection: collName,
|
|
@@ -435,7 +436,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
435
436
|
if (!status) {
|
|
436
437
|
throw new Error('Delete not permitted');
|
|
437
438
|
}
|
|
438
|
-
const res = yield collection.deleteOne(
|
|
439
|
+
const res = yield collection.deleteOne(buildAndQuery(formattedQuery), options);
|
|
439
440
|
emitMongoEvent('deleteOne');
|
|
440
441
|
return res;
|
|
441
442
|
}
|
|
@@ -536,10 +537,10 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
536
537
|
const safeQuery = Array.isArray(formattedQuery)
|
|
537
538
|
? (0, utils_3.normalizeQuery)(formattedQuery)
|
|
538
539
|
: formattedQuery;
|
|
539
|
-
const result = yield collection.findOne(
|
|
540
|
+
const result = yield collection.findOne(buildAndQuery(safeQuery));
|
|
540
541
|
if (!result) {
|
|
541
542
|
if (options === null || options === void 0 ? void 0 : options.upsert) {
|
|
542
|
-
const upsertResult = yield collection.updateOne(
|
|
543
|
+
const upsertResult = yield collection.updateOne(buildAndQuery(safeQuery), normalizedData, options);
|
|
543
544
|
emitMongoEvent('updateOne');
|
|
544
545
|
return upsertResult;
|
|
545
546
|
}
|
|
@@ -563,7 +564,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
563
564
|
if (!status || !areDocumentsEqual) {
|
|
564
565
|
throw new Error('Update not permitted');
|
|
565
566
|
}
|
|
566
|
-
const res = yield collection.updateOne(
|
|
567
|
+
const res = yield collection.updateOne(buildAndQuery(safeQuery), normalizedData, options);
|
|
567
568
|
emitMongoEvent('updateOne');
|
|
568
569
|
return res;
|
|
569
570
|
}
|
|
@@ -596,7 +597,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
596
597
|
const safeQuery = Array.isArray(formattedQuery)
|
|
597
598
|
? (0, utils_3.normalizeQuery)(formattedQuery)
|
|
598
599
|
: formattedQuery;
|
|
599
|
-
const result = yield collection.findOne(
|
|
600
|
+
const result = yield collection.findOne(buildAndQuery(safeQuery));
|
|
600
601
|
if (!result) {
|
|
601
602
|
throw new Error('Update not permitted');
|
|
602
603
|
}
|
|
@@ -609,7 +610,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
609
610
|
: getUpdatedPaths(normalizedData);
|
|
610
611
|
const [docToCheck] = Array.isArray(normalizedData)
|
|
611
612
|
? yield collection.aggregate([
|
|
612
|
-
{ $match:
|
|
613
|
+
{ $match: buildAndQuery(safeQuery) },
|
|
613
614
|
{ $limit: 1 },
|
|
614
615
|
...normalizedData
|
|
615
616
|
]).toArray()
|
|
@@ -627,8 +628,8 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
|
|
|
627
628
|
throw new Error('Update not permitted');
|
|
628
629
|
}
|
|
629
630
|
const updateResult = normalizedOptions
|
|
630
|
-
? yield collection.findOneAndUpdate(
|
|
631
|
-
: yield collection.findOneAndUpdate(
|
|
631
|
+
? yield collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData, normalizedOptions)
|
|
632
|
+
: yield collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData);
|
|
632
633
|
if (!updateResult) {
|
|
633
634
|
emitMongoEvent('findOneAndUpdate');
|
|
634
635
|
return updateResult;
|
package/package.json
CHANGED
package/src/auth/controller.ts
CHANGED
|
@@ -13,9 +13,10 @@ jest.mock('node:diagnostics_channel', () => {
|
|
|
13
13
|
}
|
|
14
14
|
})
|
|
15
15
|
|
|
16
|
+
import { ObjectId } from 'bson'
|
|
16
17
|
import fastify, { FastifyInstance, FastifyReply } from 'fastify'
|
|
18
|
+
import * as jwt from 'jsonwebtoken'
|
|
17
19
|
import jwtAuthPlugin from './jwt'
|
|
18
|
-
import { ObjectId } from 'bson'
|
|
19
20
|
|
|
20
21
|
const SECRET = 'test-secret'
|
|
21
22
|
|
|
@@ -52,7 +53,7 @@ describe('jwtAuthentication', () => {
|
|
|
52
53
|
const collectionMock = { findOne: findOneMock }
|
|
53
54
|
const dbMock = { collection: jest.fn().mockReturnValue(collectionMock) }
|
|
54
55
|
const mongoMock = { client: { db: jest.fn().mockReturnValue(dbMock) } }
|
|
55
|
-
|
|
56
|
+
; (app as any).mongo = mongoMock
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
const createReply = () => {
|
|
@@ -111,4 +112,36 @@ describe('jwtAuthentication', () => {
|
|
|
111
112
|
expect(reply.code).toHaveBeenCalledWith(401)
|
|
112
113
|
expect(reply.send).toHaveBeenCalledWith(unauthorizedSessionError)
|
|
113
114
|
})
|
|
115
|
+
|
|
116
|
+
it('preserves linked custom_data _id in access token payload', async () => {
|
|
117
|
+
const authId = new ObjectId()
|
|
118
|
+
const linkedId = new ObjectId()
|
|
119
|
+
const token = (app as any).createAccessToken({
|
|
120
|
+
_id: authId,
|
|
121
|
+
email: 'owner@example.com',
|
|
122
|
+
user_data: {
|
|
123
|
+
_id: linkedId.toHexString(),
|
|
124
|
+
role: 'owner'
|
|
125
|
+
},
|
|
126
|
+
custom_data: {
|
|
127
|
+
_id: linkedId.toHexString(),
|
|
128
|
+
role: 'owner'
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const decoded = jwt.decode(token) as {
|
|
133
|
+
id: string
|
|
134
|
+
data: { _id: string; id: string }
|
|
135
|
+
user_data: { _id: string; id: string }
|
|
136
|
+
custom_data: { _id: string; role: string }
|
|
137
|
+
sub: string
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
expect(decoded.id).toBe(authId.toHexString())
|
|
141
|
+
expect(decoded.sub).toBe(authId.toHexString())
|
|
142
|
+
expect(decoded.data._id).toBe(authId.toHexString())
|
|
143
|
+
expect(decoded.user_data._id).toBe(authId.toHexString())
|
|
144
|
+
expect(decoded.custom_data._id).toBe(linkedId.toHexString())
|
|
145
|
+
expect(decoded.custom_data.role).toBe('owner')
|
|
146
|
+
})
|
|
114
147
|
})
|
package/src/auth/plugins/jwt.ts
CHANGED
|
@@ -13,6 +13,9 @@ type JwtAccessWithTimestamp = {
|
|
|
13
13
|
iat?: number
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
17
|
+
!!value && typeof value === 'object' && !Array.isArray(value)
|
|
18
|
+
|
|
16
19
|
const unauthorizedSessionError = {
|
|
17
20
|
message: 'Unauthorized',
|
|
18
21
|
error: 'unauthorized',
|
|
@@ -98,22 +101,25 @@ export default fp(async function (fastify, opts: Options) {
|
|
|
98
101
|
|
|
99
102
|
fastify.decorate('createAccessToken', function (user: WithId<Document>) {
|
|
100
103
|
const id = user._id.toString()
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
...
|
|
104
|
+
const userData = isRecord(user.user_data) ? { ...user.user_data } : {}
|
|
105
|
+
const customData = isRecord(user.custom_data)
|
|
106
|
+
? { ...user.custom_data }
|
|
107
|
+
: { ...userData }
|
|
108
|
+
const mergedUserData = {
|
|
109
|
+
...customData,
|
|
110
|
+
...userData,
|
|
105
111
|
_id: id,
|
|
106
|
-
id
|
|
107
|
-
email: user.email
|
|
112
|
+
id,
|
|
113
|
+
email: typeof user.email === 'string' ? user.email : userData.email
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
return this.jwt.sign(
|
|
111
117
|
{
|
|
112
118
|
typ: 'access',
|
|
113
119
|
id,
|
|
114
|
-
data:
|
|
115
|
-
user_data:
|
|
116
|
-
custom_data:
|
|
120
|
+
data: mergedUserData,
|
|
121
|
+
user_data: mergedUserData,
|
|
122
|
+
custom_data: customData
|
|
117
123
|
},
|
|
118
124
|
{
|
|
119
125
|
iss: BAAS_ID,
|
|
@@ -17,7 +17,7 @@ export async function customFunctionController(app: FastifyInstance) {
|
|
|
17
17
|
const functionsList = StateManager.select('functions')
|
|
18
18
|
const services = StateManager.select('services')
|
|
19
19
|
const db = app.mongo.client.db(DB_NAME)
|
|
20
|
-
const { authCollection, refreshTokensCollection } = AUTH_CONFIG
|
|
20
|
+
const { authCollection, refreshTokensCollection, userCollection, user_id_field } = AUTH_CONFIG
|
|
21
21
|
const refreshTokenTtlMs = DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -89,10 +89,22 @@ export async function customFunctionController(app: FastifyInstance) {
|
|
|
89
89
|
return
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
const user =
|
|
93
|
+
user_id_field && userCollection
|
|
94
|
+
? await db
|
|
95
|
+
.collection(userCollection)
|
|
96
|
+
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
97
|
+
: {}
|
|
98
|
+
|
|
92
99
|
const currentUserData = {
|
|
93
100
|
_id: authUser._id,
|
|
94
101
|
user_data: {
|
|
95
|
-
|
|
102
|
+
...(user || {}),
|
|
103
|
+
id: authUser._id.toString(),
|
|
104
|
+
email: authUser.email
|
|
105
|
+
},
|
|
106
|
+
custom_data: {
|
|
107
|
+
...(user || {})
|
|
96
108
|
}
|
|
97
109
|
}
|
|
98
110
|
const refreshToken = this.createRefreshToken(currentUserData)
|
|
@@ -268,7 +268,12 @@ export async function localUserPassController(app: FastifyInstance) {
|
|
|
268
268
|
|
|
269
269
|
const userWithCustomData = {
|
|
270
270
|
...authUser,
|
|
271
|
-
user_data: {
|
|
271
|
+
user_data: {
|
|
272
|
+
...(user || {}),
|
|
273
|
+
id: authUser._id.toString(),
|
|
274
|
+
email: authUser.email
|
|
275
|
+
},
|
|
276
|
+
custom_data: { ...(user || {}) },
|
|
272
277
|
data: { email: authUser.email },
|
|
273
278
|
id: authUser._id.toString()
|
|
274
279
|
}
|
package/src/monitoring/utils.ts
CHANGED
|
@@ -404,8 +404,9 @@ export const resolveUserContext = async (
|
|
|
404
404
|
? String(customUser[userIdField])
|
|
405
405
|
: normalizedUserId)
|
|
406
406
|
|
|
407
|
+
const custom_data = customUser ? stripSensitiveFields(customUser) : {}
|
|
407
408
|
const user_data = {
|
|
408
|
-
...
|
|
409
|
+
...custom_data,
|
|
409
410
|
id,
|
|
410
411
|
_id: id,
|
|
411
412
|
email: authUser && typeof (authUser as { email?: unknown }).email === 'string'
|
|
@@ -417,7 +418,7 @@ export const resolveUserContext = async (
|
|
|
417
418
|
id,
|
|
418
419
|
user_data,
|
|
419
420
|
data: user_data,
|
|
420
|
-
custom_data
|
|
421
|
+
custom_data
|
|
421
422
|
}
|
|
422
423
|
|
|
423
424
|
if (isObjectId) {
|
|
@@ -250,6 +250,24 @@ describe('mongodb-atlas Realm compatibility', () => {
|
|
|
250
250
|
expect(find).toHaveBeenCalledWith({ active: true }, { session })
|
|
251
251
|
})
|
|
252
252
|
|
|
253
|
+
it('allows findOne({}) without emitting an empty $and query', async () => {
|
|
254
|
+
const doc = { _id: new ObjectId(), label: 'first' }
|
|
255
|
+
const findOne = jest.fn().mockResolvedValue(doc)
|
|
256
|
+
const collection = {
|
|
257
|
+
collectionName: 'todos',
|
|
258
|
+
findOne
|
|
259
|
+
}
|
|
260
|
+
const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
|
|
261
|
+
rules: createRules(),
|
|
262
|
+
user: { id: 'user-1' }
|
|
263
|
+
}).db('db').collection('todos')
|
|
264
|
+
|
|
265
|
+
const result = await operators.findOne({})
|
|
266
|
+
|
|
267
|
+
expect(result).toEqual(doc)
|
|
268
|
+
expect(findOne).toHaveBeenCalledWith({}, undefined)
|
|
269
|
+
})
|
|
270
|
+
|
|
253
271
|
it('returns insertMany insertedIds as an array', async () => {
|
|
254
272
|
const id0 = new ObjectId()
|
|
255
273
|
const id1 = new ObjectId()
|
|
@@ -136,6 +136,9 @@ const normalizeFindOneAndUpdateOptions = (
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
const buildAndQuery = (clauses: MongoFilter<Document>[]): MongoFilter<Document> =>
|
|
140
|
+
clauses.length ? { $and: clauses } : {}
|
|
141
|
+
|
|
139
142
|
const hasAtomicOperators = (data: Document) => Object.keys(data).some((key) => key.startsWith('$'))
|
|
140
143
|
|
|
141
144
|
const normalizeUpdatePayload = (data: Document) =>
|
|
@@ -410,7 +413,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
410
413
|
logService('findOne query', { collName, formattedQuery })
|
|
411
414
|
const safeQuery = normalizeQuery(formattedQuery)
|
|
412
415
|
logService('findOne normalizedQuery', { collName, safeQuery })
|
|
413
|
-
const result = await collection.findOne(
|
|
416
|
+
const result = await collection.findOne(buildAndQuery(safeQuery), resolvedOptions)
|
|
414
417
|
logDebug('findOne result', {
|
|
415
418
|
collection: collName,
|
|
416
419
|
result
|
|
@@ -477,7 +480,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
477
480
|
const formattedQuery = getFormattedQuery(filters, query, user)
|
|
478
481
|
|
|
479
482
|
// Retrieve the document to check permissions before deleting
|
|
480
|
-
const result = await collection.findOne(
|
|
483
|
+
const result = await collection.findOne(buildAndQuery(formattedQuery))
|
|
481
484
|
const winningRole = getWinningRole(result, user, roles)
|
|
482
485
|
|
|
483
486
|
logDebug('delete winningRole', {
|
|
@@ -502,7 +505,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
502
505
|
throw new Error('Delete not permitted')
|
|
503
506
|
}
|
|
504
507
|
|
|
505
|
-
const res = await collection.deleteOne(
|
|
508
|
+
const res = await collection.deleteOne(buildAndQuery(formattedQuery), options)
|
|
506
509
|
emitMongoEvent('deleteOne')
|
|
507
510
|
return res
|
|
508
511
|
}
|
|
@@ -610,12 +613,12 @@ const getOperators: GetOperatorsFunction = (
|
|
|
610
613
|
? normalizeQuery(formattedQuery)
|
|
611
614
|
: formattedQuery
|
|
612
615
|
|
|
613
|
-
const result = await collection.findOne(
|
|
616
|
+
const result = await collection.findOne(buildAndQuery(safeQuery))
|
|
614
617
|
|
|
615
618
|
if (!result) {
|
|
616
619
|
if (options?.upsert) {
|
|
617
620
|
const upsertResult = await collection.updateOne(
|
|
618
|
-
|
|
621
|
+
buildAndQuery(safeQuery),
|
|
619
622
|
normalizedData,
|
|
620
623
|
options
|
|
621
624
|
)
|
|
@@ -649,7 +652,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
649
652
|
if (!status || !areDocumentsEqual) {
|
|
650
653
|
throw new Error('Update not permitted')
|
|
651
654
|
}
|
|
652
|
-
const res = await collection.updateOne(
|
|
655
|
+
const res = await collection.updateOne(buildAndQuery(safeQuery), normalizedData, options)
|
|
653
656
|
emitMongoEvent('updateOne')
|
|
654
657
|
return res
|
|
655
658
|
}
|
|
@@ -685,7 +688,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
685
688
|
? normalizeQuery(formattedQuery)
|
|
686
689
|
: formattedQuery
|
|
687
690
|
|
|
688
|
-
const result = await collection.findOne(
|
|
691
|
+
const result = await collection.findOne(buildAndQuery(safeQuery))
|
|
689
692
|
|
|
690
693
|
if (!result) {
|
|
691
694
|
throw new Error('Update not permitted')
|
|
@@ -700,7 +703,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
700
703
|
: getUpdatedPaths(normalizedData as Document)
|
|
701
704
|
const [docToCheck] = Array.isArray(normalizedData)
|
|
702
705
|
? await collection.aggregate([
|
|
703
|
-
{ $match:
|
|
706
|
+
{ $match: buildAndQuery(safeQuery) },
|
|
704
707
|
{ $limit: 1 },
|
|
705
708
|
...normalizedData
|
|
706
709
|
]).toArray()
|
|
@@ -725,8 +728,8 @@ const getOperators: GetOperatorsFunction = (
|
|
|
725
728
|
}
|
|
726
729
|
|
|
727
730
|
const updateResult = normalizedOptions
|
|
728
|
-
? await collection.findOneAndUpdate(
|
|
729
|
-
: await collection.findOneAndUpdate(
|
|
731
|
+
? await collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData, normalizedOptions)
|
|
732
|
+
: await collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData)
|
|
730
733
|
if (!updateResult) {
|
|
731
734
|
emitMongoEvent('findOneAndUpdate')
|
|
732
735
|
return updateResult
|