@strapi/plugin-users-permissions 4.2.0-alpha.9 → 4.2.0-beta.1

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.
Files changed (41) hide show
  1. package/admin/src/components/FormModal/index.js +1 -1
  2. package/admin/src/index.js +1 -1
  3. package/admin/src/pages/AdvancedSettings/index.js +2 -2
  4. package/admin/src/pages/EmailTemplates/components/EmailTable.js +2 -2
  5. package/admin/src/pages/Providers/index.js +4 -4
  6. package/admin/src/pages/Roles/CreatePage/index.js +3 -3
  7. package/admin/src/pages/Roles/EditPage/index.js +4 -4
  8. package/admin/src/pages/Roles/ListPage/components/TableBody.js +2 -3
  9. package/admin/src/pages/Roles/ListPage/index.js +6 -6
  10. package/admin/src/translations/ar.json +0 -1
  11. package/admin/src/translations/cs.json +0 -1
  12. package/admin/src/translations/de.json +0 -2
  13. package/admin/src/translations/dk.json +0 -11
  14. package/admin/src/translations/en.json +0 -11
  15. package/admin/src/translations/es.json +0 -11
  16. package/admin/src/translations/fr.json +0 -1
  17. package/admin/src/translations/id.json +0 -2
  18. package/admin/src/translations/it.json +0 -2
  19. package/admin/src/translations/ja.json +0 -1
  20. package/admin/src/translations/ko.json +0 -11
  21. package/admin/src/translations/ms.json +0 -1
  22. package/admin/src/translations/nl.json +0 -1
  23. package/admin/src/translations/pl.json +0 -1
  24. package/admin/src/translations/pt-BR.json +0 -1
  25. package/admin/src/translations/pt.json +0 -1
  26. package/admin/src/translations/ru.json +0 -2
  27. package/admin/src/translations/sk.json +0 -1
  28. package/admin/src/translations/sv.json +0 -2
  29. package/admin/src/translations/th.json +0 -2
  30. package/admin/src/translations/tr.json +0 -1
  31. package/admin/src/translations/uk.json +0 -1
  32. package/admin/src/translations/vi.json +0 -1
  33. package/admin/src/translations/zh-Hans.json +0 -3
  34. package/admin/src/translations/zh.json +0 -1
  35. package/package.json +6 -8
  36. package/server/bootstrap/index.js +13 -4
  37. package/server/controllers/auth.js +10 -15
  38. package/server/controllers/validation/email-template.js +10 -1
  39. package/server/services/providers-list.js +152 -348
  40. package/server/services/providers.js +58 -69
  41. package/server/services/user.js +3 -1
@@ -1,51 +1,25 @@
1
1
  'use strict';
2
2
 
3
- const _ = require('lodash');
4
3
  const jwt = require('jsonwebtoken');
5
- const request = require('request');
6
4
  // Purest strategies.
7
- const purest = require('purest')({ request });
8
- const purestConfig = require('@purest/providers');
5
+ const purest = require('purest');
9
6
 
10
- module.exports = async ({ provider, access_token, callback, query, providers }) => {
7
+ module.exports = async ({ provider, access_token, query, providers }) => {
11
8
  switch (provider) {
12
9
  case 'discord': {
13
- const discord = purest({
14
- provider: 'discord',
15
- config: {
16
- discord: {
17
- 'https://discordapp.com/api/': {
18
- __domain: {
19
- auth: {
20
- auth: { bearer: '[0]' },
21
- },
22
- },
23
- '{endpoint}': {
24
- __path: {
25
- alias: '__default',
26
- },
27
- },
28
- },
29
- },
30
- },
31
- });
32
- discord
33
- .query()
10
+ const discord = purest({ provider: 'discord' });
11
+ return discord
34
12
  .get('users/@me')
35
13
  .auth(access_token)
36
- .request((err, res, body) => {
37
- if (err) {
38
- callback(err);
39
- } else {
40
- // Combine username and discriminator because discord username is not unique
41
- var username = `${body.username}#${body.discriminator}`;
42
- callback(null, {
43
- username,
44
- email: body.email,
45
- });
46
- }
14
+ .request()
15
+ .then(({ body }) => {
16
+ // Combine username and discriminator because discord username is not unique
17
+ var username = `${body.username}#${body.discriminator}`;
18
+ return {
19
+ username,
20
+ email: body.email,
21
+ };
47
22
  });
48
- break;
49
23
  }
50
24
  case 'cognito': {
51
25
  // get the id_token
@@ -53,60 +27,43 @@ module.exports = async ({ provider, access_token, callback, query, providers })
53
27
  // decode the jwt token
54
28
  const tokenPayload = jwt.decode(idToken);
55
29
  if (!tokenPayload) {
56
- callback(new Error('unable to decode jwt token'));
30
+ throw new Error('unable to decode jwt token');
57
31
  } else {
58
- callback(null, {
32
+ return {
59
33
  username: tokenPayload['cognito:username'],
60
34
  email: tokenPayload.email,
61
- });
35
+ };
62
36
  }
63
- break;
64
37
  }
65
38
  case 'facebook': {
66
- const facebook = purest({
67
- provider: 'facebook',
68
- config: purestConfig,
69
- });
39
+ const facebook = purest({ provider: 'facebook' });
70
40
 
71
- facebook
72
- .query()
73
- .get('me?fields=name,email')
41
+ return facebook
42
+ .get('me')
74
43
  .auth(access_token)
75
- .request((err, res, body) => {
76
- if (err) {
77
- callback(err);
78
- } else {
79
- callback(null, {
80
- username: body.name,
81
- email: body.email,
82
- });
83
- }
84
- });
85
- break;
44
+ .qs({ fields: 'name,email' })
45
+ .request()
46
+ .then(({ body }) => ({
47
+ username: body.name,
48
+ email: body.email,
49
+ }));
86
50
  }
87
51
  case 'google': {
88
- const google = purest({ provider: 'google', config: purestConfig });
52
+ const google = purest({ provider: 'google' });
89
53
 
90
- google
54
+ return google
91
55
  .query('oauth')
92
56
  .get('tokeninfo')
93
57
  .qs({ access_token })
94
- .request((err, res, body) => {
95
- if (err) {
96
- callback(err);
97
- } else {
98
- callback(null, {
99
- username: body.email.split('@')[0],
100
- email: body.email,
101
- });
102
- }
103
- });
104
- break;
58
+ .request()
59
+ .then(({ body }) => ({
60
+ username: body.email.split('@')[0],
61
+ email: body.email,
62
+ }));
105
63
  }
106
64
  case 'github': {
107
65
  const github = purest({
108
66
  provider: 'github',
109
- config: purestConfig,
110
67
  defaults: {
111
68
  headers: {
112
69
  'user-agent': 'strapi',
@@ -114,360 +71,207 @@ module.exports = async ({ provider, access_token, callback, query, providers })
114
71
  },
115
72
  });
116
73
 
117
- github
118
- .query()
74
+ return github
119
75
  .get('user')
120
76
  .auth(access_token)
121
- .request((err, res, userbody) => {
122
- if (err) {
123
- return callback(err);
124
- }
125
-
77
+ .request()
78
+ .then(({ body: userbody }) => {
126
79
  // This is the public email on the github profile
127
80
  if (userbody.email) {
128
- return callback(null, {
81
+ return {
129
82
  username: userbody.login,
130
83
  email: userbody.email,
131
- });
84
+ };
132
85
  }
133
-
134
86
  // Get the email with Github's user/emails API
135
- github
136
- .query()
87
+ return github
137
88
  .get('user/emails')
138
89
  .auth(access_token)
139
- .request((err, res, emailsbody) => {
140
- if (err) {
141
- return callback(err);
142
- }
143
-
144
- return callback(null, {
90
+ .request()
91
+ .then(({ body: emailsbody }) => {
92
+ return {
145
93
  username: userbody.login,
146
94
  email: Array.isArray(emailsbody)
147
95
  ? emailsbody.find(email => email.primary === true).email
148
96
  : null,
149
- });
97
+ };
150
98
  });
151
99
  });
152
- break;
153
100
  }
154
101
  case 'microsoft': {
155
- const microsoft = purest({
156
- provider: 'microsoft',
157
- config: purestConfig,
158
- });
102
+ const microsoft = purest({ provider: 'microsoft' });
159
103
 
160
- microsoft
161
- .query()
104
+ return microsoft
162
105
  .get('me')
163
106
  .auth(access_token)
164
- .request((err, res, body) => {
165
- if (err) {
166
- callback(err);
167
- } else {
168
- callback(null, {
169
- username: body.userPrincipalName,
170
- email: body.userPrincipalName,
171
- });
172
- }
173
- });
174
- break;
107
+ .request()
108
+ .then(({ body }) => ({
109
+ username: body.userPrincipalName,
110
+ email: body.userPrincipalName,
111
+ }));
175
112
  }
176
113
  case 'twitter': {
177
114
  const twitter = purest({
178
115
  provider: 'twitter',
179
- config: purestConfig,
180
- key: providers.twitter.key,
181
- secret: providers.twitter.secret,
182
116
  });
183
117
 
184
- twitter
185
- .query()
118
+ return twitter
186
119
  .get('account/verify_credentials')
187
120
  .auth(access_token, query.access_secret)
188
121
  .qs({ screen_name: query['raw[screen_name]'], include_email: 'true' })
189
- .request((err, res, body) => {
190
- if (err) {
191
- callback(err);
192
- } else {
193
- callback(null, {
194
- username: body.screen_name,
195
- email: body.email,
196
- });
197
- }
198
- });
199
- break;
122
+ .request()
123
+ .then(({ body }) => ({
124
+ username: body.screen_name,
125
+ email: body.email,
126
+ }));
200
127
  }
201
128
  case 'instagram': {
202
- const instagram = purest({
203
- provider: 'instagram',
204
- key: providers.instagram.key,
205
- secret: providers.instagram.secret,
206
- config: purestConfig,
207
- });
129
+ const instagram = purest({ provider: 'instagram' });
208
130
 
209
- instagram
210
- .query()
131
+ return instagram
211
132
  .get('me')
212
- .qs({ access_token, fields: 'id,username' })
213
- .request((err, res, body) => {
214
- if (err) {
215
- callback(err);
216
- } else {
217
- callback(null, {
218
- username: body.username,
219
- email: `${body.username}@strapi.io`, // dummy email as Instagram does not provide user email
220
- });
221
- }
222
- });
223
- break;
133
+ .auth(access_token)
134
+ .qs({ fields: 'id,username' })
135
+ .request()
136
+ .then(({ body }) => ({
137
+ username: body.username,
138
+ email: `${body.username}@strapi.io`, // dummy email as Instagram does not provide user email
139
+ }));
224
140
  }
225
141
  case 'vk': {
226
- const vk = purest({
227
- provider: 'vk',
228
- config: purestConfig,
229
- });
142
+ const vk = purest({ provider: 'vk' });
230
143
 
231
- vk.query()
144
+ return vk
232
145
  .get('users.get')
233
- .qs({ access_token, id: query.raw.user_id, v: '5.122' })
234
- .request((err, res, body) => {
235
- if (err) {
236
- callback(err);
237
- } else {
238
- callback(null, {
239
- username: `${body.response[0].last_name} ${body.response[0].first_name}`,
240
- email: query.raw.email,
241
- });
242
- }
243
- });
244
- break;
146
+ .auth(access_token)
147
+ .qs({ id: query.raw.user_id, v: '5.122' })
148
+ .request()
149
+ .then(({ body }) => ({
150
+ username: `${body.response[0].last_name} ${body.response[0].first_name}`,
151
+ email: query.raw.email,
152
+ }));
245
153
  }
246
154
  case 'twitch': {
247
155
  const twitch = purest({
248
156
  provider: 'twitch',
249
157
  config: {
250
158
  twitch: {
251
- 'https://api.twitch.tv': {
252
- __domain: {
253
- auth: {
254
- headers: {
255
- Authorization: 'Bearer [0]',
256
- 'Client-ID': '[1]',
257
- },
258
- },
259
- },
260
- 'helix/{endpoint}': {
261
- __path: {
262
- alias: '__default',
263
- },
264
- },
265
- 'oauth2/{endpoint}': {
266
- __path: {
267
- alias: 'oauth',
268
- },
159
+ default: {
160
+ origin: 'https://api.twitch.tv',
161
+ path: 'helix/{path}',
162
+ headers: {
163
+ Authorization: 'Bearer {auth}',
164
+ 'Client-Id': '{auth}',
269
165
  },
270
166
  },
271
167
  },
272
168
  },
273
169
  });
274
170
 
275
- twitch
171
+ return twitch
276
172
  .get('users')
277
173
  .auth(access_token, providers.twitch.key)
278
- .request((err, res, body) => {
279
- if (err) {
280
- callback(err);
281
- } else {
282
- callback(null, {
283
- username: body.data[0].login,
284
- email: body.data[0].email,
285
- });
286
- }
287
- });
288
- break;
174
+ .request()
175
+ .then(({ body }) => ({
176
+ username: body.data[0].login,
177
+ email: body.data[0].email,
178
+ }));
289
179
  }
290
180
  case 'linkedin': {
291
- const linkedIn = purest({
292
- provider: 'linkedin',
293
- config: {
294
- linkedin: {
295
- 'https://api.linkedin.com': {
296
- __domain: {
297
- auth: [{ auth: { bearer: '[0]' } }],
298
- },
299
- '[version]/{endpoint}': {
300
- __path: {
301
- alias: '__default',
302
- version: 'v2',
303
- },
304
- },
305
- },
306
- },
307
- },
308
- });
309
- try {
310
- const getDetailsRequest = () => {
311
- return new Promise((resolve, reject) => {
312
- linkedIn
313
- .query()
314
- .get('me')
315
- .auth(access_token)
316
- .request((err, res, body) => {
317
- if (err) {
318
- return reject(err);
319
- }
320
- resolve(body);
321
- });
322
- });
323
- };
324
-
325
- const getEmailRequest = () => {
326
- return new Promise((resolve, reject) => {
327
- linkedIn
328
- .query()
329
- .get('emailAddress?q=members&projection=(elements*(handle~))')
330
- .auth(access_token)
331
- .request((err, res, body) => {
332
- if (err) {
333
- return reject(err);
334
- }
335
- resolve(body);
336
- });
337
- });
338
- };
181
+ const linkedIn = purest({ provider: 'linkedin' });
182
+ const {
183
+ body: { localizedFirstName },
184
+ } = await linkedIn
185
+ .get('me')
186
+ .auth(access_token)
187
+ .request();
188
+ const {
189
+ body: { elements },
190
+ } = await linkedIn
191
+ .get('emailAddress?q=members&projection=(elements*(handle~))')
192
+ .auth(access_token)
193
+ .request();
339
194
 
340
- const { localizedFirstName } = await getDetailsRequest();
341
- const { elements } = await getEmailRequest();
342
- const email = elements[0]['handle~'];
195
+ const email = elements[0]['handle~'];
343
196
 
344
- callback(null, {
345
- username: localizedFirstName,
346
- email: email.emailAddress,
347
- });
348
- } catch (err) {
349
- callback(err);
350
- }
351
- break;
197
+ return {
198
+ username: localizedFirstName,
199
+ email: email.emailAddress,
200
+ };
352
201
  }
353
202
  case 'reddit': {
354
203
  const reddit = purest({
355
204
  provider: 'reddit',
356
- config: purestConfig,
357
- defaults: {
358
- headers: {
359
- 'user-agent': 'strapi',
205
+ config: {
206
+ reddit: {
207
+ default: {
208
+ origin: 'https://oauth.reddit.com',
209
+ path: 'api/{version}/{path}',
210
+ version: 'v1',
211
+ headers: {
212
+ Authorization: 'Bearer {auth}',
213
+ 'user-agent': 'strapi',
214
+ },
215
+ },
360
216
  },
361
217
  },
362
218
  });
363
219
 
364
- reddit
365
- .query('auth')
220
+ return reddit
366
221
  .get('me')
367
222
  .auth(access_token)
368
- .request((err, res, body) => {
369
- if (err) {
370
- callback(err);
371
- } else {
372
- callback(null, {
373
- username: body.name,
374
- email: `${body.name}@strapi.io`, // dummy email as Reddit does not provide user email
375
- });
376
- }
377
- });
378
- break;
223
+ .request()
224
+ .then(({ body }) => ({
225
+ username: body.name,
226
+ email: `${body.name}@strapi.io`, // dummy email as Reddit does not provide user email
227
+ }));
379
228
  }
380
229
  case 'auth0': {
381
- const purestAuth0Conf = {};
382
- purestAuth0Conf[`https://${providers.auth0.subdomain}.auth0.com`] = {
383
- __domain: {
384
- auth: {
385
- auth: { bearer: '[0]' },
386
- },
387
- },
388
- '{endpoint}': {
389
- __path: {
390
- alias: '__default',
391
- },
392
- },
393
- };
394
- const auth0 = purest({
395
- provider: 'auth0',
396
- config: {
397
- auth0: purestAuth0Conf,
398
- },
399
- });
230
+ const auth0 = purest({ provider: 'auth0' });
400
231
 
401
- auth0
232
+ return auth0
402
233
  .get('userinfo')
234
+ .subdomain(providers.auth0.subdomain)
403
235
  .auth(access_token)
404
- .request((err, res, body) => {
405
- if (err) {
406
- callback(err);
407
- } else {
408
- const username =
409
- body.username || body.nickname || body.name || body.email.split('@')[0];
410
- const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
236
+ .request()
237
+ .then(({ body }) => {
238
+ const username = body.username || body.nickname || body.name || body.email.split('@')[0];
239
+ const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
411
240
 
412
- callback(null, {
413
- username,
414
- email,
415
- });
416
- }
241
+ return {
242
+ username,
243
+ email,
244
+ };
417
245
  });
418
- break;
419
246
  }
420
247
  case 'cas': {
421
- const provider_url = 'https://' + _.get(providers.cas, 'subdomain');
422
- const cas = purest({
423
- provider: 'cas',
424
- config: {
425
- cas: {
426
- [provider_url]: {
427
- __domain: {
428
- auth: {
429
- auth: { bearer: '[0]' },
430
- },
431
- },
432
- '{endpoint}': {
433
- __path: {
434
- alias: '__default',
435
- },
436
- },
437
- },
438
- },
439
- },
440
- });
441
- cas
442
- .query()
248
+ const cas = purest({ provider: 'cas' });
249
+
250
+ return cas
443
251
  .get('oidc/profile')
252
+ .subdomain(providers.cas.subdomain)
444
253
  .auth(access_token)
445
- .request((err, res, body) => {
446
- if (err) {
447
- callback(err);
448
- } else {
449
- // CAS attribute may be in body.attributes or "FLAT", depending on CAS config
450
- const username = body.attributes
451
- ? body.attributes.strapiusername || body.id || body.sub
452
- : body.strapiusername || body.id || body.sub;
453
- const email = body.attributes
454
- ? body.attributes.strapiemail || body.attributes.email
455
- : body.strapiemail || body.email;
456
- if (!username || !email) {
457
- strapi.log.warn(
458
- 'CAS Response Body did not contain required attributes: ' + JSON.stringify(body)
459
- );
460
- }
461
- callback(null, {
462
- username,
463
- email,
464
- });
254
+ .request()
255
+ .then(({ body }) => {
256
+ // CAS attribute may be in body.attributes or "FLAT", depending on CAS config
257
+ const username = body.attributes
258
+ ? body.attributes.strapiusername || body.id || body.sub
259
+ : body.strapiusername || body.id || body.sub;
260
+ const email = body.attributes
261
+ ? body.attributes.strapiemail || body.attributes.email
262
+ : body.strapiemail || body.email;
263
+ if (!username || !email) {
264
+ strapi.log.warn(
265
+ 'CAS Response Body did not contain required attributes: ' + JSON.stringify(body)
266
+ );
465
267
  }
268
+ return {
269
+ username,
270
+ email,
271
+ };
466
272
  });
467
- break;
468
273
  }
469
274
  default:
470
- callback(new Error('Unknown provider.'));
471
- break;
275
+ throw new Error('Unknown provider.');
472
276
  }
473
277
  };