@flowerforce/flowerbase 1.7.3-beta.2 → 1.7.3-beta.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.
@@ -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,iBAwKxD"}
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"}
@@ -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;AAeD;;;;;;;GAOG;iUAC8C,OAAO;AAAxD,wBA4GE"}
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"}
@@ -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
- // const userDataId = user.user_data._id.toString()
98
- const user_data = Object.assign(Object.assign({}, user.user_data), { _id: id, id: id, email: user.email });
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: user_data,
103
- user_data: user_data,
104
- custom_data: user_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,iBAqGlE"}
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
- _id: authUser._id
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,iBA+WjE"}
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 || {})), { _id: authUser._id }), data: { email: authUser.email }, id: authUser._id.toString() });
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":"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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/monitoring/utils.ts"],"names":[],"mappings":"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"}
@@ -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 user_data = Object.assign(Object.assign({}, (customUser ? (0, exports.stripSensitiveFields)(customUser) : {})), { id, _id: id, email: authUser && typeof authUser.email === 'string'
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: user_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,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAysCrF,QAAA,MAAM,YAAY,EAAE,oBA6BlB,CAAA;AAEF,eAAe,YAAY,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"}
@@ -8,15 +8,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
11
22
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
23
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
24
  };
14
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
+ const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
15
27
  const get_1 = __importDefault(require("lodash/get"));
16
28
  const isEqual_1 = __importDefault(require("lodash/isEqual"));
17
29
  const set_1 = __importDefault(require("lodash/set"));
18
30
  const unset_1 = __importDefault(require("lodash/unset"));
19
- const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
20
31
  const utils_1 = require("../../monitoring/utils");
21
32
  const machines_1 = require("../../utils/roles/machines");
22
33
  const utils_2 = require("../../utils/roles/machines/utils");
@@ -92,6 +103,16 @@ const normalizeInsertManyResult = (result) => {
92
103
  return result;
93
104
  return Object.assign(Object.assign({}, result), { insertedIds: Object.values(result.insertedIds) });
94
105
  };
106
+ const normalizeFindOneAndUpdateOptions = (options) => {
107
+ if (!options)
108
+ return undefined;
109
+ const { returnNewDocument } = options, rest = __rest(options, ["returnNewDocument"]);
110
+ if (typeof returnNewDocument !== 'boolean' || typeof rest.returnDocument !== 'undefined') {
111
+ return rest;
112
+ }
113
+ return Object.assign(Object.assign({}, rest), { returnDocument: returnNewDocument ? 'after' : 'before' });
114
+ };
115
+ const buildAndQuery = (clauses) => clauses.length ? { $and: clauses } : {};
95
116
  const hasAtomicOperators = (data) => Object.keys(data).some((key) => key.startsWith('$'));
96
117
  const normalizeUpdatePayload = (data) => hasAtomicOperators(data) ? data : { $set: data };
97
118
  const hasOperatorExpressions = (value) => isPlainObject(value) && Object.keys(value).some((key) => key.startsWith('$'));
@@ -336,7 +357,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
336
357
  logService('findOne query', { collName, formattedQuery });
337
358
  const safeQuery = (0, utils_3.normalizeQuery)(formattedQuery);
338
359
  logService('findOne normalizedQuery', { collName, safeQuery });
339
- const result = yield collection.findOne({ $and: safeQuery }, resolvedOptions);
360
+ const result = yield collection.findOne(buildAndQuery(safeQuery), resolvedOptions);
340
361
  logDebug('findOne result', {
341
362
  collection: collName,
342
363
  result
@@ -397,7 +418,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
397
418
  // Apply access control filters
398
419
  const formattedQuery = (0, utils_3.getFormattedQuery)(filters, query, user);
399
420
  // Retrieve the document to check permissions before deleting
400
- const result = yield collection.findOne({ $and: formattedQuery });
421
+ const result = yield collection.findOne(buildAndQuery(formattedQuery));
401
422
  const winningRole = (0, utils_2.getWinningRole)(result, user, roles);
402
423
  logDebug('delete winningRole', {
403
424
  collection: collName,
@@ -415,7 +436,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
415
436
  if (!status) {
416
437
  throw new Error('Delete not permitted');
417
438
  }
418
- const res = yield collection.deleteOne({ $and: formattedQuery }, options);
439
+ const res = yield collection.deleteOne(buildAndQuery(formattedQuery), options);
419
440
  emitMongoEvent('deleteOne');
420
441
  return res;
421
442
  }
@@ -516,10 +537,10 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
516
537
  const safeQuery = Array.isArray(formattedQuery)
517
538
  ? (0, utils_3.normalizeQuery)(formattedQuery)
518
539
  : formattedQuery;
519
- const result = yield collection.findOne({ $and: safeQuery });
540
+ const result = yield collection.findOne(buildAndQuery(safeQuery));
520
541
  if (!result) {
521
542
  if (options === null || options === void 0 ? void 0 : options.upsert) {
522
- const upsertResult = yield collection.updateOne({ $and: safeQuery }, normalizedData, options);
543
+ const upsertResult = yield collection.updateOne(buildAndQuery(safeQuery), normalizedData, options);
523
544
  emitMongoEvent('updateOne');
524
545
  return upsertResult;
525
546
  }
@@ -543,7 +564,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
543
564
  if (!status || !areDocumentsEqual) {
544
565
  throw new Error('Update not permitted');
545
566
  }
546
- const res = yield collection.updateOne({ $and: safeQuery }, normalizedData, options);
567
+ const res = yield collection.updateOne(buildAndQuery(safeQuery), normalizedData, options);
547
568
  emitMongoEvent('updateOne');
548
569
  return res;
549
570
  }
@@ -569,13 +590,14 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
569
590
  findOneAndUpdate: (query, data, options) => __awaiter(void 0, void 0, void 0, function* () {
570
591
  var _a;
571
592
  try {
593
+ const normalizedOptions = normalizeFindOneAndUpdateOptions(options);
572
594
  if (!run_as_system) {
573
595
  (0, utils_3.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.UPDATE);
574
596
  const formattedQuery = (0, utils_3.getFormattedQuery)(filters, query, user);
575
597
  const safeQuery = Array.isArray(formattedQuery)
576
598
  ? (0, utils_3.normalizeQuery)(formattedQuery)
577
599
  : formattedQuery;
578
- const result = yield collection.findOne({ $and: safeQuery });
600
+ const result = yield collection.findOne(buildAndQuery(safeQuery));
579
601
  if (!result) {
580
602
  throw new Error('Update not permitted');
581
603
  }
@@ -588,7 +610,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
588
610
  : getUpdatedPaths(normalizedData);
589
611
  const [docToCheck] = Array.isArray(normalizedData)
590
612
  ? yield collection.aggregate([
591
- { $match: { $and: safeQuery } },
613
+ { $match: buildAndQuery(safeQuery) },
592
614
  { $limit: 1 },
593
615
  ...normalizedData
594
616
  ]).toArray()
@@ -605,9 +627,9 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
605
627
  if (!status || !areDocumentsEqual) {
606
628
  throw new Error('Update not permitted');
607
629
  }
608
- const updateResult = options
609
- ? yield collection.findOneAndUpdate({ $and: safeQuery }, normalizedData, options)
610
- : yield collection.findOneAndUpdate({ $and: safeQuery }, normalizedData);
630
+ const updateResult = normalizedOptions
631
+ ? yield collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData, normalizedOptions)
632
+ : yield collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData);
611
633
  if (!updateResult) {
612
634
  emitMongoEvent('findOneAndUpdate');
613
635
  return updateResult;
@@ -625,8 +647,8 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
625
647
  emitMongoEvent('findOneAndUpdate');
626
648
  return sanitizedDoc;
627
649
  }
628
- const updateResult = options
629
- ? yield collection.findOneAndUpdate(query, data, options)
650
+ const updateResult = normalizedOptions
651
+ ? yield collection.findOneAndUpdate(query, data, normalizedOptions)
630
652
  : yield collection.findOneAndUpdate(query, data);
631
653
  emitMongoEvent('findOneAndUpdate');
632
654
  return updateResult;
@@ -29,11 +29,11 @@ export type GetOperatorsFunction = (collection: Collection<Document>, { rules, c
29
29
  collName: string;
30
30
  monitoringOrigin?: string;
31
31
  }) => {
32
+ findOneAndUpdate: (filter: MongoFilter<Document>, update: UpdateFilter<Document> | Document[], options?: RealmCompatibleFindOneAndUpdateOptions) => Promise<Document | null>;
32
33
  findOne: (filter?: MongoFilter<Document>, projection?: Document, options?: FindOneOptions) => ReturnType<Method<'findOne'>>;
33
34
  deleteOne: (...params: Parameters<Method<'deleteOne'>>) => ReturnType<Method<'deleteOne'>>;
34
35
  insertOne: (...params: Parameters<Method<'insertOne'>>) => ReturnType<Method<'insertOne'>>;
35
36
  updateOne: (...params: Parameters<Method<'updateOne'>>) => ReturnType<Method<'updateOne'>>;
36
- findOneAndUpdate: (filter: MongoFilter<Document>, update: UpdateFilter<Document> | Document[], options?: FindOneAndUpdateOptions) => Promise<Document | null>;
37
37
  find: (filter?: MongoFilter<Document>, projection?: Document, options?: FindOptions) => FindCursor;
38
38
  count: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
39
39
  countDocuments: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
@@ -43,6 +43,9 @@ export type GetOperatorsFunction = (collection: Collection<Document>, { rules, c
43
43
  updateMany: (...params: Parameters<Method<'updateMany'>>) => ReturnType<Method<'updateMany'>>;
44
44
  deleteMany: (...params: Parameters<Method<'deleteMany'>>) => ReturnType<Method<'deleteMany'>>;
45
45
  };
46
+ export type RealmCompatibleFindOneAndUpdateOptions = FindOneAndUpdateOptions & {
47
+ returnNewDocument?: boolean;
48
+ };
46
49
  export declare enum CRUD_OPERATIONS {
47
50
  CREATE = "CREATE",
48
51
  READ = "READ",
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/model.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.7.3-beta.2",
3
+ "version": "1.7.3-beta.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -124,6 +124,9 @@ export async function authController(app: FastifyInstance) {
124
124
  user_data: {
125
125
  ...user,
126
126
  id: req.user.sub
127
+ },
128
+ custom_data: {
129
+ ...user
127
130
  }
128
131
  })
129
132
  }
@@ -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
- ;(app as any).mongo = mongoMock
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
  })
@@ -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
- // const userDataId = user.user_data._id.toString()
102
-
103
- const user_data = {
104
- ...user.user_data,
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: 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: user_data,
115
- user_data: user_data,
116
- custom_data: user_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
- _id: authUser._id
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: { ...(user || {}), _id: authUser._id },
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
  }
@@ -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
- ...(customUser ? stripSensitiveFields(customUser) : {}),
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: user_data
421
+ custom_data
421
422
  }
422
423
 
423
424
  if (isObjectId) {
@@ -91,4 +91,38 @@ describe('mongodb-atlas findOneAndUpdate', () => {
91
91
  ).rejects.toThrow('Update not permitted')
92
92
  expect(findOneAndUpdate).not.toHaveBeenCalled()
93
93
  })
94
+
95
+ it('maps returnNewDocument=true to returnDocument=after', async () => {
96
+ const id = new ObjectId()
97
+ const existingDoc = { _id: id, value: 100, userId: 'user-1' }
98
+ const updatedDoc = { _id: id, value: 101, userId: 'user-1' }
99
+ const findOne = jest.fn().mockResolvedValue(existingDoc)
100
+ const findOneAndUpdate = jest.fn().mockResolvedValue(updatedDoc)
101
+ const collection = {
102
+ collectionName: 'todos',
103
+ findOne,
104
+ findOneAndUpdate
105
+ }
106
+
107
+ const app = createAppWithCollection(collection)
108
+ const operators = MongoDbAtlas(app as any, {
109
+ rules: createRules(),
110
+ user: { id: 'user-1' }
111
+ })
112
+ .db('db')
113
+ .collection('todos')
114
+
115
+ const result = await operators.findOneAndUpdate(
116
+ { _id: id },
117
+ { $inc: { value: 1 } },
118
+ { returnNewDocument: true } as any
119
+ )
120
+
121
+ expect(result).toEqual(updatedDoc)
122
+ expect(findOneAndUpdate).toHaveBeenCalledWith(
123
+ { $and: [{ _id: id }] },
124
+ { $inc: { value: 1 } },
125
+ { returnDocument: 'after' }
126
+ )
127
+ })
94
128
  })
@@ -153,6 +153,31 @@ describe('mongodb-atlas Realm compatibility', () => {
153
153
  expect(aggregate).not.toHaveBeenCalled()
154
154
  })
155
155
 
156
+ it('supports Realm returnNewDocument option in findOneAndUpdate', async () => {
157
+ const id = new ObjectId()
158
+ const findOneAndUpdate = jest.fn().mockResolvedValue({ _id: id, value: 101 })
159
+ const collection = {
160
+ collectionName: 'todos',
161
+ findOneAndUpdate
162
+ }
163
+ const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
164
+ run_as_system: true
165
+ }).db('db').collection('todos')
166
+
167
+ const result = await operators.findOneAndUpdate(
168
+ { _id: id },
169
+ { $inc: { value: 1 } } as any,
170
+ { returnNewDocument: true } as any
171
+ )
172
+
173
+ expect(result).toEqual({ _id: id, value: 101 })
174
+ expect(findOneAndUpdate).toHaveBeenCalledWith(
175
+ { _id: id },
176
+ { $inc: { value: 1 } },
177
+ { returnDocument: 'after' }
178
+ )
179
+ })
180
+
156
181
  it('supports operator updates in updateMany without using invalid aggregate stages', async () => {
157
182
  const id = new ObjectId()
158
183
  const find = jest.fn().mockReturnValue({
@@ -225,6 +250,24 @@ describe('mongodb-atlas Realm compatibility', () => {
225
250
  expect(find).toHaveBeenCalledWith({ active: true }, { session })
226
251
  })
227
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
+
228
271
  it('returns insertMany insertedIds as an array', async () => {
229
272
  const id0 = new ObjectId()
230
273
  const id1 = new ObjectId()
@@ -1,17 +1,17 @@
1
+ import cloneDeep from 'lodash/cloneDeep'
1
2
  import get from 'lodash/get'
2
3
  import isEqual from 'lodash/isEqual'
3
4
  import set from 'lodash/set'
4
5
  import unset from 'lodash/unset'
5
- import cloneDeep from 'lodash/cloneDeep'
6
6
  import {
7
7
  ClientSession,
8
8
  ClientSessionOptions,
9
9
  Collection,
10
10
  Document,
11
11
  EventsDescription,
12
+ FindOneAndUpdateOptions,
12
13
  FindOneOptions,
13
14
  FindOptions,
14
- FindOneAndUpdateOptions,
15
15
  Filter as MongoFilter,
16
16
  UpdateFilter,
17
17
  WithId
@@ -21,7 +21,12 @@ import { buildRulesMeta } from '../../monitoring/utils'
21
21
  import { checkValidation } from '../../utils/roles/machines'
22
22
  import { getWinningRole } from '../../utils/roles/machines/utils'
23
23
  import { emitServiceEvent } from '../monitoring'
24
- import { CRUD_OPERATIONS, GetOperatorsFunction, MongodbAtlasFunction } from './model'
24
+ import {
25
+ CRUD_OPERATIONS,
26
+ GetOperatorsFunction,
27
+ MongodbAtlasFunction,
28
+ RealmCompatibleFindOneAndUpdateOptions
29
+ } from './model'
25
30
  import {
26
31
  applyAccessControlToPipeline,
27
32
  checkDenyOperation,
@@ -115,6 +120,25 @@ const normalizeInsertManyResult = <T extends { insertedIds?: Record<string, unkn
115
120
  }
116
121
  }
117
122
 
123
+ const normalizeFindOneAndUpdateOptions = (
124
+ options?: RealmCompatibleFindOneAndUpdateOptions
125
+ ): FindOneAndUpdateOptions | undefined => {
126
+ if (!options) return undefined
127
+
128
+ const { returnNewDocument, ...rest } = options
129
+ if (typeof returnNewDocument !== 'boolean' || typeof rest.returnDocument !== 'undefined') {
130
+ return rest
131
+ }
132
+
133
+ return {
134
+ ...rest,
135
+ returnDocument: returnNewDocument ? 'after' : 'before'
136
+ }
137
+ }
138
+
139
+ const buildAndQuery = (clauses: MongoFilter<Document>[]): MongoFilter<Document> =>
140
+ clauses.length ? { $and: clauses } : {}
141
+
118
142
  const hasAtomicOperators = (data: Document) => Object.keys(data).some((key) => key.startsWith('$'))
119
143
 
120
144
  const normalizeUpdatePayload = (data: Document) =>
@@ -389,7 +413,7 @@ const getOperators: GetOperatorsFunction = (
389
413
  logService('findOne query', { collName, formattedQuery })
390
414
  const safeQuery = normalizeQuery(formattedQuery)
391
415
  logService('findOne normalizedQuery', { collName, safeQuery })
392
- const result = await collection.findOne({ $and: safeQuery }, resolvedOptions)
416
+ const result = await collection.findOne(buildAndQuery(safeQuery), resolvedOptions)
393
417
  logDebug('findOne result', {
394
418
  collection: collName,
395
419
  result
@@ -456,7 +480,7 @@ const getOperators: GetOperatorsFunction = (
456
480
  const formattedQuery = getFormattedQuery(filters, query, user)
457
481
 
458
482
  // Retrieve the document to check permissions before deleting
459
- const result = await collection.findOne({ $and: formattedQuery })
483
+ const result = await collection.findOne(buildAndQuery(formattedQuery))
460
484
  const winningRole = getWinningRole(result, user, roles)
461
485
 
462
486
  logDebug('delete winningRole', {
@@ -481,7 +505,7 @@ const getOperators: GetOperatorsFunction = (
481
505
  throw new Error('Delete not permitted')
482
506
  }
483
507
 
484
- const res = await collection.deleteOne({ $and: formattedQuery }, options)
508
+ const res = await collection.deleteOne(buildAndQuery(formattedQuery), options)
485
509
  emitMongoEvent('deleteOne')
486
510
  return res
487
511
  }
@@ -589,12 +613,12 @@ const getOperators: GetOperatorsFunction = (
589
613
  ? normalizeQuery(formattedQuery)
590
614
  : formattedQuery
591
615
 
592
- const result = await collection.findOne({ $and: safeQuery })
616
+ const result = await collection.findOne(buildAndQuery(safeQuery))
593
617
 
594
618
  if (!result) {
595
619
  if (options?.upsert) {
596
620
  const upsertResult = await collection.updateOne(
597
- { $and: safeQuery },
621
+ buildAndQuery(safeQuery),
598
622
  normalizedData,
599
623
  options
600
624
  )
@@ -628,7 +652,7 @@ const getOperators: GetOperatorsFunction = (
628
652
  if (!status || !areDocumentsEqual) {
629
653
  throw new Error('Update not permitted')
630
654
  }
631
- const res = await collection.updateOne({ $and: safeQuery }, normalizedData, options)
655
+ const res = await collection.updateOne(buildAndQuery(safeQuery), normalizedData, options)
632
656
  emitMongoEvent('updateOne')
633
657
  return res
634
658
  }
@@ -653,9 +677,10 @@ const getOperators: GetOperatorsFunction = (
653
677
  findOneAndUpdate: async (
654
678
  query: MongoFilter<Document>,
655
679
  data: UpdateFilter<Document> | Document[],
656
- options?: FindOneAndUpdateOptions
680
+ options?: RealmCompatibleFindOneAndUpdateOptions
657
681
  ) => {
658
682
  try {
683
+ const normalizedOptions = normalizeFindOneAndUpdateOptions(options)
659
684
  if (!run_as_system) {
660
685
  checkDenyOperation(normalizedRules, collection.collectionName, CRUD_OPERATIONS.UPDATE)
661
686
  const formattedQuery = getFormattedQuery(filters, query, user)
@@ -663,7 +688,7 @@ const getOperators: GetOperatorsFunction = (
663
688
  ? normalizeQuery(formattedQuery)
664
689
  : formattedQuery
665
690
 
666
- const result = await collection.findOne({ $and: safeQuery })
691
+ const result = await collection.findOne(buildAndQuery(safeQuery))
667
692
 
668
693
  if (!result) {
669
694
  throw new Error('Update not permitted')
@@ -678,7 +703,7 @@ const getOperators: GetOperatorsFunction = (
678
703
  : getUpdatedPaths(normalizedData as Document)
679
704
  const [docToCheck] = Array.isArray(normalizedData)
680
705
  ? await collection.aggregate([
681
- { $match: { $and: safeQuery } },
706
+ { $match: buildAndQuery(safeQuery) },
682
707
  { $limit: 1 },
683
708
  ...normalizedData
684
709
  ]).toArray()
@@ -702,9 +727,9 @@ const getOperators: GetOperatorsFunction = (
702
727
  throw new Error('Update not permitted')
703
728
  }
704
729
 
705
- const updateResult = options
706
- ? await collection.findOneAndUpdate({ $and: safeQuery }, normalizedData, options)
707
- : await collection.findOneAndUpdate({ $and: safeQuery }, normalizedData)
730
+ const updateResult = normalizedOptions
731
+ ? await collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData, normalizedOptions)
732
+ : await collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData)
708
733
  if (!updateResult) {
709
734
  emitMongoEvent('findOneAndUpdate')
710
735
  return updateResult
@@ -729,8 +754,8 @@ const getOperators: GetOperatorsFunction = (
729
754
  return sanitizedDoc
730
755
  }
731
756
 
732
- const updateResult = options
733
- ? await collection.findOneAndUpdate(query, data, options)
757
+ const updateResult = normalizedOptions
758
+ ? await collection.findOneAndUpdate(query, data, normalizedOptions)
734
759
  : await collection.findOneAndUpdate(query, data)
735
760
  emitMongoEvent('findOneAndUpdate')
736
761
  return updateResult
@@ -59,6 +59,11 @@ export type GetOperatorsFunction = (
59
59
  monitoringOrigin?: string
60
60
  }
61
61
  ) => {
62
+ findOneAndUpdate: (
63
+ filter: MongoFilter<Document>,
64
+ update: UpdateFilter<Document> | Document[],
65
+ options?: RealmCompatibleFindOneAndUpdateOptions
66
+ ) => Promise<Document | null>
62
67
  findOne: (
63
68
  filter?: MongoFilter<Document>,
64
69
  projection?: Document,
@@ -71,11 +76,6 @@ export type GetOperatorsFunction = (
71
76
  updateOne: (
72
77
  ...params: Parameters<Method<'updateOne'>>
73
78
  ) => ReturnType<Method<'updateOne'>>
74
- findOneAndUpdate: (
75
- filter: MongoFilter<Document>,
76
- update: UpdateFilter<Document> | Document[],
77
- options?: FindOneAndUpdateOptions
78
- ) => Promise<Document | null>
79
79
  find: (
80
80
  filter?: MongoFilter<Document>,
81
81
  projection?: Document,
@@ -102,6 +102,10 @@ export type GetOperatorsFunction = (
102
102
  ) => ReturnType<Method<'deleteMany'>>
103
103
  }
104
104
 
105
+ export type RealmCompatibleFindOneAndUpdateOptions = FindOneAndUpdateOptions & {
106
+ returnNewDocument?: boolean
107
+ }
108
+
105
109
 
106
110
  export enum CRUD_OPERATIONS {
107
111
  CREATE = "CREATE",