impulse-api 3.0.3 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "test": "nyc --reporter=lcov --reporter=text-summary mocha",
13
13
  "test-server": "node ./test/integration/test-server.js"
14
14
  },
15
- "version": "3.0.3",
15
+ "version": "3.0.4",
16
16
  "engines": {
17
17
  "node": ">=22"
18
18
  },
package/src/auth.js CHANGED
@@ -1,11 +1,21 @@
1
1
  const jwt = require('jsonwebtoken');
2
- const auth = {
3
- generateToken(params, config) {
4
- return(jwt.sign(params, config.secretKey));
5
- },
6
- verifyToken(token, secretKey) {
7
- return jwt.verify(token, secretKey);
8
- },
2
+
3
+ class Auth {
4
+ constructor(secretKey) {
5
+ if (!secretKey) {
6
+ throw new Error('Auth instance must be initialized with secretKey');
7
+ }
8
+ this.secretKey = secretKey;
9
+ }
10
+
11
+ generateToken(params) {
12
+ return jwt.sign(params, this.secretKey);
13
+ }
14
+
15
+ verifyToken(token) {
16
+ return jwt.verify(token, this.secretKey);
17
+ }
18
+
9
19
  // Helper function to create custom validators
10
20
  createCustomValidator(validatorFn) {
11
21
  if (typeof validatorFn !== 'function') {
@@ -13,6 +23,6 @@ const auth = {
13
23
  }
14
24
  return validatorFn;
15
25
  }
16
- };
26
+ }
17
27
 
18
- module.exports = auth;
28
+ module.exports = Auth;
package/src/server.js CHANGED
@@ -36,6 +36,7 @@ class Server {
36
36
  this.heartbeat = config.heartbeat || null;
37
37
  this.container = new Container(config.services);
38
38
  this.secretKey = config.secretKey;
39
+ this.auth = config.secretKey ? new Auth(config.secretKey) : null;
39
40
  this.tokenValidator = config.tokenValidator || null;
40
41
  this.errors = config.errors || Errors;
41
42
  process.env.NODE_ENV = this.env || 'dev';
@@ -225,7 +226,10 @@ class Server {
225
226
  decoded = await this.tokenValidator(token, this.container);
226
227
  } else {
227
228
  // Default JWT validation
228
- decoded = await Auth.verifyToken(token, this.secretKey);
229
+ if (!this.auth) {
230
+ throw new Error(`Route ${route.name} requires token auth but server was not initialized with secretKey`);
231
+ }
232
+ decoded = this.auth.verifyToken(token);
229
233
  }
230
234
 
231
235
  // Allow route-specific validation to override the global validator
@@ -99,8 +99,9 @@ exports.testRoute = {
99
99
  await api.init();
100
100
 
101
101
  // Test default JWT validation
102
- const token = Auth.generateToken({ userId: 'test-user' }, { secretKey: 'test-secret' });
103
- const decoded = Auth.verifyToken(token, 'test-secret');
102
+ const auth = new Auth('test-secret');
103
+ const token = auth.generateToken({ userId: 'test-user' });
104
+ const decoded = auth.verifyToken(token);
104
105
  assert.strictEqual(decoded.userId, 'test-user');
105
106
  });
106
107
  });
@@ -290,8 +291,9 @@ exports.testRoute = {
290
291
  await api.init();
291
292
 
292
293
  // Test that default JWT validation still works
293
- const token = Auth.generateToken({ userId: 'legacy-user' }, { secretKey: 'test-secret' });
294
- const decoded = Auth.verifyToken(token, 'test-secret');
294
+ const auth = new Auth('test-secret');
295
+ const token = auth.generateToken({ userId: 'legacy-user' });
296
+ const decoded = auth.verifyToken(token);
295
297
  assert.strictEqual(decoded.userId, 'legacy-user');
296
298
  });
297
299
  });
@@ -1,4 +1,5 @@
1
1
  const Server = require('../src/server');
2
+ const Auth = require('../src/auth');
2
3
  const assert = require('assert');
3
4
  const sinon = require('sinon');
4
5
 
@@ -355,4 +356,147 @@ describe('server-test', () => {
355
356
  sinon.assert.notCalled(spy);
356
357
  });
357
358
  });
359
+
360
+ describe('Auth module', () => {
361
+ describe('instantiation', () => {
362
+ it('should throw an error if secretKey is not provided', () => {
363
+ try {
364
+ new Auth();
365
+ assert.fail('Should have thrown an error');
366
+ } catch (e) {
367
+ assert.contains(e.message, 'must be initialized with secretKey');
368
+ }
369
+ });
370
+
371
+ it('should throw an error if secretKey is null', () => {
372
+ try {
373
+ new Auth(null);
374
+ assert.fail('Should have thrown an error');
375
+ } catch (e) {
376
+ assert.contains(e.message, 'must be initialized with secretKey');
377
+ }
378
+ });
379
+
380
+ it('should throw an error if secretKey is undefined', () => {
381
+ try {
382
+ new Auth(undefined);
383
+ assert.fail('Should have thrown an error');
384
+ } catch (e) {
385
+ assert.contains(e.message, 'must be initialized with secretKey');
386
+ }
387
+ });
388
+
389
+ it('should create an instance when secretKey is provided', () => {
390
+ const auth = new Auth('test-secret-key');
391
+ assert.strictEqual(auth.secretKey, 'test-secret-key');
392
+ });
393
+ });
394
+
395
+ describe('generateToken', () => {
396
+ it('should generate a token without requiring secretKey parameter', () => {
397
+ const auth = new Auth('test-secret-key');
398
+ const params = { userId: 'test-user', role: 'admin' };
399
+ const token = auth.generateToken(params);
400
+ assert.strictEqual(typeof token, 'string');
401
+ assert.strictEqual(token.length > 0, true);
402
+ });
403
+
404
+ it('should generate different tokens for different params', () => {
405
+ const auth = new Auth('test-secret-key');
406
+ const token1 = auth.generateToken({ userId: 'user1' });
407
+ const token2 = auth.generateToken({ userId: 'user2' });
408
+ assert.notStrictEqual(token1, token2);
409
+ });
410
+ });
411
+
412
+ describe('verifyToken', () => {
413
+ it('should verify a token without requiring secretKey parameter', () => {
414
+ const auth = new Auth('test-secret-key');
415
+ const params = { userId: 'test-user', role: 'admin' };
416
+ const token = auth.generateToken(params);
417
+ const decoded = auth.verifyToken(token);
418
+ assert.strictEqual(decoded.userId, 'test-user');
419
+ assert.strictEqual(decoded.role, 'admin');
420
+ });
421
+
422
+ it('should throw an error when verifying a token with wrong secretKey', () => {
423
+ const auth1 = new Auth('secret-key-1');
424
+ const auth2 = new Auth('secret-key-2');
425
+ const token = auth1.generateToken({ userId: 'test-user' });
426
+ try {
427
+ auth2.verifyToken(token);
428
+ assert.fail('Should have thrown an error');
429
+ } catch (e) {
430
+ assert.contains(e.message, 'invalid signature');
431
+ }
432
+ });
433
+
434
+ it('should throw an error when verifying an invalid token', () => {
435
+ const auth = new Auth('test-secret-key');
436
+ try {
437
+ auth.verifyToken('invalid-token-string');
438
+ assert.fail('Should have thrown an error');
439
+ } catch (e) {
440
+ assert.strictEqual(typeof e.message, 'string');
441
+ }
442
+ });
443
+ });
444
+
445
+ describe('createCustomValidator', () => {
446
+ it('should throw an error if validator is not a function', () => {
447
+ const auth = new Auth('test-secret-key');
448
+ try {
449
+ auth.createCustomValidator('not-a-function');
450
+ assert.fail('Should have thrown an error');
451
+ } catch (e) {
452
+ assert.contains(e.message, 'must be a function');
453
+ }
454
+ });
455
+
456
+ it('should return the validator function if valid', () => {
457
+ const auth = new Auth('test-secret-key');
458
+ const validatorFn = () => true;
459
+ const result = auth.createCustomValidator(validatorFn);
460
+ assert.strictEqual(result, validatorFn);
461
+ });
462
+ });
463
+ });
464
+
465
+ describe('Server Auth integration', () => {
466
+ it('should create auth instance when secretKey is provided', () => {
467
+ const server = new Server({
468
+ name: 'test-server',
469
+ routeDir: './test-routes',
470
+ port: 4000,
471
+ env: 'test',
472
+ secretKey: 'test-secret-key',
473
+ services: {}
474
+ });
475
+ assert.strictEqual(server.auth !== null, true);
476
+ assert.strictEqual(server.auth.secretKey, 'test-secret-key');
477
+ });
478
+
479
+ it('should not create auth instance when secretKey is not provided', () => {
480
+ const server = new Server({
481
+ name: 'test-server',
482
+ routeDir: './test-routes',
483
+ port: 4000,
484
+ env: 'test',
485
+ services: {}
486
+ });
487
+ assert.strictEqual(server.auth, null);
488
+ });
489
+
490
+ it('should not create auth instance when secretKey is null', () => {
491
+ const server = new Server({
492
+ name: 'test-server',
493
+ routeDir: './test-routes',
494
+ port: 4000,
495
+ env: 'test',
496
+ secretKey: null,
497
+ services: {}
498
+ });
499
+ assert.strictEqual(server.auth, null);
500
+ });
501
+ });
358
502
  });