@flowerforce/flowerbase 1.4.2-beta.2 → 1.4.2-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,iBA+IxD"}
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,iBA0JxD"}
@@ -31,6 +31,14 @@ function authController(app) {
31
31
  catch (error) {
32
32
  console.error('Failed to ensure refresh token TTL index', error);
33
33
  }
34
+ try {
35
+ yield db.collection(authCollection).createIndex({ email: 1 }, {
36
+ unique: true
37
+ });
38
+ }
39
+ catch (error) {
40
+ console.error('Failed to ensure auth email unique index', error);
41
+ }
34
42
  app.addHook(HANDLER_TYPE, app.jwtAuthentication);
35
43
  /**
36
44
  * Endpoint to retrieve the authenticated user's profile.
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/anon-user/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,eAAe,iBA8E5D"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/anon-user/controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,eAAe,iBAmE5D"}
@@ -10,9 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.anonUserController = anonUserController;
13
+ const bson_1 = require("bson");
13
14
  const constants_1 = require("../../../constants");
14
- const crypto_1 = require("../../../utils/crypto");
15
15
  const handleUserRegistration_model_1 = require("../../../shared/models/handleUserRegistration.model");
16
+ const crypto_1 = require("../../../utils/crypto");
16
17
  const utils_1 = require("../../utils");
17
18
  /**
18
19
  * Controller for handling anonymous user login.
@@ -41,30 +42,23 @@ function anonUserController(app) {
41
42
  throw new Error('Anonymous authentication disabled');
42
43
  }
43
44
  const now = new Date();
44
- const insertResult = yield db.collection(authCollection).insertOne({
45
+ const userId = new bson_1.ObjectId();
46
+ const anonEmail = `anon-${userId.toString()}@users.invalid`;
47
+ yield db.collection(authCollection).insertOne({
48
+ _id: userId,
49
+ email: anonEmail,
45
50
  status: 'confirmed',
46
51
  createdAt: now,
47
52
  custom_data: {},
48
53
  identities: [
49
54
  {
55
+ id: userId.toString(),
56
+ provider_id: userId.toString(),
50
57
  provider_type: handleUserRegistration_model_1.PROVIDER.ANON_USER,
51
58
  provider_data: {}
52
59
  }
53
60
  ]
54
61
  });
55
- const userId = insertResult.insertedId;
56
- yield db.collection(authCollection).updateOne({ _id: userId }, {
57
- $set: {
58
- identities: [
59
- {
60
- id: userId.toString(),
61
- provider_id: userId.toString(),
62
- provider_type: handleUserRegistration_model_1.PROVIDER.ANON_USER,
63
- provider_data: {}
64
- }
65
- ]
66
- }
67
- });
68
62
  const currentUserData = {
69
63
  _id: userId,
70
64
  user_data: {}
@@ -15,10 +15,10 @@ exports.LOGIN_SCHEMA = {
15
15
  username: {
16
16
  type: 'string',
17
17
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
18
- minLength: 3,
18
+ minLength: 5,
19
19
  maxLength: 254
20
20
  },
21
- password: { type: 'string', minLength: 8, maxLength: 128 }
21
+ password: { type: 'string', minLength: 6, maxLength: 128 }
22
22
  },
23
23
  required: ['username', 'password']
24
24
  }
@@ -30,7 +30,7 @@ exports.RESET_SEND_SCHEMA = {
30
30
  email: {
31
31
  type: 'string',
32
32
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
33
- minLength: 3,
33
+ minLength: 5,
34
34
  maxLength: 254
35
35
  }
36
36
  },
@@ -44,10 +44,10 @@ exports.RESET_CALL_SCHEMA = {
44
44
  email: {
45
45
  type: 'string',
46
46
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
47
- minLength: 3,
47
+ minLength: 5,
48
48
  maxLength: 254
49
49
  },
50
- password: { type: 'string', minLength: 8, maxLength: 128 },
50
+ password: { type: 'string', minLength: 6, maxLength: 128 },
51
51
  arguments: { type: 'array' }
52
52
  },
53
53
  required: ['email', 'password']
@@ -57,7 +57,7 @@ exports.CONFIRM_RESET_SCHEMA = {
57
57
  body: {
58
58
  type: 'object',
59
59
  properties: {
60
- password: { type: 'string', minLength: 8, maxLength: 128 },
60
+ password: { type: 'string', minLength: 6, maxLength: 128 },
61
61
  token: { type: 'string' },
62
62
  tokenId: { type: 'string' }
63
63
  },
@@ -82,10 +82,10 @@ exports.REGISTRATION_SCHEMA = {
82
82
  email: {
83
83
  type: 'string',
84
84
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
85
- minLength: 3,
85
+ minLength: 5,
86
86
  maxLength: 254
87
87
  },
88
- password: { type: 'string', minLength: 8, maxLength: 128 }
88
+ password: { type: 'string', minLength: 6, maxLength: 128 }
89
89
  },
90
90
  required: ['email', 'password']
91
91
  }
@@ -1,11 +1,14 @@
1
- import { AWSError } from 'aws-sdk';
2
- import Lambda from 'aws-sdk/clients/lambda';
3
- import S3 from 'aws-sdk/clients/s3';
4
- import { PromiseResult } from 'aws-sdk/lib/request';
1
+ import { InvokeAsyncCommandInput, InvokeAsyncCommandOutput, InvokeCommandInput, InvokeCommandOutput, Lambda } from '@aws-sdk/client-lambda';
2
+ import { S3 } from '@aws-sdk/client-s3';
3
+ type LambdaInvokeResponse = Omit<InvokeCommandOutput, 'Payload'> & {
4
+ Payload: {
5
+ text: () => string | undefined;
6
+ };
7
+ };
5
8
  declare const Aws: () => {
6
9
  lambda: (region: string) => Lambda & {
7
- Invoke: (...args: Parameters<Lambda["invoke"]>) => Promise<PromiseResult<Lambda.InvocationResponse, AWSError>>;
8
- InvokeAsync: Lambda["invokeAsync"];
10
+ Invoke: (params: InvokeCommandInput) => Promise<LambdaInvokeResponse>;
11
+ InvokeAsync: (params: InvokeAsyncCommandInput) => Promise<InvokeAsyncCommandOutput>;
9
12
  };
10
13
  s3: (region: string) => S3;
11
14
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/aws/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAe,MAAM,SAAS,CAAA;AAC/C,OAAO,MAAM,MAAM,wBAAwB,CAAA;AAC3C,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAInD,QAAA,MAAM,GAAG;qBAQY,MAAM;gBAKX,CACN,GAAG,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAClC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;qBACnD,MAAM,CAAC,aAAa,CAAC;;iBAczB,MAAM;CAStB,CAAA;AAED,eAAe,GAAG,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/aws/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,uBAAuB,EACvB,wBAAwB,EAExB,kBAAkB,EAClB,mBAAmB,EACnB,MAAM,EACP,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAGvC,KAAK,oBAAoB,GAAG,IAAI,CAAC,mBAAmB,EAAE,SAAS,CAAC,GAAG;IACjE,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;KAC/B,CAAA;CACF,CAAA;AAUD,QAAA,MAAM,GAAG;qBAUY,MAAM;gBAKX,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC,oBAAoB,CAAC;qBACxD,CAAC,MAAM,EAAE,uBAAuB,KAAK,OAAO,CAAC,wBAAwB,CAAC;;iBAwB1E,MAAM;CAOtB,CAAA;AAED,eAAe,GAAG,CAAA"}
@@ -8,39 +8,46 @@ 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 __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const lambda_1 = __importDefault(require("aws-sdk/clients/lambda"));
16
- const s3_1 = __importDefault(require("aws-sdk/clients/s3"));
12
+ const client_lambda_1 = require("@aws-sdk/client-lambda");
13
+ const client_s3_1 = require("@aws-sdk/client-s3");
17
14
  const constants_1 = require("../../constants");
15
+ const decodePayload = (payload) => {
16
+ if (!payload) {
17
+ return undefined;
18
+ }
19
+ return Buffer.from(payload).toString('utf-8');
20
+ };
18
21
  const Aws = () => {
19
- const credentials = {
20
- accessKeyId: constants_1.S3_CONFIG.ACCESS_KEY_ID,
21
- secretAccessKey: constants_1.S3_CONFIG.SECRET_ACCESS_KEY,
22
- };
22
+ const credentials = constants_1.S3_CONFIG.ACCESS_KEY_ID && constants_1.S3_CONFIG.SECRET_ACCESS_KEY
23
+ ? {
24
+ accessKeyId: constants_1.S3_CONFIG.ACCESS_KEY_ID,
25
+ secretAccessKey: constants_1.S3_CONFIG.SECRET_ACCESS_KEY
26
+ }
27
+ : undefined;
23
28
  return {
24
29
  lambda: (region) => {
25
- const lambda = new lambda_1.default({
30
+ const lambda = new client_lambda_1.Lambda({
26
31
  region: region,
27
32
  credentials
28
33
  });
29
- lambda.Invoke = (...args) => __awaiter(void 0, void 0, void 0, function* () {
30
- const res = yield lambda.invoke(...args).promise();
34
+ lambda.Invoke = (params) => __awaiter(void 0, void 0, void 0, function* () {
35
+ const res = yield lambda.send(new client_lambda_1.InvokeCommand(params));
31
36
  return Object.assign(Object.assign({}, res), { Payload: {
32
- text: () => res.Payload
37
+ text: () => decodePayload(res.Payload)
33
38
  } });
34
39
  });
35
- lambda.InvokeAsync = lambda.invokeAsync;
40
+ const invokeAsync = (params) => __awaiter(void 0, void 0, void 0, function* () {
41
+ return lambda.send(new client_lambda_1.InvokeAsyncCommand(params));
42
+ });
43
+ lambda.InvokeAsync = invokeAsync;
44
+ lambda.invokeAsync = invokeAsync;
36
45
  return lambda;
37
46
  },
38
- s3: (region) => new s3_1.default({
47
+ s3: (region) => new client_s3_1.S3({
39
48
  region,
40
- apiVersion: '2006-03-01',
41
49
  credentials,
42
- s3ForcePathStyle: true,
43
- signatureVersion: 'v4'
50
+ forcePathStyle: true
44
51
  })
45
52
  };
46
53
  };
@@ -114,11 +114,15 @@ export declare const services: {
114
114
  }>;
115
115
  };
116
116
  aws: () => {
117
- lambda: (region: string) => import("aws-sdk").Lambda & {
118
- Invoke: (...args: Parameters<import("aws-sdk").Lambda["invoke"]>) => Promise<import("aws-sdk/lib/request").PromiseResult<import("aws-sdk/clients/lambda").InvocationResponse, import("aws-sdk").AWSError>>;
119
- InvokeAsync: import("aws-sdk").Lambda["invokeAsync"];
117
+ lambda: (region: string) => import("@aws-sdk/client-lambda/dist-types").Lambda & {
118
+ Invoke: (params: import("@aws-sdk/client-lambda/dist-types").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda/dist-types").InvokeCommandOutput, "Payload"> & {
119
+ Payload: {
120
+ text: () => string | undefined;
121
+ };
122
+ }>;
123
+ InvokeAsync: (params: import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandOutput>;
120
124
  };
121
- s3: (region: string) => import("aws-sdk").S3;
125
+ s3: (region: string) => import("@aws-sdk/client-s3/dist-types").S3;
122
126
  };
123
127
  auth: import("./auth/model").AuthServiceType;
124
128
  'mongodb-atlas': import("./mongodb-atlas/model").MongodbAtlasFunction;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAMqT,GAAc;;;;;;;CADvV,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKpB,CAAA"}
@@ -155,11 +155,15 @@ export declare const generateContextData: ({ user, services, app, rules, current
155
155
  context: object;
156
156
  }>;
157
157
  } | {
158
- lambda: (region: string) => import("aws-sdk").Lambda & {
159
- Invoke: (...args: Parameters<import("aws-sdk").Lambda["invoke"]>) => Promise<import("aws-sdk/lib/request").PromiseResult<import("aws-sdk/clients/lambda").InvocationResponse, import("aws-sdk").AWSError>>;
160
- InvokeAsync: import("aws-sdk").Lambda["invokeAsync"];
158
+ lambda: (region: string) => import("@aws-sdk/client-lambda/dist-types").Lambda & {
159
+ Invoke: (params: import("@aws-sdk/client-lambda/dist-types").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda/dist-types").InvokeCommandOutput, "Payload"> & {
160
+ Payload: {
161
+ text: () => string | undefined;
162
+ };
163
+ }>;
164
+ InvokeAsync: (params: import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandOutput>;
161
165
  };
162
- s3: (region: string) => import("aws-sdk").S3;
166
+ s3: (region: string) => import("@aws-sdk/client-s3/dist-types").S3;
163
167
  } | {
164
168
  emailPasswordAuth: {
165
169
  registerUser: ReturnType<import("../../shared/models/handleUserRegistration.model").HandleUserRegistration>;
@@ -284,11 +288,15 @@ export declare const generateContextData: ({ user, services, app, rules, current
284
288
  context: object;
285
289
  }>;
286
290
  } | {
287
- lambda: (region: string) => import("aws-sdk").Lambda & {
288
- Invoke: (...args: Parameters<import("aws-sdk").Lambda["invoke"]>) => Promise<import("aws-sdk/lib/request").PromiseResult<import("aws-sdk/clients/lambda").InvocationResponse, import("aws-sdk").AWSError>>;
289
- InvokeAsync: import("aws-sdk").Lambda["invokeAsync"];
291
+ lambda: (region: string) => import("@aws-sdk/client-lambda/dist-types").Lambda & {
292
+ Invoke: (params: import("@aws-sdk/client-lambda/dist-types").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda/dist-types").InvokeCommandOutput, "Payload"> & {
293
+ Payload: {
294
+ text: () => string | undefined;
295
+ };
296
+ }>;
297
+ InvokeAsync: (params: import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandOutput>;
290
298
  };
291
- s3: (region: string) => import("aws-sdk").S3;
299
+ s3: (region: string) => import("@aws-sdk/client-s3/dist-types").S3;
292
300
  } | {
293
301
  emailPasswordAuth: {
294
302
  registerUser: ReturnType<import("../../shared/models/handleUserRegistration.model").HandleUserRegistration>;
@@ -412,11 +420,15 @@ export declare const generateContextData: ({ user, services, app, rules, current
412
420
  context: object;
413
421
  }>;
414
422
  } | {
415
- lambda: (region: string) => import("aws-sdk").Lambda & {
416
- Invoke: (...args: Parameters<import("aws-sdk").Lambda["invoke"]>) => Promise<import("aws-sdk/lib/request").PromiseResult<import("aws-sdk/clients/lambda").InvocationResponse, import("aws-sdk").AWSError>>;
417
- InvokeAsync: import("aws-sdk").Lambda["invokeAsync"];
423
+ lambda: (region: string) => import("@aws-sdk/client-lambda/dist-types").Lambda & {
424
+ Invoke: (params: import("@aws-sdk/client-lambda/dist-types").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda/dist-types").InvokeCommandOutput, "Payload"> & {
425
+ Payload: {
426
+ text: () => string | undefined;
427
+ };
428
+ }>;
429
+ InvokeAsync: (params: import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandOutput>;
418
430
  };
419
- s3: (region: string) => import("aws-sdk").S3;
431
+ s3: (region: string) => import("@aws-sdk/client-s3/dist-types").S3;
420
432
  } | {
421
433
  emailPasswordAuth: {
422
434
  registerUser: ReturnType<import("../../shared/models/handleUserRegistration.model").HandleUserRegistration>;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/context/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAEvD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,0FASjC,yBAAyB;;;;uBAqBP,SAAS;yBAGP,SAAS;;;;;;;;;;;;;;;;;;uBAcb,MAAM;;;+BArCU,MAAM,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAZP,GAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAF2C,GAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAF2C,GAE3C;;;;;;;;;;4BAuDkB,MAAM,OAAO,aAAa,WAAW,SAAS;;;CAerE,CAAA"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/context/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAEvD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,0FASjC,yBAAyB;;;;uBAqBP,SAAS;yBAGP,SAAS;;;;;;;;;;;;;;;;;;uBAcb,MAAM;;;+BArCU,MAAM,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA6ChC,MAAM,OAAO,aAAa,WAAW,SAAS;;;CAerE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.4.2-beta.2",
3
+ "version": "1.4.2-beta.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,7 +25,8 @@
25
25
  "@fastify/mongodb": "^9.0.1",
26
26
  "@fastify/swagger": "^9.5.1",
27
27
  "@fastify/swagger-ui": "^5.2.3",
28
- "aws-sdk": "^2.1692.0",
28
+ "@aws-sdk/client-lambda": "^3.974.0",
29
+ "@aws-sdk/client-s3": "^3.974.0",
29
30
  "bson": "^6.8.0",
30
31
  "dotenv": "^16.4.7",
31
32
  "fastify": "^5.0.0",
@@ -0,0 +1,51 @@
1
+ import { authController } from '../controller'
2
+
3
+ jest.mock('../../constants', () => ({
4
+ AUTH_CONFIG: {
5
+ authCollection: 'auth_users',
6
+ refreshTokensCollection: 'refresh_tokens',
7
+ userCollection: 'users',
8
+ user_id_field: 'id'
9
+ },
10
+ DB_NAME: 'test-db',
11
+ DEFAULT_CONFIG: {
12
+ REFRESH_TOKEN_TTL_DAYS: 1
13
+ }
14
+ }))
15
+
16
+ describe('authController', () => {
17
+ it('creates a unique email index on the auth collection', async () => {
18
+ const authCollection = {
19
+ createIndex: jest.fn().mockResolvedValue('ok')
20
+ }
21
+ const refreshCollection = {
22
+ createIndex: jest.fn().mockResolvedValue('ok')
23
+ }
24
+ const db = {
25
+ collection: jest.fn((name: string) => {
26
+ if (name === 'auth_users') {
27
+ return authCollection
28
+ }
29
+ if (name === 'refresh_tokens') {
30
+ return refreshCollection
31
+ }
32
+ return { createIndex: jest.fn().mockResolvedValue('ok') }
33
+ })
34
+ }
35
+ const app = {
36
+ mongo: { client: { db: jest.fn().mockReturnValue(db) } },
37
+ addHook: jest.fn(),
38
+ get: jest.fn(),
39
+ post: jest.fn(),
40
+ delete: jest.fn(),
41
+ jwtAuthentication: jest.fn()
42
+ }
43
+
44
+ await authController(app as unknown as never)
45
+
46
+ expect(authCollection.createIndex).toHaveBeenCalledWith(
47
+ { email: 1 },
48
+ { unique: true }
49
+ )
50
+ })
51
+ })
@@ -27,6 +27,17 @@ export async function authController(app: FastifyInstance) {
27
27
  console.error('Failed to ensure refresh token TTL index', error)
28
28
  }
29
29
 
30
+ try {
31
+ await db.collection(authCollection).createIndex(
32
+ { email: 1 },
33
+ {
34
+ unique: true
35
+ }
36
+ )
37
+ } catch (error) {
38
+ console.error('Failed to ensure auth email unique index', error)
39
+ }
40
+
30
41
  app.addHook(HANDLER_TYPE, app.jwtAuthentication)
31
42
 
32
43
  /**
@@ -0,0 +1,82 @@
1
+ import { anonUserController } from '../controller'
2
+ import { PROVIDER } from '../../../../shared/models/handleUserRegistration.model'
3
+
4
+ jest.mock('../../../../constants', () => ({
5
+ AUTH_CONFIG: {
6
+ authCollection: 'auth_users',
7
+ refreshTokensCollection: 'refresh_tokens',
8
+ providers: {
9
+ 'anon-user': { disabled: false }
10
+ }
11
+ },
12
+ DB_NAME: 'test-db',
13
+ DEFAULT_CONFIG: {
14
+ REFRESH_TOKEN_TTL_DAYS: 1,
15
+ ANON_USER_TTL_SECONDS: 3600
16
+ }
17
+ }))
18
+
19
+ describe('anonUserController', () => {
20
+ it('inserts anon users with a generated email', async () => {
21
+ let insertedDoc: Record<string, unknown> | undefined
22
+ const authCollection = {
23
+ createIndex: jest.fn().mockResolvedValue('ok'),
24
+ insertOne: jest.fn(async (doc: Record<string, unknown>) => {
25
+ insertedDoc = doc
26
+ return { insertedId: doc._id }
27
+ })
28
+ }
29
+ const refreshCollection = {
30
+ insertOne: jest.fn().mockResolvedValue({})
31
+ }
32
+ const db = {
33
+ collection: jest.fn((name: string) => {
34
+ if (name === 'auth_users') {
35
+ return authCollection
36
+ }
37
+ if (name === 'refresh_tokens') {
38
+ return refreshCollection
39
+ }
40
+ return authCollection
41
+ })
42
+ }
43
+
44
+ let loginHandler: ((...args: unknown[]) => unknown) | undefined
45
+ const app = {
46
+ mongo: { client: { db: jest.fn().mockReturnValue(db) } },
47
+ post: jest.fn((path: string, handler: (...args: unknown[]) => unknown) => {
48
+ loginHandler = handler
49
+ })
50
+ }
51
+
52
+ await anonUserController(app as unknown as never)
53
+
54
+ const context = {
55
+ createRefreshToken: jest.fn(() => 'refresh'),
56
+ createAccessToken: jest.fn(() => 'access')
57
+ }
58
+
59
+ await (loginHandler as (...args: unknown[]) => Promise<unknown>).call(context, {})
60
+
61
+ const doc = insertedDoc as {
62
+ _id: { toString: () => string }
63
+ email: string
64
+ identities: Array<{
65
+ id?: string
66
+ provider_id?: string
67
+ provider_type?: string
68
+ provider_data?: Record<string, unknown>
69
+ }>
70
+ }
71
+
72
+ expect(doc.email).toBe(`anon-${doc._id.toString()}@users.invalid`)
73
+ expect(doc.identities[0]).toEqual(
74
+ expect.objectContaining({
75
+ id: doc._id.toString(),
76
+ provider_id: doc._id.toString(),
77
+ provider_type: PROVIDER.ANON_USER,
78
+ provider_data: {}
79
+ })
80
+ )
81
+ })
82
+ })
@@ -1,7 +1,8 @@
1
+ import { ObjectId } from 'bson'
1
2
  import { FastifyInstance } from 'fastify'
2
3
  import { AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../../../constants'
3
- import { hashToken } from '../../../utils/crypto'
4
4
  import { PROVIDER } from '../../../shared/models/handleUserRegistration.model'
5
+ import { hashToken } from '../../../utils/crypto'
5
6
  import { AUTH_ENDPOINTS } from '../../utils'
6
7
  import { LoginDto } from './dtos'
7
8
 
@@ -37,35 +38,24 @@ export async function anonUserController(app: FastifyInstance) {
37
38
  }
38
39
 
39
40
  const now = new Date()
40
- const insertResult = await db.collection(authCollection!).insertOne({
41
+ const userId = new ObjectId()
42
+ const anonEmail = `anon-${userId.toString()}@users.invalid`
43
+ await db.collection(authCollection!).insertOne({
44
+ _id: userId,
45
+ email: anonEmail,
41
46
  status: 'confirmed',
42
47
  createdAt: now,
43
48
  custom_data: {},
44
49
  identities: [
45
50
  {
51
+ id: userId.toString(),
52
+ provider_id: userId.toString(),
46
53
  provider_type: PROVIDER.ANON_USER,
47
54
  provider_data: {}
48
55
  }
49
56
  ]
50
57
  })
51
58
 
52
- const userId = insertResult.insertedId
53
- await db.collection(authCollection!).updateOne(
54
- { _id: userId },
55
- {
56
- $set: {
57
- identities: [
58
- {
59
- id: userId.toString(),
60
- provider_id: userId.toString(),
61
- provider_type: PROVIDER.ANON_USER,
62
- provider_data: {}
63
- }
64
- ]
65
- }
66
- }
67
- )
68
-
69
59
  const currentUserData = {
70
60
  _id: userId,
71
61
  user_data: {}
package/src/auth/utils.ts CHANGED
@@ -11,10 +11,10 @@ export const LOGIN_SCHEMA = {
11
11
  username: {
12
12
  type: 'string',
13
13
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
14
- minLength: 3,
14
+ minLength: 5,
15
15
  maxLength: 254
16
16
  },
17
- password: { type: 'string', minLength: 8, maxLength: 128 }
17
+ password: { type: 'string', minLength: 6, maxLength: 128 }
18
18
  },
19
19
  required: ['username', 'password']
20
20
  }
@@ -27,7 +27,7 @@ export const RESET_SEND_SCHEMA = {
27
27
  email: {
28
28
  type: 'string',
29
29
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
30
- minLength: 3,
30
+ minLength: 5,
31
31
  maxLength: 254
32
32
  }
33
33
  },
@@ -42,10 +42,10 @@ export const RESET_CALL_SCHEMA = {
42
42
  email: {
43
43
  type: 'string',
44
44
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
45
- minLength: 3,
45
+ minLength: 5,
46
46
  maxLength: 254
47
47
  },
48
- password: { type: 'string', minLength: 8, maxLength: 128 },
48
+ password: { type: 'string', minLength: 6, maxLength: 128 },
49
49
  arguments: { type: 'array' }
50
50
  },
51
51
  required: ['email', 'password']
@@ -56,7 +56,7 @@ export const CONFIRM_RESET_SCHEMA = {
56
56
  body: {
57
57
  type: 'object',
58
58
  properties: {
59
- password: { type: 'string', minLength: 8, maxLength: 128 },
59
+ password: { type: 'string', minLength: 6, maxLength: 128 },
60
60
  token: { type: 'string' },
61
61
  tokenId: { type: 'string' }
62
62
  },
@@ -84,10 +84,10 @@ export const REGISTRATION_SCHEMA = {
84
84
  email: {
85
85
  type: 'string',
86
86
  pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
87
- minLength: 3,
87
+ minLength: 5,
88
88
  maxLength: 254
89
89
  },
90
- password: { type: 'string', minLength: 8, maxLength: 128 }
90
+ password: { type: 'string', minLength: 6, maxLength: 128 }
91
91
  },
92
92
  required: ['email', 'password']
93
93
  }
@@ -1,16 +1,37 @@
1
- import { AWSError, Credentials } from 'aws-sdk'
2
- import Lambda from 'aws-sdk/clients/lambda'
3
- import S3 from 'aws-sdk/clients/s3'
4
- import { PromiseResult } from 'aws-sdk/lib/request'
1
+ import {
2
+ InvokeAsyncCommand,
3
+ InvokeAsyncCommandInput,
4
+ InvokeAsyncCommandOutput,
5
+ InvokeCommand,
6
+ InvokeCommandInput,
7
+ InvokeCommandOutput,
8
+ Lambda
9
+ } from '@aws-sdk/client-lambda'
10
+ import { S3 } from '@aws-sdk/client-s3'
5
11
  import { S3_CONFIG } from '../../constants'
6
12
 
13
+ type LambdaInvokeResponse = Omit<InvokeCommandOutput, 'Payload'> & {
14
+ Payload: {
15
+ text: () => string | undefined
16
+ }
17
+ }
7
18
 
8
- const Aws = () => {
19
+ const decodePayload = (payload?: Uint8Array): string | undefined => {
20
+ if (!payload) {
21
+ return undefined
22
+ }
9
23
 
10
- const credentials = {
11
- accessKeyId: S3_CONFIG.ACCESS_KEY_ID,
12
- secretAccessKey: S3_CONFIG.SECRET_ACCESS_KEY,
13
- } as Credentials
24
+ return Buffer.from(payload).toString('utf-8')
25
+ }
26
+
27
+ const Aws = () => {
28
+ const credentials =
29
+ S3_CONFIG.ACCESS_KEY_ID && S3_CONFIG.SECRET_ACCESS_KEY
30
+ ? {
31
+ accessKeyId: S3_CONFIG.ACCESS_KEY_ID,
32
+ secretAccessKey: S3_CONFIG.SECRET_ACCESS_KEY
33
+ }
34
+ : undefined
14
35
 
15
36
  return {
16
37
  lambda: (region: string) => {
@@ -18,30 +39,36 @@ const Aws = () => {
18
39
  region: region,
19
40
  credentials
20
41
  }) as Lambda & {
21
- Invoke: (
22
- ...args: Parameters<Lambda['invoke']>
23
- ) => Promise<PromiseResult<Lambda.InvocationResponse, AWSError>>
24
- InvokeAsync: Lambda['invokeAsync']
42
+ Invoke: (params: InvokeCommandInput) => Promise<LambdaInvokeResponse>
43
+ InvokeAsync: (params: InvokeAsyncCommandInput) => Promise<InvokeAsyncCommandOutput>
25
44
  }
26
- lambda.Invoke = async (...args: Parameters<Lambda['invoke']>) => {
27
- const res = await lambda.invoke(...args).promise()
45
+
46
+ lambda.Invoke = async (params: InvokeCommandInput): Promise<LambdaInvokeResponse> => {
47
+ const res = await lambda.send(new InvokeCommand(params))
28
48
  return {
29
49
  ...res,
30
50
  Payload: {
31
- text: () => res.Payload
51
+ text: () => decodePayload(res.Payload)
32
52
  }
33
53
  }
34
54
  }
35
- lambda.InvokeAsync = lambda.invokeAsync
55
+
56
+ const invokeAsync = async (
57
+ params: InvokeAsyncCommandInput
58
+ ): Promise<InvokeAsyncCommandOutput> => {
59
+ return lambda.send(new InvokeAsyncCommand(params))
60
+ }
61
+
62
+ lambda.InvokeAsync = invokeAsync
63
+ lambda.invokeAsync = invokeAsync
64
+
36
65
  return lambda
37
66
  },
38
67
  s3: (region: string) =>
39
68
  new S3({
40
69
  region,
41
- apiVersion: '2006-03-01',
42
70
  credentials,
43
- s3ForcePathStyle: true,
44
- signatureVersion: 'v4'
71
+ forcePathStyle: true
45
72
  })
46
73
  }
47
74
  }