@qikdev/sdk 0.1.161 → 0.1.163
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 +1 -1
- package/package.json +1 -1
- package/src/api/qik.access.js +750 -715
- package/src/api/qik.auth.js +740 -797
- package/src/version.js +1 -1
package/src/api/qik.auth.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import axios from
|
|
2
|
-
import { EventDispatcher } from
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { EventDispatcher } from "./qik.utils.js";
|
|
3
3
|
|
|
4
4
|
///////////////////////////////////////////////////
|
|
5
5
|
|
|
@@ -12,927 +12,870 @@ import { EventDispatcher } from './qik.utils.js';
|
|
|
12
12
|
* @param {QikAPI} 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.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
var QikAuth = function(qik) {
|
|
15
|
+
var QikAuth = function (qik) {
|
|
16
|
+
if (!qik.api) {
|
|
17
|
+
throw new Error(`Please ensure that QikAPI exists before QikAuth`);
|
|
18
|
+
}
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
//Keep track of any refresh requests
|
|
22
|
-
var inflightRefreshRequest;
|
|
20
|
+
//Keep track of any refresh requests
|
|
21
|
+
var inflightRefreshRequest;
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
///////////////////////////////////////////////////
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
var sessionStorage = {};
|
|
26
|
+
var store = sessionStorage;
|
|
27
|
+
const tokenBufferSeconds = 10;
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
///////////////////////////////////////////////////
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
const service = {
|
|
32
|
+
debug: false,
|
|
33
|
+
};
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
Object.defineProperty(service, "store", {
|
|
36
|
+
value: store,
|
|
37
|
+
writable: false,
|
|
38
|
+
});
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
//Create a new dispatcher
|
|
41
|
+
const dispatcher = new EventDispatcher();
|
|
42
|
+
dispatcher.bootstrap(service);
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
///////////////////////////////////////////////////
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
var user = store.user;
|
|
51
|
-
|
|
52
|
-
//Dispatch the change to the listeners
|
|
53
|
-
if (service.onChange) {
|
|
54
|
-
service.onChange(user);
|
|
55
|
-
}
|
|
46
|
+
function dispatch(parameters) {
|
|
47
|
+
//Get the current user
|
|
48
|
+
var user = store.user;
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
//Dispatch the change to the listeners
|
|
51
|
+
if (service.onChange) {
|
|
52
|
+
service.onChange(user);
|
|
59
53
|
}
|
|
60
54
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
55
|
+
//Dispatch the change event
|
|
56
|
+
dispatcher.dispatch("change", user, parameters);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
///////////////////////////////////////////////////
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @alias auth.set
|
|
63
|
+
* @description Manually set current user session
|
|
64
|
+
* @param {Object} user The user session object to set as the current user session
|
|
65
|
+
* @param {Object} parameters Additional parameters to dispatch
|
|
66
|
+
* @param {Boolean} stopDispatch Whether to supress dispatching a 'change' event.
|
|
67
|
+
* @example
|
|
68
|
+
*
|
|
69
|
+
* const userSession = {_id:'61eca4746971e75c1fc670cf', firstName:'Daffy', lastName:'Duck' ...};
|
|
70
|
+
* sdk.auth.set(userSession);
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
service.set = function (user, parameters, stopDispatch) {
|
|
74
|
+
if (JSON.stringify(store.user) != JSON.stringify(user)) {
|
|
75
|
+
store.user = user;
|
|
76
|
+
if (!stopDispatch) {
|
|
77
|
+
return dispatch(parameters);
|
|
78
|
+
}
|
|
85
79
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
///////////////////////////////////////////////////
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @alias auth.logout
|
|
86
|
+
* @description Clear the current user session from memory and erase all caches
|
|
87
|
+
* @example
|
|
88
|
+
* sdk.auth.logout();
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
service.logout = function () {
|
|
92
|
+
delete store.user;
|
|
93
|
+
qik.cache.reset();
|
|
94
|
+
return dispatch();
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
///////////////////////////////////////////////////
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @alias auth.changeOrganisation
|
|
101
|
+
* @description Manually set current user session
|
|
102
|
+
* @param {(String|Object)} organisation The id of the organisation to switch into
|
|
103
|
+
* @param {Object} options Additional options
|
|
104
|
+
* @param {Boolean} options.disableAutoAuthentication By default when switching organisation, the current user session
|
|
105
|
+
* will be updated to reflect a session in the new organisation, you can use this option to disable that behavior and instead return the
|
|
106
|
+
* user session without dispatching any events
|
|
107
|
+
* @example
|
|
108
|
+
*
|
|
109
|
+
* sdk.auth.changeOrganisation('61eca4746971e75c1fc670cf');
|
|
110
|
+
* // Current user session will be automatically updated
|
|
111
|
+
*
|
|
112
|
+
* const newSession = await sdk.auth.changeOrganisation('61eca4746971e75c1fc670cf', {disableAutoAuthentication:true});
|
|
113
|
+
* // Current user session will not be updated
|
|
114
|
+
* sdk.auth.set(newSession);
|
|
115
|
+
*/
|
|
116
|
+
service.changeOrganisation = function (organisationID, options) {
|
|
117
|
+
//Ensure we just have the ID
|
|
118
|
+
organisationID = qik.utils.id(organisationID);
|
|
119
|
+
|
|
120
|
+
//////////////////////////
|
|
121
|
+
|
|
122
|
+
if (!options) {
|
|
123
|
+
options = {};
|
|
101
124
|
}
|
|
102
125
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @alias auth.changeOrganisation
|
|
107
|
-
* @description Manually set current user session
|
|
108
|
-
* @param {(String|Object)} organisation The id of the organisation to switch into
|
|
109
|
-
* @param {Object} options Additional options
|
|
110
|
-
* @param {Boolean} options.disableAutoAuthentication By default when switching organisation, the current user session
|
|
111
|
-
* will be updated to reflect a session in the new organisation, you can use this option to disable that behavior and instead return the
|
|
112
|
-
* user session without dispatching any events
|
|
113
|
-
* @example
|
|
114
|
-
*
|
|
115
|
-
* sdk.auth.changeOrganisation('61eca4746971e75c1fc670cf');
|
|
116
|
-
* // Current user session will be automatically updated
|
|
117
|
-
*
|
|
118
|
-
* const newSession = await sdk.auth.changeOrganisation('61eca4746971e75c1fc670cf', {disableAutoAuthentication:true});
|
|
119
|
-
* // Current user session will not be updated
|
|
120
|
-
* sdk.auth.set(newSession);
|
|
121
|
-
*/
|
|
122
|
-
service.changeOrganisation = function(organisationID, options) {
|
|
123
|
-
|
|
124
|
-
//Ensure we just have the ID
|
|
125
|
-
organisationID = qik.utils.id(organisationID);
|
|
126
|
-
|
|
127
|
-
//////////////////////////
|
|
128
|
-
|
|
129
|
-
if (!options) {
|
|
130
|
-
options = {};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
//////////////////////////
|
|
126
|
+
//////////////////////////
|
|
134
127
|
|
|
135
|
-
|
|
136
|
-
|
|
128
|
+
//Change the users current tokens straight away
|
|
129
|
+
var autoAuthenticate = true;
|
|
137
130
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
//////////////////////////
|
|
143
|
-
|
|
144
|
-
return new Promise(function(resolve, reject) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
qik.api.post(`/user/switch/${organisationID}`)
|
|
148
|
-
.then(function(response) {
|
|
131
|
+
if (options.disableAutoAuthentication) {
|
|
132
|
+
autoAuthenticate = false;
|
|
133
|
+
}
|
|
149
134
|
|
|
150
|
-
|
|
151
|
-
qik.cache.reset();
|
|
152
|
-
service.set(response.data);
|
|
153
|
-
}
|
|
135
|
+
//////////////////////////
|
|
154
136
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
137
|
+
return new Promise(function (resolve, reject) {
|
|
138
|
+
qik.api
|
|
139
|
+
.post(`/user/switch/${organisationID}`)
|
|
140
|
+
.then(function (response) {
|
|
141
|
+
if (autoAuthenticate) {
|
|
142
|
+
qik.cache.reset();
|
|
143
|
+
service.set(response.data);
|
|
144
|
+
}
|
|
158
145
|
|
|
146
|
+
resolve(response.data);
|
|
159
147
|
})
|
|
148
|
+
.catch(reject);
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
///////////////////////////////////////////////////
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @alias auth.impersonate
|
|
156
|
+
* @description Impersonate another user within your organisation
|
|
157
|
+
* @param {(String|Object)} persona The id of the user persona you want to impersonate
|
|
158
|
+
* @param {Object} options Additional options
|
|
159
|
+
* @param {Boolean} options.disableAutoAuthentication By default when impersonating a user, the current user session
|
|
160
|
+
* will be updated automatically to reflect the new session, you can use this option to disable that behavior and instead return the
|
|
161
|
+
* new impersonation user session without dispatching any events
|
|
162
|
+
* @example
|
|
163
|
+
*
|
|
164
|
+
* sdk.auth.impersonate('61eca4746971e75c1fc670cf');
|
|
165
|
+
* // Current user session will be automatically updated
|
|
166
|
+
*
|
|
167
|
+
* const newSession = await sdk.auth.impersonate('61eca4746971e75c1fc670cf', {disableAutoAuthentication:true});
|
|
168
|
+
* // Current user session will not be updated
|
|
169
|
+
* sdk.auth.set(newSession);
|
|
170
|
+
*/
|
|
171
|
+
service.impersonate = function (personaID, options) {
|
|
172
|
+
//Ensure we just have the ID
|
|
173
|
+
personaID = qik.utils.id(personaID);
|
|
174
|
+
|
|
175
|
+
//////////////////////////
|
|
176
|
+
|
|
177
|
+
if (!options) {
|
|
178
|
+
options = {};
|
|
160
179
|
}
|
|
161
180
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* @alias auth.impersonate
|
|
166
|
-
* @description Impersonate another user within your organisation
|
|
167
|
-
* @param {(String|Object)} persona The id of the user persona you want to impersonate
|
|
168
|
-
* @param {Object} options Additional options
|
|
169
|
-
* @param {Boolean} options.disableAutoAuthentication By default when impersonating a user, the current user session
|
|
170
|
-
* will be updated automatically to reflect the new session, you can use this option to disable that behavior and instead return the
|
|
171
|
-
* new impersonation user session without dispatching any events
|
|
172
|
-
* @example
|
|
173
|
-
*
|
|
174
|
-
* sdk.auth.impersonate('61eca4746971e75c1fc670cf');
|
|
175
|
-
* // Current user session will be automatically updated
|
|
176
|
-
*
|
|
177
|
-
* const newSession = await sdk.auth.impersonate('61eca4746971e75c1fc670cf', {disableAutoAuthentication:true});
|
|
178
|
-
* // Current user session will not be updated
|
|
179
|
-
* sdk.auth.set(newSession);
|
|
180
|
-
*/
|
|
181
|
-
service.impersonate = function(personaID, options) {
|
|
182
|
-
|
|
183
|
-
//Ensure we just have the ID
|
|
184
|
-
personaID = qik.utils.id(personaID);
|
|
185
|
-
|
|
186
|
-
//////////////////////////
|
|
187
|
-
|
|
188
|
-
if (!options) {
|
|
189
|
-
options = {};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
//////////////////////////
|
|
193
|
-
|
|
194
|
-
//Change the users current tokens straight away
|
|
195
|
-
var autoAuthenticate = true;
|
|
196
|
-
|
|
197
|
-
if (options.disableAutoAuthentication) {
|
|
198
|
-
autoAuthenticate = false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
//////////////////////////
|
|
202
|
-
|
|
203
|
-
var promise = qik.api.post(`/user/impersonate/${personaID}`)
|
|
181
|
+
//////////////////////////
|
|
204
182
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (autoAuthenticate) {
|
|
208
|
-
qik.cache.reset();
|
|
209
|
-
service.set(res.data);
|
|
210
|
-
}
|
|
211
|
-
}, function(err) {});
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return promise;
|
|
183
|
+
//Change the users current tokens straight away
|
|
184
|
+
var autoAuthenticate = true;
|
|
215
185
|
|
|
186
|
+
if (options.disableAutoAuthentication) {
|
|
187
|
+
autoAuthenticate = false;
|
|
216
188
|
}
|
|
217
189
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* @alias auth.login
|
|
222
|
-
* @description Login and authenticate as a user
|
|
223
|
-
* @param {Object} credentials The credentials used to login
|
|
224
|
-
* @param {String} credentials.email The email address to login to
|
|
225
|
-
* @param {String} credentials.password The password to login with
|
|
226
|
-
* @param {String} credentials.mfa The MFA (Multi Factor Authentication) code
|
|
227
|
-
* @param {Object} options Additional options
|
|
228
|
-
* @param {Boolean} options.disableAutoAuthentication By default when logging in the current user session
|
|
229
|
-
* will be updated automatically to reflect the new session, you can use this option to disable that behavior and instead return the
|
|
230
|
-
* session that was logged in to without dispatching any events
|
|
231
|
-
* @example
|
|
232
|
-
*
|
|
233
|
-
* const credentials = {
|
|
234
|
-
* email:'me@email.com',
|
|
235
|
-
* password:'******',
|
|
236
|
-
* mfa:'1234',
|
|
237
|
-
* }
|
|
238
|
-
*
|
|
239
|
-
* sdk.auth.login(credentials);
|
|
240
|
-
* // Current user session will be automatically updated
|
|
241
|
-
*
|
|
242
|
-
* const newSession = await sdk.auth.login(credentials, {disableAutoAuthentication:true});
|
|
243
|
-
* // Current user session will not be updated
|
|
244
|
-
* sdk.auth.set(newSession);
|
|
245
|
-
*/
|
|
246
|
-
service.login = async function(credentials, options) {
|
|
247
|
-
|
|
248
|
-
if (!options) {
|
|
249
|
-
options = {};
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
//////////////////////////
|
|
190
|
+
//////////////////////////
|
|
253
191
|
|
|
254
|
-
|
|
255
|
-
var autoAuthenticate = true;
|
|
192
|
+
var promise = qik.api.post(`/user/impersonate/${personaID}`);
|
|
256
193
|
|
|
257
|
-
|
|
258
|
-
|
|
194
|
+
promise.then(
|
|
195
|
+
function (res) {
|
|
196
|
+
if (autoAuthenticate) {
|
|
197
|
+
qik.cache.reset();
|
|
198
|
+
service.set(res.data);
|
|
259
199
|
}
|
|
200
|
+
},
|
|
201
|
+
function (err) {},
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
return promise;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
///////////////////////////////////////////////////
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @alias auth.login
|
|
211
|
+
* @description Login and authenticate as a user
|
|
212
|
+
* @param {Object} credentials The credentials used to login
|
|
213
|
+
* @param {String} credentials.email The email address to login to
|
|
214
|
+
* @param {String} credentials.password The password to login with
|
|
215
|
+
* @param {String} credentials.mfa The MFA (Multi Factor Authentication) code
|
|
216
|
+
* @param {Object} options Additional options
|
|
217
|
+
* @param {Boolean} options.disableAutoAuthentication By default when logging in the current user session
|
|
218
|
+
* will be updated automatically to reflect the new session, you can use this option to disable that behavior and instead return the
|
|
219
|
+
* session that was logged in to without dispatching any events
|
|
220
|
+
* @example
|
|
221
|
+
*
|
|
222
|
+
* const credentials = {
|
|
223
|
+
* email:'me@email.com',
|
|
224
|
+
* password:'******',
|
|
225
|
+
* mfa:'1234',
|
|
226
|
+
* }
|
|
227
|
+
*
|
|
228
|
+
* sdk.auth.login(credentials);
|
|
229
|
+
* // Current user session will be automatically updated
|
|
230
|
+
*
|
|
231
|
+
* const newSession = await sdk.auth.login(credentials, {disableAutoAuthentication:true});
|
|
232
|
+
* // Current user session will not be updated
|
|
233
|
+
* sdk.auth.set(newSession);
|
|
234
|
+
*/
|
|
235
|
+
service.login = async function (credentials, options) {
|
|
236
|
+
if (!options) {
|
|
237
|
+
options = {};
|
|
238
|
+
}
|
|
260
239
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
var promise = new Promise(loginCheck)
|
|
240
|
+
//////////////////////////
|
|
264
241
|
|
|
265
|
-
|
|
242
|
+
//Change the users current tokens straight away
|
|
243
|
+
var autoAuthenticate = true;
|
|
266
244
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
})
|
|
271
|
-
}
|
|
245
|
+
if (options.disableAutoAuthentication) {
|
|
246
|
+
autoAuthenticate = false;
|
|
247
|
+
}
|
|
272
248
|
|
|
273
|
-
|
|
274
|
-
return reject({
|
|
275
|
-
message: 'Username was not provided',
|
|
276
|
-
})
|
|
277
|
-
}
|
|
249
|
+
//////////////////////////////////////
|
|
278
250
|
|
|
279
|
-
|
|
280
|
-
return reject({
|
|
281
|
-
message: 'Password was not provided',
|
|
282
|
-
})
|
|
283
|
-
}
|
|
251
|
+
var promise = new Promise(loginCheck);
|
|
284
252
|
|
|
285
|
-
|
|
253
|
+
function loginCheck(resolve, reject) {
|
|
254
|
+
if (!credentials) {
|
|
255
|
+
return reject({
|
|
256
|
+
message: "Missing credentials!",
|
|
257
|
+
});
|
|
258
|
+
}
|
|
286
259
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
260
|
+
if (!credentials.email || !credentials.email.length) {
|
|
261
|
+
return reject({
|
|
262
|
+
message: "Username was not provided",
|
|
263
|
+
});
|
|
264
|
+
}
|
|
290
265
|
|
|
291
|
-
|
|
266
|
+
if (!credentials.password || !credentials.password.length) {
|
|
267
|
+
return reject({
|
|
268
|
+
message: "Password was not provided",
|
|
269
|
+
});
|
|
270
|
+
}
|
|
292
271
|
|
|
293
|
-
|
|
272
|
+
/////////////////////////////////////////////
|
|
294
273
|
|
|
295
|
-
|
|
274
|
+
var postOptions = {
|
|
275
|
+
bypassInterceptor: true,
|
|
276
|
+
};
|
|
296
277
|
|
|
297
|
-
|
|
298
|
-
if (options.url) {
|
|
299
|
-
url = options.url;
|
|
300
|
-
}
|
|
278
|
+
/////////////////////////////////////////////
|
|
301
279
|
|
|
302
|
-
|
|
280
|
+
var url = `${qik.apiURL}/user/login`;
|
|
303
281
|
|
|
304
|
-
|
|
282
|
+
/////////////////////////////////////////////
|
|
305
283
|
|
|
306
|
-
|
|
307
|
-
|
|
284
|
+
//If we have a specified url
|
|
285
|
+
if (options.url) {
|
|
286
|
+
url = options.url;
|
|
287
|
+
}
|
|
308
288
|
|
|
309
|
-
|
|
289
|
+
/////////////////////////////////////////////
|
|
310
290
|
|
|
311
|
-
|
|
312
|
-
|
|
291
|
+
qik.api.post(url, credentials, postOptions).then(function (res) {
|
|
292
|
+
if (autoAuthenticate) {
|
|
293
|
+
service.set(res.data);
|
|
313
294
|
}
|
|
314
295
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return promise;
|
|
318
|
-
|
|
296
|
+
resolve(res);
|
|
297
|
+
}, reject);
|
|
319
298
|
}
|
|
320
299
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
service.signup = async function(credentials, options) {
|
|
324
|
-
|
|
325
|
-
if (!options) {
|
|
326
|
-
options = {};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
//////////////////////////
|
|
300
|
+
//////////////////////////////////////
|
|
331
301
|
|
|
332
|
-
|
|
333
|
-
|
|
302
|
+
return promise;
|
|
303
|
+
};
|
|
334
304
|
|
|
335
|
-
|
|
336
|
-
autoAuthenticate = false;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
//////////////////////////////////////
|
|
305
|
+
///////////////////////////////////////////////////
|
|
340
306
|
|
|
341
|
-
|
|
307
|
+
service.signup = async function (credentials, options) {
|
|
308
|
+
if (!options) {
|
|
309
|
+
options = {};
|
|
310
|
+
}
|
|
342
311
|
|
|
343
|
-
|
|
312
|
+
//////////////////////////
|
|
344
313
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
message: 'No details provided',
|
|
348
|
-
})
|
|
349
|
-
}
|
|
314
|
+
//Change the users current tokens straight away
|
|
315
|
+
var autoAuthenticate = true;
|
|
350
316
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
})
|
|
355
|
-
}
|
|
317
|
+
if (options.disableAutoAuthentication) {
|
|
318
|
+
autoAuthenticate = false;
|
|
319
|
+
}
|
|
356
320
|
|
|
357
|
-
|
|
358
|
-
return reject({
|
|
359
|
-
message: 'Last Name was not provided',
|
|
360
|
-
})
|
|
361
|
-
}
|
|
321
|
+
//////////////////////////////////////
|
|
362
322
|
|
|
363
|
-
|
|
364
|
-
return reject({
|
|
365
|
-
message: 'Email/Username was not provided',
|
|
366
|
-
})
|
|
367
|
-
}
|
|
323
|
+
var promise = new Promise(signupCheck);
|
|
368
324
|
|
|
325
|
+
function signupCheck(resolve, reject) {
|
|
326
|
+
if (!credentials) {
|
|
327
|
+
return reject({
|
|
328
|
+
message: "No details provided",
|
|
329
|
+
});
|
|
330
|
+
}
|
|
369
331
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
332
|
+
if (!credentials.firstName || !credentials.firstName.length) {
|
|
333
|
+
return reject({
|
|
334
|
+
message: "First Name was not provided",
|
|
335
|
+
});
|
|
336
|
+
}
|
|
375
337
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
338
|
+
if (!credentials.lastName || !credentials.lastName.length) {
|
|
339
|
+
return reject({
|
|
340
|
+
message: "Last Name was not provided",
|
|
341
|
+
});
|
|
342
|
+
}
|
|
381
343
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
344
|
+
if (!credentials.email || !credentials.email.length) {
|
|
345
|
+
return reject({
|
|
346
|
+
message: "Email/Username was not provided",
|
|
347
|
+
});
|
|
348
|
+
}
|
|
387
349
|
|
|
388
|
-
|
|
350
|
+
if (!credentials.password || !credentials.password.length) {
|
|
351
|
+
return reject({
|
|
352
|
+
message: "Password was not provided",
|
|
353
|
+
});
|
|
354
|
+
}
|
|
389
355
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
356
|
+
if (!credentials.confirmPassword || !credentials.confirmPassword.length) {
|
|
357
|
+
return reject({
|
|
358
|
+
message: "Confirm Password was not provided",
|
|
359
|
+
});
|
|
360
|
+
}
|
|
393
361
|
|
|
394
|
-
|
|
362
|
+
if (credentials.confirmPassword != credentials.password) {
|
|
363
|
+
return reject({
|
|
364
|
+
message: "Your passwords do not match",
|
|
365
|
+
});
|
|
366
|
+
}
|
|
395
367
|
|
|
396
|
-
|
|
368
|
+
/////////////////////////////////////////////
|
|
397
369
|
|
|
398
|
-
|
|
370
|
+
var postOptions = {
|
|
371
|
+
bypassInterceptor: true,
|
|
372
|
+
};
|
|
399
373
|
|
|
400
|
-
|
|
401
|
-
if (options.application) {
|
|
374
|
+
/////////////////////////////////////////////
|
|
402
375
|
|
|
403
|
-
|
|
404
|
-
url = `${qik.domain || ''}/qik/application/signup`;
|
|
405
|
-
}
|
|
376
|
+
var url = `${qik.apiURL}/user/signup`;
|
|
406
377
|
|
|
407
|
-
|
|
408
|
-
if (options.url) {
|
|
409
|
-
url = options.url;
|
|
410
|
-
}
|
|
378
|
+
/////////////////////////////////////////////
|
|
411
379
|
|
|
412
|
-
|
|
380
|
+
//If we are authenticating as an application
|
|
381
|
+
if (options.application) {
|
|
382
|
+
//The url is relative to the domain
|
|
383
|
+
url = `${qik.domain || ""}/qik/application/signup`;
|
|
384
|
+
}
|
|
413
385
|
|
|
414
|
-
|
|
386
|
+
//If we have a specified url
|
|
387
|
+
if (options.url) {
|
|
388
|
+
url = options.url;
|
|
389
|
+
}
|
|
415
390
|
|
|
416
|
-
|
|
417
|
-
service.set(res.data);
|
|
418
|
-
}
|
|
391
|
+
/////////////////////////////////////////////
|
|
419
392
|
|
|
420
|
-
|
|
421
|
-
|
|
393
|
+
qik.api.post(url, credentials, postOptions).then(function (res) {
|
|
394
|
+
if (autoAuthenticate) {
|
|
395
|
+
service.set(res.data);
|
|
422
396
|
}
|
|
423
397
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
return promise;
|
|
427
|
-
|
|
398
|
+
resolve(res);
|
|
399
|
+
}, reject);
|
|
428
400
|
}
|
|
429
401
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
bypassInterceptor: true
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
return new Promise(function(resolve, reject) {
|
|
458
|
-
qik.api.get(options.url || `${qik.apiURL}/user/reset/${resetToken}`, postOptions).then(function(res) {
|
|
459
|
-
return resolve(res.data);
|
|
460
|
-
}, reject);
|
|
461
|
-
});
|
|
462
|
-
|
|
402
|
+
//////////////////////////////////////
|
|
403
|
+
|
|
404
|
+
return promise;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
///////////////////////////////////////////////////
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @alias auth.retrieveUserFromResetToken
|
|
411
|
+
* @description Retrieve user session through use of a valid reset token,
|
|
412
|
+
* Reset tokens are short lived tokens that can be generated when a user has forgotten their password or their
|
|
413
|
+
* password has been reset by an administrator
|
|
414
|
+
* @param {String} resetToken The token to use to authenticate
|
|
415
|
+
* @param {Object} options Additional options for the request
|
|
416
|
+
* @example
|
|
417
|
+
*
|
|
418
|
+
* const resetToken = 'XXX-324623-$$...';
|
|
419
|
+
*
|
|
420
|
+
* // Retrieve the user session by providing a reset token
|
|
421
|
+
* const user = await sdk.auth.retrieveUserFromResetToken(resetToken);
|
|
422
|
+
*/
|
|
423
|
+
service.retrieveUserFromResetToken = async function (resetToken, options) {
|
|
424
|
+
if (!options) {
|
|
425
|
+
options = {};
|
|
463
426
|
}
|
|
464
427
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
var postOptions = {
|
|
503
|
-
bypassInterceptor: true
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
qik.api.post(options.url || `${qik.apiURL}/user/reset/${resetToken}`, body, postOptions)
|
|
507
|
-
.then(function(res) {
|
|
508
|
-
|
|
509
|
-
//If we should automatically authenticate
|
|
510
|
-
//once the request is successful
|
|
511
|
-
//Then clear caches and update the session
|
|
512
|
-
if (autoAuthenticate) {
|
|
513
|
-
qik.cache.reset();
|
|
514
|
-
service.set(res.data);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
return resolve(res.data);
|
|
518
|
-
}, reject);
|
|
519
|
-
});
|
|
520
|
-
|
|
428
|
+
var postOptions = {
|
|
429
|
+
bypassInterceptor: true,
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
return new Promise(function (resolve, reject) {
|
|
433
|
+
qik.api
|
|
434
|
+
.get(
|
|
435
|
+
options.url || `${qik.apiURL}/user/reset/${resetToken}`,
|
|
436
|
+
postOptions,
|
|
437
|
+
)
|
|
438
|
+
.then(function (res) {
|
|
439
|
+
return resolve(res.data);
|
|
440
|
+
}, reject);
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
///////////////////////////////////////////////////
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* @alias auth.updateUserWithToken
|
|
448
|
+
* @description Update a user's credentials through use of a reset token
|
|
449
|
+
* @param {String} resetToken The token to use to authenticate
|
|
450
|
+
* @param {Object} body Updates to be made to the user
|
|
451
|
+
* @param {Object} options Additional options for the request
|
|
452
|
+
* @param {Boolean} options.disableAutoAuthentication By default the current user session
|
|
453
|
+
* will be updated automatically to reflect the new updated session, you can use this option to disable that behavior
|
|
454
|
+
* and instead return the result without dispatching any events
|
|
455
|
+
* @example
|
|
456
|
+
*
|
|
457
|
+
* const resetToken = 'XXX-324623-$$...';
|
|
458
|
+
*
|
|
459
|
+
* // Retrieve the user session by providing a reset token
|
|
460
|
+
* const user = await sdk.auth.retrieveUserFromResetToken(resetToken);
|
|
461
|
+
*/
|
|
462
|
+
service.updateUserWithToken = async function (resetToken, body, options) {
|
|
463
|
+
if (!options) {
|
|
464
|
+
options = {};
|
|
521
465
|
}
|
|
522
466
|
|
|
523
|
-
|
|
524
|
-
* @alias auth.sendResetPasswordRequest
|
|
525
|
-
* @description This function allows a reset token to be generated and emailed to the requesting user
|
|
526
|
-
* allowing them to modify their user details
|
|
527
|
-
* @param {Object} body Details for the reset request
|
|
528
|
-
* @param {String} body.email The email of the user to generate a token for
|
|
529
|
-
* @example
|
|
530
|
-
*
|
|
531
|
-
* const resetToken = 'XXX-324623-$$...';
|
|
532
|
-
*
|
|
533
|
-
* // Retrieve the user session by providing a reset token
|
|
534
|
-
* const user = await sdk.auth.retrieveUserFromResetToken(resetToken);
|
|
535
|
-
*/
|
|
536
|
-
service.sendResetPasswordRequest = function(details, options) {
|
|
537
|
-
|
|
538
|
-
if (!options) {
|
|
539
|
-
options = {};
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
if (!details) {
|
|
543
|
-
return Promise.reject({
|
|
544
|
-
message: 'No details were provided for password reset request',
|
|
545
|
-
})
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
if (!details.email || !details.email.length) {
|
|
549
|
-
return Promise.reject({
|
|
550
|
-
message: 'Email is required but was not provided',
|
|
551
|
-
})
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
return new Promise(function(resolve, reject) {
|
|
467
|
+
//////////////////////////
|
|
555
468
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
}
|
|
469
|
+
//Change the users current tokens straight away
|
|
470
|
+
var autoAuthenticate = true;
|
|
559
471
|
|
|
560
|
-
|
|
561
|
-
|
|
472
|
+
if (options.disableAutoAuthentication) {
|
|
473
|
+
autoAuthenticate = false;
|
|
562
474
|
}
|
|
563
475
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
if (forceRefresh) {
|
|
608
|
-
console.log('force refresh valid token', token.refreshToken)
|
|
609
|
-
return await service.refreshAccessToken(token.refreshToken);
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
//If the token is still fresh
|
|
613
|
-
if (now < expires) {
|
|
614
|
-
|
|
615
|
-
return token;
|
|
616
|
-
} else {
|
|
617
|
-
|
|
618
|
-
return await service.refreshAccessToken(token.refreshToken);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
|
|
476
|
+
//////////////////////////////////////
|
|
477
|
+
|
|
478
|
+
return new Promise(function (resolve, reject) {
|
|
479
|
+
var postOptions = {
|
|
480
|
+
bypassInterceptor: true,
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
qik.api
|
|
484
|
+
.post(
|
|
485
|
+
options.url || `${qik.apiURL}/user/reset/${resetToken}`,
|
|
486
|
+
body,
|
|
487
|
+
postOptions,
|
|
488
|
+
)
|
|
489
|
+
.then(function (res) {
|
|
490
|
+
//If we should automatically authenticate
|
|
491
|
+
//once the request is successful
|
|
492
|
+
//Then clear caches and update the session
|
|
493
|
+
if (autoAuthenticate) {
|
|
494
|
+
qik.cache.reset();
|
|
495
|
+
service.set(res.data);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return resolve(res.data);
|
|
499
|
+
}, reject);
|
|
500
|
+
});
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* @alias auth.sendResetPasswordRequest
|
|
505
|
+
* @description This function allows a reset token to be generated and emailed to the requesting user
|
|
506
|
+
* allowing them to modify their user details
|
|
507
|
+
* @param {Object} body Details for the reset request
|
|
508
|
+
* @param {String} body.email The email of the user to generate a token for
|
|
509
|
+
* @example
|
|
510
|
+
*
|
|
511
|
+
* const resetToken = 'XXX-324623-$$...';
|
|
512
|
+
*
|
|
513
|
+
* // Retrieve the user session by providing a reset token
|
|
514
|
+
* const user = await sdk.auth.retrieveUserFromResetToken(resetToken);
|
|
515
|
+
*/
|
|
516
|
+
service.sendResetPasswordRequest = function (details, options) {
|
|
517
|
+
if (!options) {
|
|
518
|
+
options = {};
|
|
622
519
|
}
|
|
623
520
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
service.refreshAccessToken = async function(refreshToken) {
|
|
629
|
-
|
|
630
|
-
// /////////////////////////////////////////////
|
|
631
|
-
|
|
632
|
-
// if (appContext) {
|
|
633
|
-
|
|
634
|
-
// } else {
|
|
635
|
-
|
|
636
|
-
// }
|
|
637
|
-
|
|
638
|
-
// /////////////////////////////////////////////
|
|
639
|
-
|
|
640
|
-
//If there is already a request in progress
|
|
641
|
-
if (refreshContext.inflightRefreshRequest) {
|
|
642
|
-
|
|
643
|
-
return refreshContext.inflightRefreshRequest;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
/////////////////////////////////////////////////////
|
|
647
|
-
|
|
648
|
-
//Create an refresh request
|
|
649
|
-
|
|
650
|
-
refreshContext.inflightRefreshRequest = new Promise(function(resolve, reject) {
|
|
651
|
-
|
|
652
|
-
//Bypass the interceptor on all token refresh calls
|
|
653
|
-
//Because we don't need to add the access token etc onto it
|
|
654
|
-
|
|
655
|
-
qik.api.post(`/user/refresh`, {
|
|
656
|
-
refreshToken: refreshToken
|
|
657
|
-
}, {
|
|
658
|
-
bypassInterceptor: true,
|
|
659
|
-
withoutToken: true,
|
|
660
|
-
})
|
|
661
|
-
.then(function tokenRefreshComplete(res) {
|
|
662
|
-
|
|
663
|
-
//Update the user with any changes
|
|
664
|
-
//returned back from the refresh request
|
|
665
|
-
if (!res) {
|
|
666
|
-
|
|
667
|
-
refreshContext.inflightRefreshRequest = null;
|
|
668
|
-
return reject();
|
|
669
|
-
|
|
670
|
-
} else {
|
|
671
|
-
//Update with our new session
|
|
672
|
-
service.set(res.data);
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
dispatch();
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
//Resolve with the new token
|
|
679
|
-
resolve(res.data.token);
|
|
680
|
-
|
|
681
|
-
//Remove the inflight request
|
|
682
|
-
setTimeout(function() {
|
|
683
|
-
refreshContext.inflightRefreshRequest = null;
|
|
684
|
-
})
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
})
|
|
688
|
-
.catch(function(err) {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
//TODO Check if invalid_refresh_token
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
setTimeout(function() {
|
|
696
|
-
refreshContext.inflightRefreshRequest = null;
|
|
697
|
-
});
|
|
698
|
-
reject(err);
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
});
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
//Return the refresh request
|
|
706
|
-
return refreshContext.inflightRefreshRequest;
|
|
521
|
+
if (!details) {
|
|
522
|
+
return Promise.reject({
|
|
523
|
+
message: "No details were provided for password reset request",
|
|
524
|
+
});
|
|
707
525
|
}
|
|
708
526
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* @alias auth.sync
|
|
715
|
-
* @description A useful function to sync the current user session with the server.
|
|
716
|
-
* @example
|
|
717
|
-
*
|
|
718
|
-
* // Makes request to the API and updates the current user session to match the response
|
|
719
|
-
* sdk.auth.sync();
|
|
720
|
-
*/
|
|
721
|
-
service.sync = function() {
|
|
722
|
-
|
|
723
|
-
return qik.api.get('/user')
|
|
724
|
-
.then(function(res) {
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
if (res.data) {
|
|
728
|
-
if (store.user) {
|
|
729
|
-
Object.assign(store.user.session, res.data);
|
|
730
|
-
}
|
|
731
|
-
} else {
|
|
732
|
-
service.set(null);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
retryCount = 0;
|
|
737
|
-
|
|
738
|
-
dispatch();
|
|
739
|
-
})
|
|
740
|
-
.catch(function(err) {
|
|
741
|
-
|
|
742
|
-
// if (retryCount > 2) {
|
|
743
|
-
service.set(null);
|
|
744
|
-
retryCount = 0;
|
|
745
|
-
dispatch();
|
|
746
|
-
// } else {
|
|
747
|
-
|
|
748
|
-
// retryCount++;
|
|
749
|
-
// service.sync();
|
|
750
|
-
// }
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
});
|
|
527
|
+
if (!details.email || !details.email.length) {
|
|
528
|
+
return Promise.reject({
|
|
529
|
+
message: "Email is required but was not provided",
|
|
530
|
+
});
|
|
754
531
|
}
|
|
755
532
|
|
|
756
|
-
|
|
533
|
+
return new Promise(function (resolve, reject) {
|
|
534
|
+
var postOptions = {
|
|
535
|
+
bypassInterceptor: true,
|
|
536
|
+
};
|
|
757
537
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
538
|
+
qik.api
|
|
539
|
+
.post(options.url || `${qik.apiURL}/user/forgot`, details, postOptions)
|
|
540
|
+
.then(resolve, reject);
|
|
541
|
+
});
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
///////////////////////////////////////////////////
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* @alias auth.ensureValidToken
|
|
548
|
+
* @description This function forces a check to ensure that the current access token has not expired.
|
|
549
|
+
* If the token has expired, the user session will be refreshed with a new token.
|
|
550
|
+
* @param {Boolean} forceRefresh Whether to force the current token to be refreshed, even if it has not yet expired.
|
|
551
|
+
* @example
|
|
552
|
+
*
|
|
553
|
+
* // Check to ensure that the current access token is valid
|
|
554
|
+
* sdk.auth.ensureValidToken();
|
|
555
|
+
*
|
|
556
|
+
* // Force the token to be refreshed, even if the current token in use has not yet expired.
|
|
557
|
+
* sdk.auth.ensureValidToken(true);
|
|
558
|
+
*/
|
|
559
|
+
service.ensureValidToken = async function (forceRefresh) {
|
|
560
|
+
var currentUser = service.getCurrentUser();
|
|
561
|
+
if (!currentUser) {
|
|
562
|
+
return Promise.reject("No user");
|
|
767
563
|
}
|
|
768
564
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
* @description Retrieves the current access token. If the user is authenticated
|
|
773
|
-
* the response will be the current user's access token, otherwise will fall back to the
|
|
774
|
-
* applications token.
|
|
775
|
-
* @example
|
|
776
|
-
* const currentAccessToken = sdk.auth.getCurrentToken();
|
|
777
|
-
*/
|
|
778
|
-
service.getCurrentToken = function() {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
var user = service.getCurrentUser();
|
|
782
|
-
|
|
783
|
-
//User is not logged in
|
|
784
|
-
if (!user) {
|
|
785
|
-
|
|
786
|
-
//But there is an application token
|
|
787
|
-
if (qik.applicationToken) {
|
|
788
|
-
//use that instead
|
|
789
|
-
return qik.applicationToken;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
//No token
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
var { token } = user;
|
|
797
|
-
if (!token) {
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
return token.accessToken;
|
|
802
|
-
|
|
565
|
+
var { token } = currentUser;
|
|
566
|
+
if (!token) {
|
|
567
|
+
return Promise.reject("No token");
|
|
803
568
|
}
|
|
804
569
|
|
|
805
570
|
/////////////////////////////////////////////////////
|
|
806
571
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
//If we want to bypass the interceptor
|
|
810
|
-
//then just return the request
|
|
811
|
-
if (config.bypassInterceptor) {
|
|
812
|
-
return config;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
//////////////////////////////
|
|
816
|
-
|
|
817
|
-
//Get the original request
|
|
818
|
-
var originalRequest = config;
|
|
819
|
-
|
|
820
|
-
//////////////////////////////
|
|
572
|
+
//Check our date
|
|
573
|
+
var now = new Date();
|
|
821
574
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
var expiryDate;
|
|
575
|
+
//Give us a bit of buffer so that the backend doesn't beat us to
|
|
576
|
+
//retiring the token
|
|
577
|
+
now.setSeconds(now.getSeconds() + tokenBufferSeconds);
|
|
826
578
|
|
|
827
|
-
|
|
828
|
-
var { token } = userDetails;
|
|
829
|
-
if (token) {
|
|
830
|
-
accessToken = token.accessToken;
|
|
831
|
-
refreshToken = token.refreshToken;
|
|
832
|
-
expiryDate = token.expires;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
//////////////////////////////
|
|
837
|
-
|
|
838
|
-
//If there is a user token
|
|
839
|
-
if (accessToken) {
|
|
840
|
-
//Set the token of the request as the user's access token
|
|
841
|
-
originalRequest.headers['Authorization'] = `Bearer ${accessToken}`;
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
} else {
|
|
845
|
-
//Return the original request without a token
|
|
846
|
-
|
|
847
|
-
return originalRequest;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
/////////////////////////////////////////////////////
|
|
851
|
-
|
|
852
|
-
//If no refresh token
|
|
853
|
-
if (!refreshToken) {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
//Continue with the original request
|
|
857
|
-
return originalRequest;
|
|
858
|
-
}
|
|
579
|
+
/////////////////////////////////////////////////////
|
|
859
580
|
|
|
860
|
-
|
|
581
|
+
var expires = new Date(token.expires);
|
|
861
582
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
583
|
+
if (forceRefresh) {
|
|
584
|
+
console.log("force refresh valid token", token.refreshToken);
|
|
585
|
+
return await service.refreshAccessToken(token.refreshToken);
|
|
586
|
+
}
|
|
865
587
|
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
588
|
+
//If the token is still fresh
|
|
589
|
+
if (now < expires) {
|
|
590
|
+
return token;
|
|
591
|
+
} else {
|
|
592
|
+
return await service.refreshAccessToken(token.refreshToken);
|
|
593
|
+
}
|
|
594
|
+
};
|
|
869
595
|
|
|
870
|
-
|
|
596
|
+
///////////////////////////////////////////////////
|
|
871
597
|
|
|
872
|
-
|
|
598
|
+
const refreshContext = {};
|
|
873
599
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
//Return the original request
|
|
877
|
-
return originalRequest;
|
|
878
|
-
}
|
|
600
|
+
service.refreshAccessToken = async function (refreshToken) {
|
|
601
|
+
// /////////////////////////////////////////////
|
|
879
602
|
|
|
880
|
-
|
|
603
|
+
// if (appContext) {
|
|
881
604
|
|
|
882
|
-
|
|
605
|
+
// } else {
|
|
883
606
|
|
|
884
|
-
|
|
885
|
-
await service.refreshAccessToken(refreshToken)
|
|
886
|
-
.then(function(newToken) {
|
|
607
|
+
// }
|
|
887
608
|
|
|
888
|
-
|
|
889
|
-
originalRequest.headers['Authorization'] = `Bearer ${newToken}`;
|
|
890
|
-
//And continue onward
|
|
891
|
-
return resolve(originalRequest);
|
|
892
|
-
})
|
|
893
|
-
.catch(function(err) {
|
|
609
|
+
// /////////////////////////////////////////////
|
|
894
610
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
611
|
+
//If there is already a request in progress
|
|
612
|
+
if (refreshContext.inflightRefreshRequest) {
|
|
613
|
+
return refreshContext.inflightRefreshRequest;
|
|
614
|
+
}
|
|
898
615
|
|
|
616
|
+
/////////////////////////////////////////////////////
|
|
899
617
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
618
|
+
//Create an refresh request
|
|
619
|
+
|
|
620
|
+
refreshContext.inflightRefreshRequest = new Promise(function (
|
|
621
|
+
resolve,
|
|
622
|
+
reject,
|
|
623
|
+
) {
|
|
624
|
+
//Bypass the interceptor on all token refresh calls
|
|
625
|
+
//Because we don't need to add the access token etc onto it
|
|
626
|
+
|
|
627
|
+
qik.api
|
|
628
|
+
.post(
|
|
629
|
+
`/user/refresh`,
|
|
630
|
+
{
|
|
631
|
+
refreshToken: refreshToken,
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
bypassInterceptor: true,
|
|
635
|
+
withoutToken: true,
|
|
636
|
+
},
|
|
637
|
+
)
|
|
638
|
+
.then(function tokenRefreshComplete(res) {
|
|
639
|
+
//Update the user with any changes
|
|
640
|
+
//returned back from the refresh request
|
|
641
|
+
if (!res) {
|
|
642
|
+
refreshContext.inflightRefreshRequest = null;
|
|
643
|
+
return reject();
|
|
644
|
+
} else {
|
|
645
|
+
//Update with our new session
|
|
646
|
+
service.set(res.data);
|
|
647
|
+
|
|
648
|
+
dispatch();
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
//Resolve with the new token
|
|
652
|
+
resolve(res.data.token);
|
|
653
|
+
|
|
654
|
+
//Remove the inflight request
|
|
655
|
+
setTimeout(function () {
|
|
656
|
+
refreshContext.inflightRefreshRequest = null;
|
|
657
|
+
});
|
|
903
658
|
})
|
|
659
|
+
.catch(function (err) {
|
|
660
|
+
//TODO Check if invalid_refresh_token
|
|
904
661
|
|
|
662
|
+
setTimeout(function () {
|
|
663
|
+
refreshContext.inflightRefreshRequest = null;
|
|
664
|
+
});
|
|
665
|
+
reject(err);
|
|
666
|
+
});
|
|
667
|
+
});
|
|
905
668
|
|
|
669
|
+
//Return the refresh request
|
|
670
|
+
return refreshContext.inflightRefreshRequest;
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
///////////////////////////////////////////////////
|
|
674
|
+
|
|
675
|
+
var retryCount = 0;
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* @alias auth.sync
|
|
679
|
+
* @description A useful function to sync the current user session with the server.
|
|
680
|
+
* @example
|
|
681
|
+
*
|
|
682
|
+
* // Makes request to the API and updates the current user session to match the response
|
|
683
|
+
* sdk.auth.sync();
|
|
684
|
+
*/
|
|
685
|
+
service.sync = function () {
|
|
686
|
+
return qik.api
|
|
687
|
+
.get("/user")
|
|
688
|
+
.then(function (res) {
|
|
689
|
+
if (res.data) {
|
|
690
|
+
if (store.user) {
|
|
691
|
+
Object.assign(store.user.session, res.data);
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
service.set(null);
|
|
695
|
+
}
|
|
906
696
|
|
|
907
|
-
|
|
697
|
+
retryCount = 0;
|
|
908
698
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
699
|
+
dispatch();
|
|
700
|
+
})
|
|
701
|
+
.catch(function (err) {
|
|
702
|
+
// if (retryCount > 2) {
|
|
703
|
+
service.set(null);
|
|
704
|
+
retryCount = 0;
|
|
705
|
+
dispatch();
|
|
706
|
+
// } else {
|
|
912
707
|
|
|
913
|
-
|
|
708
|
+
// retryCount++;
|
|
709
|
+
// service.sync();
|
|
710
|
+
// }
|
|
711
|
+
});
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
/////////////////////////////////////////////////////
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* @alias auth.getCurrentUser
|
|
718
|
+
* @description Retrieves the current user session
|
|
719
|
+
* @example
|
|
720
|
+
*
|
|
721
|
+
* const me = sdk.auth.getCurrentUser();
|
|
722
|
+
*/
|
|
723
|
+
service.getCurrentUser = function (reloadFromServer) {
|
|
724
|
+
return store.user;
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* @alias auth.getCurrentToken
|
|
729
|
+
* @description Retrieves the current access token. If the user is authenticated
|
|
730
|
+
* the response will be the current user's access token, otherwise will fall back to the
|
|
731
|
+
* applications token.
|
|
732
|
+
* @example
|
|
733
|
+
* const currentAccessToken = sdk.auth.getCurrentToken();
|
|
734
|
+
*/
|
|
735
|
+
service.getCurrentToken = function () {
|
|
736
|
+
var user = service.getCurrentUser();
|
|
737
|
+
|
|
738
|
+
//User is not logged in
|
|
739
|
+
if (!user) {
|
|
740
|
+
//But there is an application token
|
|
741
|
+
if (qik.applicationToken) {
|
|
742
|
+
//use that instead
|
|
743
|
+
return qik.applicationToken;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
//No token
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
914
749
|
|
|
915
|
-
|
|
916
|
-
|
|
750
|
+
var { token } = user;
|
|
751
|
+
if (!token) {
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
917
754
|
|
|
755
|
+
return token.accessToken;
|
|
756
|
+
};
|
|
918
757
|
|
|
919
|
-
|
|
920
|
-
case 401:
|
|
921
|
-
service.logout();
|
|
922
|
-
break;
|
|
923
|
-
default:
|
|
924
|
-
//Some other error
|
|
925
|
-
break;
|
|
926
|
-
}
|
|
758
|
+
/////////////////////////////////////////////////////
|
|
927
759
|
|
|
928
|
-
|
|
760
|
+
qik.api.interceptors.request.use(
|
|
761
|
+
async function (config) {
|
|
762
|
+
//If we want to bypass the interceptor
|
|
763
|
+
//then just return the request
|
|
764
|
+
if (config.bypassInterceptor) {
|
|
765
|
+
return config;
|
|
766
|
+
}
|
|
929
767
|
|
|
930
|
-
|
|
931
|
-
})
|
|
768
|
+
//////////////////////////////
|
|
932
769
|
|
|
933
|
-
|
|
770
|
+
//Get the original request
|
|
771
|
+
var originalRequest = config;
|
|
934
772
|
|
|
935
|
-
|
|
773
|
+
//////////////////////////////
|
|
936
774
|
|
|
775
|
+
var userDetails = await service.getCurrentUser();
|
|
776
|
+
var accessToken;
|
|
777
|
+
var refreshToken;
|
|
778
|
+
var expiryDate;
|
|
937
779
|
|
|
938
|
-
|
|
780
|
+
if (userDetails) {
|
|
781
|
+
var { token } = userDetails;
|
|
782
|
+
if (token) {
|
|
783
|
+
accessToken = token.accessToken;
|
|
784
|
+
refreshToken = token.refreshToken;
|
|
785
|
+
expiryDate = token.expires;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
//////////////////////////////
|
|
790
|
+
|
|
791
|
+
//If there is a user token
|
|
792
|
+
if (accessToken) {
|
|
793
|
+
//Set the token of the request as the user's access token
|
|
794
|
+
originalRequest.headers["Authorization"] = `Bearer ${accessToken}`;
|
|
795
|
+
} else {
|
|
796
|
+
//Return the original request without a token
|
|
797
|
+
|
|
798
|
+
return originalRequest;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/////////////////////////////////////////////////////
|
|
802
|
+
|
|
803
|
+
//If no refresh token
|
|
804
|
+
if (!refreshToken) {
|
|
805
|
+
//Continue with the original request
|
|
806
|
+
return originalRequest;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/////////////////////////////////////////////////////
|
|
810
|
+
|
|
811
|
+
//We have a refresh token so we need to check
|
|
812
|
+
//whether our access token is stale and needs to be refreshed
|
|
813
|
+
var now = new Date();
|
|
814
|
+
|
|
815
|
+
//Give us a bit of buffer so that the backend doesn't beat us to
|
|
816
|
+
//retiring the token
|
|
817
|
+
now.setSeconds(now.getSeconds() + tokenBufferSeconds);
|
|
818
|
+
|
|
819
|
+
/////////////////////////////////////////////////////
|
|
820
|
+
|
|
821
|
+
var expires = new Date(expiryDate);
|
|
822
|
+
|
|
823
|
+
//If the token is still fresh
|
|
824
|
+
if (now < expires) {
|
|
825
|
+
//Return the original request
|
|
826
|
+
return originalRequest;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/////////////////////////////////////////////////////
|
|
830
|
+
|
|
831
|
+
return new Promise(async function (resolve, reject) {
|
|
832
|
+
//Refresh the token
|
|
833
|
+
await service
|
|
834
|
+
.refreshAccessToken(refreshToken)
|
|
835
|
+
.then(function (newToken) {
|
|
836
|
+
//Update the original request with our new token
|
|
837
|
+
originalRequest.headers["Authorization"] = `Bearer ${newToken}`;
|
|
838
|
+
//And continue onward
|
|
839
|
+
return resolve(originalRequest);
|
|
840
|
+
})
|
|
841
|
+
.catch(function (err) {
|
|
842
|
+
return reject(err);
|
|
843
|
+
});
|
|
844
|
+
});
|
|
845
|
+
},
|
|
846
|
+
function (error) {
|
|
847
|
+
return Promise.reject(error);
|
|
848
|
+
},
|
|
849
|
+
);
|
|
850
|
+
|
|
851
|
+
/////////////////////////////////////////////////////
|
|
852
|
+
|
|
853
|
+
qik.api.interceptors.response.use(
|
|
854
|
+
function (response) {
|
|
855
|
+
return response;
|
|
856
|
+
},
|
|
857
|
+
function (err) {
|
|
858
|
+
//////////////////////////////
|
|
859
|
+
|
|
860
|
+
//Get the response status
|
|
861
|
+
var status = (err && err.response && err.response.status) || err.status;
|
|
862
|
+
|
|
863
|
+
switch (status) {
|
|
864
|
+
case 401:
|
|
865
|
+
service.logout();
|
|
866
|
+
break;
|
|
867
|
+
default:
|
|
868
|
+
//Some other error
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/////////////////////////////////////////////////////
|
|
873
|
+
|
|
874
|
+
return Promise.reject(err);
|
|
875
|
+
},
|
|
876
|
+
);
|
|
877
|
+
|
|
878
|
+
return service;
|
|
879
|
+
};
|
|
880
|
+
|
|
881
|
+
export default QikAuth;
|