@qikdev/sdk 1.0.12 → 1.0.13
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/dist/main.js +796 -759
- package/package.json +1 -1
- package/src/api/qik.access.js +177 -201
- package/src/api/qik.api.js +55 -28
- package/src/api/qik.auth.js +181 -113
- package/src/api/qik.cache.js +29 -7
- package/src/api/qik.content.js +275 -147
- package/src/api/qik.core.js +19 -28
- package/src/api/qik.files.js +48 -38
- package/src/api/qik.filter.js +148 -207
- package/src/api/qik.geo.js +59 -42
- package/src/api/qik.socket.js +117 -43
- package/src/api/qik.storage.js +17 -8
- package/src/api/qik.system.js +6 -5
- package/src/api/qik.utils.js +244 -199
- package/src/version.js +1 -1
package/src/api/qik.api.js
CHANGED
|
@@ -5,13 +5,26 @@ import { version } from "../version.js";
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* The HTTP client for the Qik REST API: an axios instance whose base URL is the API, so paths are relative
|
|
9
|
+
* ('/content/profile/list'). Every request automatically carries the current access token (refreshed
|
|
10
|
+
* first when it's about to expire), the caller's timezone and the SDK version. Responses are axios
|
|
11
|
+
* responses, so the body is in `.data`; errors are axios errors (the server's message is in
|
|
12
|
+
* err.response.data.message, or use sdk.utils.errorMessage(err)).
|
|
13
|
+
* Use the standard axios methods: get(url, config), delete(url, config), post(url, body, config),
|
|
14
|
+
* put(url, body, config), patch(url, body, config). Query string values go in config.params (arrays are
|
|
15
|
+
* sent as repeated keys: ?select=a&select=b). A request body for DELETE goes in config.data.
|
|
16
|
+
* Rate-limited requests (429) are retried up to 3 times honouring Retry-After, and 502/504 responses are retried.
|
|
17
|
+
* Identical requests made at the same time share one network call.
|
|
18
|
+
* Extra config options the SDK understands: `bypassInterceptor: true` skips the automatic token refresh
|
|
19
|
+
* (the current token is still sent); add `withoutToken: true` as well to send no access token or Qik headers at all.
|
|
11
20
|
* @alias api
|
|
12
21
|
* @constructor
|
|
13
22
|
* @hideconstructor
|
|
14
|
-
* @param {
|
|
23
|
+
* @param {QikCore} qik A reference to the parent instance of the QikCore module. This module is usually created by a QikCore instance that passes itself in as the first argument.
|
|
24
|
+
* @example
|
|
25
|
+
* const { data } = await sdk.api.get('/user');
|
|
26
|
+
* const { data: result } = await sdk.api.post('/content/profile/list', { select: ['firstName'], page: { size: 10 } });
|
|
27
|
+
* const { data: partial } = await sdk.api.get('/content/61eca4746971e75c1fc670cd', { params: { select: ['title', 'meta.created'] } });
|
|
15
28
|
*/
|
|
16
29
|
|
|
17
30
|
const CancelToken = axios.CancelToken;
|
|
@@ -121,25 +134,19 @@ var QikAPI = function (qik) {
|
|
|
121
134
|
//////////////////////////////////////////////////////////////////////////////
|
|
122
135
|
|
|
123
136
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
137
|
+
* Builds a full URL for an API endpoint, with the current access token added as ?access_token=, for
|
|
138
|
+
* links the browser opens by itself (a download link, an <img> src, a new window) where no
|
|
139
|
+
* Authorization header can be sent. The token in the URL grants the user's access, so don't share or log these URLs.
|
|
127
140
|
* @alias api.generateEndpointURL
|
|
128
|
-
* @param
|
|
129
|
-
* @param
|
|
130
|
-
* @param
|
|
131
|
-
* @param
|
|
132
|
-
* @param
|
|
141
|
+
* @param {String} endpoint The path, starting with a slash, e.g. '/image/61eca4746971e75c1fc670cf'.
|
|
142
|
+
* @param {Object} [params] Query string values. Values that are undefined, null, false, 0 or '' are left out; arrays become repeated keys.
|
|
143
|
+
* @param {Object} [options] Options.
|
|
144
|
+
* @param {Boolean} [options.withoutToken] Don't add the access token.
|
|
145
|
+
* @param {Boolean} [options.file] Build the URL on the file host (sdk.fileAPI) when one is configured, instead of the API URL.
|
|
146
|
+
* @returns {String} The URL, e.g. 'https://api.qik.dev/image/61eca...?access_token=XXXX&w=100&h=50'.
|
|
133
147
|
* @example
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* const result = sdk.api.generateEndpointURL('/image/61eca4746971e75c1fc670cf', {
|
|
137
|
-
* w:100,
|
|
138
|
-
* h:50,
|
|
139
|
-
* }, {file:true})
|
|
140
|
-
*
|
|
141
|
-
* // Would return something similar to:
|
|
142
|
-
* // https://api.qik.dev/image/61eca4746971e75c1fc670cf?w=100&h=50&access_token=XXXX...
|
|
148
|
+
* const url = sdk.api.generateEndpointURL('/image/61eca4746971e75c1fc670cf', { w: 100, h: 50 }, { file: true });
|
|
149
|
+
* // https://api.qik.dev/image/61eca4746971e75c1fc670cf?access_token=XXXX&w=100&h=50
|
|
143
150
|
*/
|
|
144
151
|
service.generateEndpointURL = function (endpoint, params, options) {
|
|
145
152
|
options = options || {};
|
|
@@ -172,6 +179,19 @@ var QikAPI = function (qik) {
|
|
|
172
179
|
|
|
173
180
|
//////////////////////////////////////////////////////////////////////////////
|
|
174
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Tells whether a request error came from cancelling the request (for example a cancellable content.list),
|
|
184
|
+
* so you can ignore it instead of showing an error.
|
|
185
|
+
* @alias api.wasCancelled
|
|
186
|
+
* @param {Error} err The error a request rejected with.
|
|
187
|
+
* @returns {Boolean} True when the request was cancelled.
|
|
188
|
+
* @example
|
|
189
|
+
* try {
|
|
190
|
+
* await request.promise;
|
|
191
|
+
* } catch (err) {
|
|
192
|
+
* if (!sdk.api.wasCancelled(err)) throw err;
|
|
193
|
+
* }
|
|
194
|
+
*/
|
|
175
195
|
service.wasCancelled = function (err) {
|
|
176
196
|
return axios.isCancel(err);
|
|
177
197
|
};
|
|
@@ -343,16 +363,23 @@ var QikAPI = function (qik) {
|
|
|
343
363
|
///////////////////////////////////////
|
|
344
364
|
|
|
345
365
|
/**
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
* external APIs and not send tokens etc..
|
|
350
|
-
* @name api.axios
|
|
366
|
+
* The axios CancelToken class, for cancelling an in-flight request: create a source, pass
|
|
367
|
+
* source.token as the request's cancelToken, and call source.cancel() to abort it.
|
|
368
|
+
* @alias api.CancelToken
|
|
351
369
|
* @example
|
|
352
|
-
* const
|
|
370
|
+
* const source = sdk.api.CancelToken.source();
|
|
371
|
+
* const request = sdk.api.get('/user', { cancelToken: source.token });
|
|
372
|
+
* source.cancel('No longer needed');
|
|
353
373
|
*/
|
|
354
|
-
|
|
355
374
|
service.CancelToken = CancelToken;
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* The plain axios library (https://www.npmjs.com/package/axios), for requests to other services:
|
|
378
|
+
* requests made with it carry no Qik token or headers and don't use the API base URL.
|
|
379
|
+
* @alias api.axios
|
|
380
|
+
* @example
|
|
381
|
+
* const { data } = await sdk.api.axios.get('https://example.com/feed.json');
|
|
382
|
+
*/
|
|
356
383
|
service.axios = axios;
|
|
357
384
|
|
|
358
385
|
///////////////////////////////////////
|
package/src/api/qik.auth.js
CHANGED
|
@@ -4,12 +4,23 @@ import { createStorageAdapter } from './qik.storage.js';
|
|
|
4
4
|
///////////////////////////////////////////////////
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Signing in and out and the current session. The SDK keeps the session in memory (or, with
|
|
8
|
+
* useHttpOnlyCookies, lets the browser hold the tokens in httpOnly cookies) and attaches its access token to
|
|
9
|
+
* every sdk.api request, refreshing it shortly before it expires. A 401 response signs the user out.
|
|
10
|
+
* The session object returned by getCurrentUser() is { session, token }: `session` describes the signed-in
|
|
11
|
+
* user in the current organisation (_id, firstName, lastName, email, userType, organisation, persona,
|
|
12
|
+
* profiles, permissions, cacheKey...) and is what the sdk.access helpers expect; `token` is
|
|
13
|
+
* { accessToken, refreshToken, expires } (absent in cookie mode).
|
|
14
|
+
* Listen for 'change' with sdk.auth.addEventListener('change', handler): the handler gets the new stored
|
|
15
|
+
* value (or null after sign-out) and, as a second argument, any parameters passed to sdk.auth.set().
|
|
9
16
|
* @alias auth
|
|
10
17
|
* @constructor
|
|
11
18
|
* @hideconstructor
|
|
12
|
-
* @param {
|
|
19
|
+
* @param {QikCore} qik A reference to the parent instance of the QikCore module. This module is usually created by a QikCore instance that passes itself in as the first argument.
|
|
20
|
+
* @example
|
|
21
|
+
* sdk.auth.addEventListener('change', (user) => {
|
|
22
|
+
* console.log(user ? `Signed in as ${user.session.firstName}` : 'Signed out');
|
|
23
|
+
* });
|
|
13
24
|
*/
|
|
14
25
|
|
|
15
26
|
var QikAuth = function(qik) {
|
|
@@ -59,10 +70,11 @@ var QikAuth = function(qik) {
|
|
|
59
70
|
|
|
60
71
|
//Dispatch the change to the listeners
|
|
61
72
|
if (service.onChange) {
|
|
62
|
-
service.onChange(user);
|
|
73
|
+
service.onChange(user, parameters);
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
//Dispatch the change event
|
|
76
|
+
//Dispatch the change event: listeners get the user first and any
|
|
77
|
+
//parameters passed to set() second
|
|
66
78
|
dispatcher.dispatch('change', user, parameters);
|
|
67
79
|
}
|
|
68
80
|
|
|
@@ -70,15 +82,17 @@ var QikAuth = function(qik) {
|
|
|
70
82
|
///////////////////////////////////////////////////
|
|
71
83
|
|
|
72
84
|
/**
|
|
85
|
+
* Stores a session as the current one (replacing any other) and fires 'change', unless it's identical
|
|
86
|
+
* to the session already stored. Use it with a session returned by a call made with
|
|
87
|
+
* { disableAutoAuthentication: true }.
|
|
73
88
|
* @alias auth.set
|
|
74
|
-
* @
|
|
75
|
-
* @param
|
|
76
|
-
* @param
|
|
77
|
-
* @
|
|
89
|
+
* @param {Object|null} user The { session, token } object to store, as returned by login, changeOrganisation or impersonate. null clears it.
|
|
90
|
+
* @param {Object} [parameters] Extra details for 'change' listeners, passed to them as their second argument (the user is the first).
|
|
91
|
+
* @param {Boolean} [stopDispatch] Store the session without firing 'change'.
|
|
92
|
+
* @returns {undefined}
|
|
78
93
|
* @example
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* sdk.auth.set(userSession);
|
|
94
|
+
* const { data } = await sdk.auth.login(credentials, { disableAutoAuthentication: true });
|
|
95
|
+
* sdk.auth.set(data);
|
|
82
96
|
*/
|
|
83
97
|
|
|
84
98
|
service.set = function(user, parameters, stopDispatch) {
|
|
@@ -97,8 +111,10 @@ var QikAuth = function(qik) {
|
|
|
97
111
|
///////////////////////////////////////////////////
|
|
98
112
|
|
|
99
113
|
/**
|
|
114
|
+
* Signs out locally: forgets the current session, clears every SDK cache (sdk.cache.reset()) and fires
|
|
115
|
+
* 'change' with null. No request is sent to the server.
|
|
100
116
|
* @alias auth.logout
|
|
101
|
-
* @
|
|
117
|
+
* @returns {undefined}
|
|
102
118
|
* @example
|
|
103
119
|
* sdk.auth.logout();
|
|
104
120
|
*/
|
|
@@ -112,21 +128,19 @@ var QikAuth = function(qik) {
|
|
|
112
128
|
///////////////////////////////////////////////////
|
|
113
129
|
|
|
114
130
|
/**
|
|
131
|
+
* Switches the signed-in user into another organisation they belong to (POST /user/switch/:organisationID).
|
|
132
|
+
* By default the new session replaces the current one, SDK caches are cleared and 'change' fires; an open
|
|
133
|
+
* socket reconnects under the new organisation.
|
|
115
134
|
* @alias auth.changeOrganisation
|
|
116
|
-
* @
|
|
117
|
-
* @param
|
|
118
|
-
* @param
|
|
119
|
-
* @
|
|
120
|
-
* will be updated to reflect a session in the new organisation, you can use this option to disable that behavior and instead return the
|
|
121
|
-
* user session without dispatching any events
|
|
135
|
+
* @param {String|Object} organisationID The organisation's id, or an object with an _id.
|
|
136
|
+
* @param {Object} [options] Options.
|
|
137
|
+
* @param {Boolean} [options.disableAutoAuthentication] Only return the new session; don't store it, clear caches or fire 'change'.
|
|
138
|
+
* @returns {Promise<Object>} The new { session, token } for that organisation.
|
|
122
139
|
* @example
|
|
140
|
+
* await sdk.auth.changeOrganisation('61eca4746971e75c1fc670cf');
|
|
123
141
|
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* const newSession = await sdk.auth.changeOrganisation('61eca4746971e75c1fc670cf', {disableAutoAuthentication:true});
|
|
128
|
-
* // Current user session will not be updated
|
|
129
|
-
* sdk.auth.set(newSession);
|
|
142
|
+
* // Get the session without switching to it
|
|
143
|
+
* const newSession = await sdk.auth.changeOrganisation('61eca4746971e75c1fc670cf', { disableAutoAuthentication: true });
|
|
130
144
|
*/
|
|
131
145
|
service.changeOrganisation = function(organisationID, options) {
|
|
132
146
|
|
|
@@ -171,21 +185,18 @@ var QikAuth = function(qik) {
|
|
|
171
185
|
///////////////////////////////////////////////////
|
|
172
186
|
|
|
173
187
|
/**
|
|
188
|
+
* Starts a session as another person (persona) in the organisation, for administrators checking what
|
|
189
|
+
* someone else sees (POST /user/impersonate with { persona, application } in the body).
|
|
190
|
+
* On success the new session replaces the current one and caches are cleared.
|
|
174
191
|
* @alias auth.impersonate
|
|
175
|
-
* @
|
|
176
|
-
* @param
|
|
177
|
-
* @param
|
|
178
|
-
* @param
|
|
179
|
-
*
|
|
180
|
-
* new impersonation user session without dispatching any events
|
|
192
|
+
* @param {String|Object} personaID The persona's id, or an object with an _id.
|
|
193
|
+
* @param {Object} [options] Options.
|
|
194
|
+
* @param {String|Object} [options.application] An application id (or object with an _id), to impersonate the persona as an app user of that application.
|
|
195
|
+
* @param {Boolean} [options.disableAutoAuthentication] Only return the response; don't store the new session or clear caches.
|
|
196
|
+
* @returns {Promise<Object>} The axios response; its `data` is the impersonation { session, token }.
|
|
181
197
|
* @example
|
|
182
|
-
*
|
|
183
|
-
* sdk.auth.
|
|
184
|
-
* // Current user session will be automatically updated
|
|
185
|
-
*
|
|
186
|
-
* const newSession = await sdk.auth.impersonate('61eca4746971e75c1fc670cf', {disableAutoAuthentication:true});
|
|
187
|
-
* // Current user session will not be updated
|
|
188
|
-
* sdk.auth.set(newSession);
|
|
198
|
+
* await sdk.auth.impersonate('61eca4746971e75c1fc670cf');
|
|
199
|
+
* console.log(sdk.auth.getCurrentUser().session.firstName);
|
|
189
200
|
*/
|
|
190
201
|
service.impersonate = function(personaID, options) {
|
|
191
202
|
|
|
@@ -209,7 +220,13 @@ var QikAuth = function(qik) {
|
|
|
209
220
|
|
|
210
221
|
//////////////////////////
|
|
211
222
|
|
|
212
|
-
|
|
223
|
+
// The server reads the persona (and optional application) from the body
|
|
224
|
+
var body = { persona: personaID };
|
|
225
|
+
if (options.application) {
|
|
226
|
+
body.application = qik.utils.id(options.application);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
var promise = qik.api.post(`/user/impersonate`, body)
|
|
213
230
|
|
|
214
231
|
promise.then(function(res) {
|
|
215
232
|
|
|
@@ -227,30 +244,34 @@ var QikAuth = function(qik) {
|
|
|
227
244
|
///////////////////////////////////////////////////
|
|
228
245
|
|
|
229
246
|
/**
|
|
247
|
+
* Signs in with an email and password (POST /user/login). When a one-time code is required (always for
|
|
248
|
+
* dashboard users; for app users when the application or the person requires it) the first call, without `mfa`,
|
|
249
|
+
* emails a code and returns { mfa: true, type: 'email', to, expires } instead of a session; call again with
|
|
250
|
+
* the same credentials plus the code in `mfa` to get the session.
|
|
251
|
+
* With an `application` id (or when running on an application's domain) the person signs in to that
|
|
252
|
+
* application's organisation as an app user; otherwise as a dashboard user.
|
|
253
|
+
* By default a returned session is stored as the current one and 'change' fires; the code-required
|
|
254
|
+
* response is only returned, not stored.
|
|
255
|
+
* With useHttpOnlyCookies the tokens are set as httpOnly cookies instead of being returned for storage.
|
|
230
256
|
* @alias auth.login
|
|
231
|
-
* @
|
|
232
|
-
* @param
|
|
233
|
-
* @param
|
|
234
|
-
* @param
|
|
235
|
-
* @param
|
|
236
|
-
* @param
|
|
237
|
-
* @param
|
|
238
|
-
*
|
|
239
|
-
*
|
|
257
|
+
* @param {Object} credentials The sign-in details.
|
|
258
|
+
* @param {String} credentials.email The email address.
|
|
259
|
+
* @param {String} credentials.password The password.
|
|
260
|
+
* @param {String} [credentials.mfa] The one-time code from the email, on the second call.
|
|
261
|
+
* @param {String} [credentials.application] Application id, to sign in to an application's organisation as an app user.
|
|
262
|
+
* @param {String} [credentials.organisation] Organisation id to sign in to (dashboard users who belong to several).
|
|
263
|
+
* @param {Object} [options] Options.
|
|
264
|
+
* @param {Boolean} [options.disableAutoAuthentication] Only return the response; don't store the session or fire 'change'.
|
|
265
|
+
* @param {String} [options.url] Post to this URL instead of the API's /user/login.
|
|
266
|
+
* @returns {Promise<Object>} The axios response. Its `data` is either the code request { mfa: true, type, to, expires } or the session { session, token }. Rejects with { message } when email or password is missing, or with the server error (400 for wrong credentials or code).
|
|
240
267
|
* @example
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* mfa:'
|
|
268
|
+
* const credentials = { email: 'me@example.com', password: '******' };
|
|
269
|
+
* let { data } = await sdk.auth.login(credentials);
|
|
270
|
+
* if (data.mfa) {
|
|
271
|
+
* // ask for the code emailed to data.to, then:
|
|
272
|
+
* ({ data } = await sdk.auth.login({ ...credentials, mfa: '123456' }));
|
|
246
273
|
* }
|
|
247
|
-
*
|
|
248
|
-
* sdk.auth.login(credentials);
|
|
249
|
-
* // Current user session will be automatically updated
|
|
250
|
-
*
|
|
251
|
-
* const newSession = await sdk.auth.login(credentials, {disableAutoAuthentication:true});
|
|
252
|
-
* // Current user session will not be updated
|
|
253
|
-
* sdk.auth.set(newSession);
|
|
274
|
+
* console.log(data.session.firstName);
|
|
254
275
|
*/
|
|
255
276
|
service.login = async function(credentials, options) {
|
|
256
277
|
|
|
@@ -321,7 +342,9 @@ var QikAuth = function(qik) {
|
|
|
321
342
|
|
|
322
343
|
qik.api.post(url, credentials, postOptions).then(function(res) {
|
|
323
344
|
|
|
324
|
-
|
|
345
|
+
// A { mfa: true } response asks for a one-time code; it isn't a session,
|
|
346
|
+
// so only store real sessions
|
|
347
|
+
if (autoAuthenticate && !(res.data && res.data.mfa)) {
|
|
325
348
|
service.set(res.data);
|
|
326
349
|
}
|
|
327
350
|
|
|
@@ -337,6 +360,33 @@ var QikAuth = function(qik) {
|
|
|
337
360
|
|
|
338
361
|
///////////////////////////////////////////////////
|
|
339
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Creates a new account (POST /user/signup). Checks locally that firstName, lastName, email, password and
|
|
365
|
+
* a matching confirmPassword were given. If the email already has an account and the password matches, the
|
|
366
|
+
* person is signed in instead. With an `application` id in the credentials the account is created as an app
|
|
367
|
+
* user in that application's organisation. By default the returned session is stored and 'change' fires.
|
|
368
|
+
* @alias auth.signup
|
|
369
|
+
* @param {Object} credentials The new account's details.
|
|
370
|
+
* @param {String} credentials.firstName First name.
|
|
371
|
+
* @param {String} credentials.lastName Last name.
|
|
372
|
+
* @param {String} credentials.email Email address.
|
|
373
|
+
* @param {String} credentials.password Password.
|
|
374
|
+
* @param {String} credentials.confirmPassword Must equal password.
|
|
375
|
+
* @param {String} [credentials.application] Application id, to sign up to an application's organisation as an app user.
|
|
376
|
+
* @param {Object} [options] Options.
|
|
377
|
+
* @param {Boolean} [options.disableAutoAuthentication] Only return the response; don't store the session or fire 'change'.
|
|
378
|
+
* @param {Boolean} [options.application] Post to the current site's /qik/application/signup route (sdk.domain) instead of the API.
|
|
379
|
+
* @param {String} [options.url] Post to this URL instead.
|
|
380
|
+
* @returns {Promise<Object>} The axios response; its `data` is the new { session, token }. Rejects with { message } when a detail is missing or the passwords differ.
|
|
381
|
+
* @example
|
|
382
|
+
* const { data } = await sdk.auth.signup({
|
|
383
|
+
* firstName: 'Mickey',
|
|
384
|
+
* lastName: 'Mouse',
|
|
385
|
+
* email: 'mickey@example.com',
|
|
386
|
+
* password: '******',
|
|
387
|
+
* confirmPassword: '******',
|
|
388
|
+
* });
|
|
389
|
+
*/
|
|
340
390
|
service.signup = async function(credentials, options) {
|
|
341
391
|
|
|
342
392
|
if (!options) {
|
|
@@ -457,18 +507,16 @@ var QikAuth = function(qik) {
|
|
|
457
507
|
///////////////////////////////////////////////////
|
|
458
508
|
|
|
459
509
|
/**
|
|
510
|
+
* Looks up who a password reset token belongs to (GET /user/reset/:token), e.g. to greet them on the
|
|
511
|
+
* reset page. Reset tokens are short-lived and come from the link in a reset email.
|
|
460
512
|
* @alias auth.retrieveUserFromResetToken
|
|
461
|
-
* @
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
* @
|
|
465
|
-
* @param {Object} options Additional options for the request
|
|
513
|
+
* @param {String} resetToken The token from the reset link.
|
|
514
|
+
* @param {Object} [options] Options.
|
|
515
|
+
* @param {String} [options.url] Request this URL instead.
|
|
516
|
+
* @returns {Promise<Object>} For a dashboard user { _id, firstName, lastName, email }; for an app user the persona { _id, firstName, lastName, username, application: { title, primaryDomain } }. Rejects with 400 when the token is used up or expired.
|
|
466
517
|
* @example
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
* // Retrieve the user session by providing a reset token
|
|
471
|
-
* const user = await sdk.auth.retrieveUserFromResetToken(resetToken);
|
|
518
|
+
* const person = await sdk.auth.retrieveUserFromResetToken(token);
|
|
519
|
+
* console.log(`Choose a new password, ${person.firstName}`);
|
|
472
520
|
*/
|
|
473
521
|
service.retrieveUserFromResetToken = async function(resetToken, options) {
|
|
474
522
|
|
|
@@ -491,20 +539,19 @@ var QikAuth = function(qik) {
|
|
|
491
539
|
///////////////////////////////////////////////////
|
|
492
540
|
|
|
493
541
|
/**
|
|
542
|
+
* Sets a new password (and optionally name) using a reset token (POST /user/reset/:token). The token
|
|
543
|
+
* works once. For a dashboard user the response is a new session, which by default is stored, caches are
|
|
544
|
+
* cleared and 'change' fires; for an app user the response is { done: true } (sign in afterwards) — note the
|
|
545
|
+
* SDK currently stores that as the session too unless disableAutoAuthentication is set.
|
|
494
546
|
* @alias auth.updateUserWithToken
|
|
495
|
-
* @
|
|
496
|
-
* @param
|
|
497
|
-
* @param
|
|
498
|
-
* @param
|
|
499
|
-
* @param
|
|
500
|
-
*
|
|
501
|
-
* and instead return the result without dispatching any events
|
|
547
|
+
* @param {String} resetToken The token from the reset link.
|
|
548
|
+
* @param {Object} body The changes: { password, firstName, lastName }, plus email (dashboard users) or username (app users).
|
|
549
|
+
* @param {Object} [options] Options.
|
|
550
|
+
* @param {Boolean} [options.disableAutoAuthentication] Only return the result; don't store it or fire 'change'.
|
|
551
|
+
* @param {String} [options.url] Post to this URL instead.
|
|
552
|
+
* @returns {Promise<Object>} A new { session, token } for a dashboard user, or { done: true } for an app user.
|
|
502
553
|
* @example
|
|
503
|
-
*
|
|
504
|
-
* const resetToken = 'XXX-324623-$$...';
|
|
505
|
-
*
|
|
506
|
-
* // Retrieve the user session by providing a reset token
|
|
507
|
-
* const user = await sdk.auth.retrieveUserFromResetToken(resetToken);
|
|
554
|
+
* await sdk.auth.updateUserWithToken(token, { password: 'a new password' });
|
|
508
555
|
*/
|
|
509
556
|
service.updateUserWithToken = async function(resetToken, body, options) {
|
|
510
557
|
|
|
@@ -547,17 +594,16 @@ var QikAuth = function(qik) {
|
|
|
547
594
|
}
|
|
548
595
|
|
|
549
596
|
/**
|
|
597
|
+
* Emails the person a password reset link (POST /user/forgot). On an application's domain (or with an
|
|
598
|
+
* application in the details) the link is for that application's app users.
|
|
550
599
|
* @alias auth.sendResetPasswordRequest
|
|
551
|
-
* @
|
|
552
|
-
*
|
|
553
|
-
* @param
|
|
554
|
-
* @param
|
|
600
|
+
* @param {Object} details The request.
|
|
601
|
+
* @param {String} details.email The account's email address.
|
|
602
|
+
* @param {Object} [options] Options.
|
|
603
|
+
* @param {String} [options.url] Post to this URL instead.
|
|
604
|
+
* @returns {Promise<Object>} The axios response; for dashboard users its `data` is { done: true }. Rejects with { message } when no email is given.
|
|
555
605
|
* @example
|
|
556
|
-
*
|
|
557
|
-
* const resetToken = 'XXX-324623-$$...';
|
|
558
|
-
*
|
|
559
|
-
* // Retrieve the user session by providing a reset token
|
|
560
|
-
* const user = await sdk.auth.retrieveUserFromResetToken(resetToken);
|
|
606
|
+
* await sdk.auth.sendResetPasswordRequest({ email: 'me@example.com' });
|
|
561
607
|
*/
|
|
562
608
|
service.sendResetPasswordRequest = function(details, options) {
|
|
563
609
|
|
|
@@ -591,17 +637,15 @@ var QikAuth = function(qik) {
|
|
|
591
637
|
///////////////////////////////////////////////////
|
|
592
638
|
|
|
593
639
|
/**
|
|
640
|
+
* Makes sure the current access token is still valid, refreshing it (POST /user/refresh) when it expires
|
|
641
|
+
* within the next few seconds. Requests through sdk.api already do this automatically; call it before handing
|
|
642
|
+
* the token to something else, such as a URL or another library.
|
|
594
643
|
* @alias auth.ensureValidToken
|
|
595
|
-
* @
|
|
596
|
-
*
|
|
597
|
-
* @param {Boolean} forceRefresh Whether to force the current token to be refreshed, even if it has not yet expired.
|
|
644
|
+
* @param {Boolean} [forceRefresh] Refresh even if the token hasn't expired yet.
|
|
645
|
+
* @returns {Promise<Object|String>} The current token object { accessToken, refreshToken, expires } when it is still valid, or the new access token string after a refresh. In cookie mode, a placeholder string. Rejects when nobody is signed in.
|
|
598
646
|
* @example
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
* sdk.auth.ensureValidToken();
|
|
602
|
-
*
|
|
603
|
-
* // Force the token to be refreshed, even if the current token in use has not yet expired.
|
|
604
|
-
* sdk.auth.ensureValidToken(true);
|
|
647
|
+
* await sdk.auth.ensureValidToken();
|
|
648
|
+
* const url = `${sdk.apiURL}/file/${fileID}?access_token=${sdk.auth.getCurrentToken()}`;
|
|
605
649
|
*/
|
|
606
650
|
service.ensureValidToken = async function(forceRefresh) {
|
|
607
651
|
|
|
@@ -656,6 +700,16 @@ var QikAuth = function(qik) {
|
|
|
656
700
|
|
|
657
701
|
const refreshContext = {};
|
|
658
702
|
|
|
703
|
+
/**
|
|
704
|
+
* Exchanges the refresh token for a new access token (POST /user/refresh), stores the refreshed session
|
|
705
|
+
* and fires 'change'. Calls made while a refresh is already running share it. Usually you want
|
|
706
|
+
* ensureValidToken() instead, which only refreshes when needed.
|
|
707
|
+
* @alias auth.refreshAccessToken
|
|
708
|
+
* @param {String} [refreshToken] The refresh token (getCurrentUser().token.refreshToken). Not needed in cookie mode.
|
|
709
|
+
* @returns {Promise<String>} The new access token (in cookie mode, the string 'cookie_token_refreshed').
|
|
710
|
+
* @example
|
|
711
|
+
* const accessToken = await sdk.auth.refreshAccessToken(sdk.auth.getCurrentUser().token.refreshToken);
|
|
712
|
+
*/
|
|
659
713
|
service.refreshAccessToken = async function(refreshToken) {
|
|
660
714
|
|
|
661
715
|
//If there is already a request in progress
|
|
@@ -739,14 +793,21 @@ var QikAuth = function(qik) {
|
|
|
739
793
|
///////////////////////////////////////////////////
|
|
740
794
|
|
|
741
795
|
/**
|
|
796
|
+
* Re-reads the current session from the server (GET /user) and stores it, e.g. after the user's
|
|
797
|
+
* permissions or profile changed. If the request fails the session is cleared (signed out), unless
|
|
798
|
+
* options.keepOnError is set, in which case the signed-in user is left exactly as it was.
|
|
799
|
+
* Fires 'change' when done.
|
|
742
800
|
* @alias auth.sync
|
|
743
|
-
* @
|
|
801
|
+
* @param {Object} [options]
|
|
802
|
+
* @param {Boolean} [options.keepOnError] Keep the current user if the request fails (e.g. a network
|
|
803
|
+
* blip) instead of signing out. The socket uses this when told the person's access changed.
|
|
804
|
+
* @returns {Promise<undefined>} Resolves when the stored session has been updated.
|
|
744
805
|
* @example
|
|
745
|
-
*
|
|
746
|
-
*
|
|
747
|
-
* sdk.auth.sync();
|
|
806
|
+
* await sdk.auth.sync();
|
|
807
|
+
* const { session } = sdk.auth.getCurrentUser();
|
|
748
808
|
*/
|
|
749
|
-
service.sync = function() {
|
|
809
|
+
service.sync = function(options) {
|
|
810
|
+
options = options || {};
|
|
750
811
|
|
|
751
812
|
return qik.api.get('/user')
|
|
752
813
|
.then(function(res) {
|
|
@@ -771,6 +832,9 @@ var QikAuth = function(qik) {
|
|
|
771
832
|
dispatch();
|
|
772
833
|
})
|
|
773
834
|
.catch(function(err) {
|
|
835
|
+
if (options.keepOnError) {
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
774
838
|
service.set(null);
|
|
775
839
|
dispatch();
|
|
776
840
|
});
|
|
@@ -779,11 +843,15 @@ var QikAuth = function(qik) {
|
|
|
779
843
|
/////////////////////////////////////////////////////
|
|
780
844
|
|
|
781
845
|
/**
|
|
846
|
+
* Returns the stored session straight away (no request).
|
|
782
847
|
* @alias auth.getCurrentUser
|
|
783
|
-
* @
|
|
848
|
+
* @returns {Object|null} { session, token } when signed in, otherwise null. Pass `session` to the sdk.access helpers.
|
|
784
849
|
* @example
|
|
785
|
-
*
|
|
786
|
-
*
|
|
850
|
+
* const current = sdk.auth.getCurrentUser();
|
|
851
|
+
* if (current) {
|
|
852
|
+
* const { session } = current;
|
|
853
|
+
* console.log(session.firstName, session.organisation.title);
|
|
854
|
+
* }
|
|
787
855
|
*/
|
|
788
856
|
service.getCurrentUser = function() {
|
|
789
857
|
return storageAdapter.getUser();
|
|
@@ -791,12 +859,12 @@ var QikAuth = function(qik) {
|
|
|
791
859
|
|
|
792
860
|
|
|
793
861
|
/**
|
|
862
|
+
* Returns the access token requests are sent with: the signed-in user's token, or when nobody is signed in
|
|
863
|
+
* the application token the SDK was created with. Doesn't check expiry (see ensureValidToken).
|
|
794
864
|
* @alias auth.getCurrentToken
|
|
795
|
-
* @
|
|
796
|
-
* the response will be the current user's access token, otherwise will fall back to the
|
|
797
|
-
* applications token.
|
|
865
|
+
* @returns {String|undefined} The access token, or undefined when there is none. In cookie mode a signed-in user's token can't be read, so this is undefined for them.
|
|
798
866
|
* @example
|
|
799
|
-
* const
|
|
867
|
+
* const token = sdk.auth.getCurrentToken();
|
|
800
868
|
*/
|
|
801
869
|
service.getCurrentToken = function() {
|
|
802
870
|
|