pryv 3.10.0 → 3.11.0

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pryv",
3
- "version": "3.10.0",
3
+ "version": "3.11.0",
4
4
  "description": "Pryv JavaScript library",
5
5
  "keywords": [
6
6
  "Pryv",
@@ -86,11 +86,12 @@ async function hmacSha256Hex (verifierSecret, message) {
86
86
  * @param {number} params.ttl seconds the secret stays redeemable (required)
87
87
  * @param {string} params.title shown to the account owner (required)
88
88
  * @param {Object} params.onConsumed `{ message, returnUrl? }` shown once spent
89
- * @param {*} params.secret the payload — any JSON value
89
+ * @param {*} params.secret the payload: any non-null JSON value (the server
90
+ * refuses `null` and `undefined` with `shared-secret-missing-secret`)
90
91
  * @param {Object} [params.signature] `{ type: 'secret', value }` or
91
92
  * `{ type: 'hmac-sha256', verifierSecret }`. For the HMAC form the key
92
93
  * material is generated here so the proof can be bound before creation.
93
- * @returns {Promise<Object>} `{ id, key, expires, ... }` — `key` is returned
94
+ * @returns {Promise<Object>} `{ id, key, expires, ... }`; `key` is returned
94
95
  * only here and cannot be recovered later.
95
96
  */
96
97
  async function create (connection, params) {
package/src/index.d.ts CHANGED
@@ -172,12 +172,14 @@ declare module 'pryv' {
172
172
  * Thrown by `Service.login` when the platform returned `{ mfaToken }`
173
173
  * instead of `{ token }`. Carries the `mfaToken` so the consumer can
174
174
  * call `Service.mfaVerify(userId, err.mfaToken, code)` after prompting
175
- * the user for their SMS code.
175
+ * the user for their code. `method` (when present) says which factor to
176
+ * prompt for: `'totp'` (authenticator app) or `'sms'`.
176
177
  */
177
178
  export class MfaRequiredError extends PryvError {
178
179
  constructor(mfaToken: string, response: Response, body?: any);
179
180
  name: 'MfaRequiredError';
180
181
  mfaToken: string;
182
+ method?: 'totp' | 'sms' | string;
181
183
  }
182
184
 
183
185
  /** Catalogue of Pryv API error ids (mirrors open-pryv.io ErrorIds.js). */
@@ -8,7 +8,10 @@ const PryvError = require('./PryvError');
8
8
  /**
9
9
  * Thrown by `Service.login` when the platform replied with `{ mfaToken }`
10
10
  * instead of `{ token }`. Consumers catch this, prompt the user for the
11
- * SMS code, then call `Service.mfaVerify(userId, err.mfaToken, code)`.
11
+ * code, then call `Service.mfaVerify(userId, err.mfaToken, code)`.
12
+ *
13
+ * `err.method` (when present) tells the app which factor to prompt for:
14
+ * `'totp'` (an authenticator-app code) or `'sms'` (a code sent by SMS).
12
15
  *
13
16
  * try { conn = await service.login(u, p, app) }
14
17
  * catch (err) {
@@ -33,6 +36,8 @@ class MfaRequiredError extends PryvError {
33
36
  this.name = 'MfaRequiredError';
34
37
  /** @type {string} */
35
38
  this.mfaToken = mfaToken;
39
+ /** @type {string|undefined} The MFA method to prompt for: 'totp' | 'sms'. */
40
+ this.method = body && body.mfaMethod;
36
41
  this.id = (apiErr && apiErr.id) || 'mfa-required';
37
42
  this.status = response && response.status;
38
43
  this.response = { body, status: response && response.status };
@@ -90,5 +90,30 @@ describe('[MFLX] Service MFA', function () {
90
90
  expect(err.id).to.equal('custom-id');
91
91
  expect(err.message).to.equal('custom msg');
92
92
  });
93
+
94
+ it('[MERC] surfaces the MFA method from the API body when present', function () {
95
+ const totp = new pryv.MfaRequiredError(
96
+ 'tok-1',
97
+ { status: 200 },
98
+ { mfaToken: 'tok-1', mfaMethod: 'totp' }
99
+ );
100
+ expect(totp.method).to.equal('totp');
101
+
102
+ const sms = new pryv.MfaRequiredError(
103
+ 'tok-2',
104
+ { status: 200 },
105
+ { mfaToken: 'tok-2', mfaMethod: 'sms' }
106
+ );
107
+ expect(sms.method).to.equal('sms');
108
+ });
109
+
110
+ it('[MERD] leaves method undefined when the body omits it (older servers)', function () {
111
+ const err = new pryv.MfaRequiredError(
112
+ 'tok-3',
113
+ { status: 200 },
114
+ { mfaToken: 'tok-3' }
115
+ );
116
+ expect(err.method).to.equal(undefined);
117
+ });
93
118
  });
94
119
  });
@@ -82,8 +82,8 @@ describe('[SERX] Service', function () {
82
82
  if (isDnsLess) {
83
83
  expect(error.message).to.include('Unknown user');
84
84
  } else {
85
- // fetch throws 'fetch failed'
86
- expect(error.message).to.match(/Load failed|fetch failed|getaddrinfo ENOTFOUND|Request has been terminated/);
85
+ // fetch error message differs per environment (Chrome says 'Failed to fetch')
86
+ expect(error.message).to.match(/Load failed|fetch failed|Failed to fetch|getaddrinfo ENOTFOUND|Request has been terminated/);
87
87
  }
88
88
  return;
89
89
  }
@@ -89,7 +89,10 @@ describe('[SSEC] shared-secrets helper', function () {
89
89
  const seen = new Set();
90
90
  for (let i = 0; i < 50; i++) {
91
91
  const out = await SharedSecrets.create(conn, {
92
- ttl: 60, title: 't', onConsumed: { message: 'm' }, secret: 1,
92
+ ttl: 60,
93
+ title: 't',
94
+ onConsumed: { message: 'm' },
95
+ secret: 1,
93
96
  signature: { type: 'hmac-sha256', verifierSecret: 'V' }
94
97
  });
95
98
  const { randomPart } = SharedSecrets.parseKey(out.key);
@@ -2,17 +2,16 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <title>Pryv JS lib browser tests</title>
5
- <link rel="stylesheet" href="https://unpkg.com/mocha/mocha.css" />
5
+ <link rel="stylesheet" href="https://unpkg.com/mocha@10.8.2/mocha.css" />
6
6
  </head>
7
7
 
8
8
  <body>
9
9
  <div id="mocha"></div>
10
10
  <script src="https://unpkg.com/chai@4.3.7/chai.js"></script>
11
- <script src="https://unpkg.com/mocha/mocha.js"></script>
11
+ <script src="https://unpkg.com/mocha@10.8.2/mocha.js"></script>
12
12
 
13
13
  <script class="mocha-init">
14
14
  mocha.setup('bdd');
15
- mocha.setup({ignoreLeaks: true});
16
15
  </script>
17
16
 
18
17
  <!-- Files cf. webpack config -->