@things-factory/auth-base 8.0.0-alpha.35 → 8.0.0-alpha.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/auth-base",
3
- "version": "8.0.0-alpha.35",
3
+ "version": "8.0.0-alpha.36",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -46,5 +46,5 @@
46
46
  "passport-jwt": "^4.0.0",
47
47
  "passport-local": "^1.0.0"
48
48
  },
49
- "gitHead": "94fe243a5c99837a1e6f98de2c454c351ac8e6fd"
49
+ "gitHead": "7529955cea0ce5eaa29069374ceac5de848ca1a0"
50
50
  }
@@ -211,10 +211,9 @@ authPublicProcessRouter.post('/forgot-password', async (context, next) => {
211
211
 
212
212
  authPublicProcessRouter.post('/reset-password', async (context, next) => {
213
213
  const { header, t } = context
214
+ const { password, token } = context.request.body
214
215
 
215
216
  try {
216
- const { password, token } = context.request.body
217
-
218
217
  if (!(token && password)) {
219
218
  let message = t('error.token or password is invalid')
220
219
 
@@ -243,7 +242,7 @@ authPublicProcessRouter.post('/reset-password', async (context, next) => {
243
242
 
244
243
  await resetPassword(token, password, context)
245
244
 
246
- var message = t('text.password reset succeed')
245
+ var message = t('text.password changed successfully')
247
246
  context.body = message
248
247
 
249
248
  clearAccessTokenCookie(context)
@@ -266,10 +265,12 @@ authPublicProcessRouter.post('/reset-password', async (context, next) => {
266
265
 
267
266
  if (accepts(header.accept, ['text/html', '*/*'])) {
268
267
  await context.render('auth-page', {
269
- pageElement: 'auth-result',
270
- elementScript: '/auth/result.js',
268
+ pageElement: 'reset-password',
269
+ elementScript: '/auth/reset-password.js',
271
270
  data: {
271
+ token,
272
272
  message: e.message,
273
+ passwordRule,
273
274
  disableUserSignupProcess,
274
275
  disableUserFavoredLanguage,
275
276
  languages
@@ -216,16 +216,22 @@ export class UserMutation {
216
216
 
217
217
  @Directive('@transaction')
218
218
  @Mutation(returns => Boolean, { description: 'To invite new user' })
219
- async inviteUser(
220
- @Arg('email', type => GraphQLEmailAddress) email: string,
221
- @Ctx() context: ResolverContext
222
- ): Promise<boolean> {
219
+ async inviteUser(@Arg('username') username: string, @Ctx() context: ResolverContext): Promise<boolean> {
223
220
  const { domain, tx } = context.state
224
- const invitee: User = await getRepository(User, tx).findOne({
225
- where: { email: ILike(email) },
221
+ const userRepository = getRepository(User, tx)
222
+
223
+ var invitee: User = await userRepository.findOne({
224
+ where: { username },
226
225
  relations: ['domains']
227
226
  })
228
227
 
228
+ if (!invitee && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
229
+ invitee = await userRepository.findOne({
230
+ where: { email: ILike(username) },
231
+ relations: ['domains']
232
+ })
233
+ }
234
+
229
235
  if (!invitee) {
230
236
  throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
231
237
  }
@@ -234,8 +240,9 @@ export class UserMutation {
234
240
  if (existingDomains.find((d: Domain) => d.id === domain.id)) {
235
241
  throw new Error(context.t('error.x already exists in y', { x: context.t('field.user'), y: domain.name }))
236
242
  }
243
+
237
244
  invitee.domains = [...existingDomains, domain]
238
- await getRepository(User, tx).save(invitee)
245
+ await userRepository.save(invitee)
239
246
 
240
247
  return true
241
248
  }
@@ -243,16 +250,22 @@ export class UserMutation {
243
250
  @Directive('@transaction')
244
251
  @Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
245
252
  @Mutation(returns => Boolean, { description: 'To delete domain user' })
246
- async deleteDomainUser(
247
- @Arg('email', type => GraphQLEmailAddress) email: string,
248
- @Ctx() context: ResolverContext
249
- ): Promise<boolean> {
253
+ async deleteDomainUser(@Arg('username') username: string, @Ctx() context: ResolverContext): Promise<boolean> {
250
254
  const { tx, domain } = context.state
255
+ const userRepository = getRepository(User, tx)
251
256
 
252
- let user: User = await getRepository(User, tx).findOne({
253
- where: { email: ILike(email) },
254
- relations: ['domains', 'roles', 'roles.domain']
257
+ var user: User = await userRepository.findOne({
258
+ where: { username },
259
+ relations: ['domains', 'roles']
255
260
  })
261
+
262
+ if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
263
+ user = await userRepository.findOne({
264
+ where: { email: ILike(username) },
265
+ relations: ['domains', 'roles']
266
+ })
267
+ }
268
+
256
269
  if (!user) {
257
270
  throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
258
271
  }
@@ -266,9 +279,9 @@ export class UserMutation {
266
279
  user.domains.splice(targetDomainIdx, 1)
267
280
 
268
281
  // Remove domain's roles that user has
269
- user.roles = user.roles.filter((role: Role) => role.domain.id !== domain.id)
282
+ user.roles = user.roles.filter((role: Role) => role.domainId !== domain.id)
270
283
 
271
- await getRepository(User, tx).save(user)
284
+ await userRepository.save(user)
272
285
 
273
286
  return true
274
287
  }
@@ -276,18 +289,24 @@ export class UserMutation {
276
289
  @Directive('@privilege(domainOwnerGranted: true, superUserGranted: true)')
277
290
  @Directive('@transaction')
278
291
  @Mutation(returns => Boolean, { description: 'To transfer owner of domain' })
279
- async transferOwner(
280
- @Arg('email', type => GraphQLEmailAddress) email: string,
281
- @Ctx() context: ResolverContext
282
- ): Promise<boolean> {
292
+ async transferOwner(@Arg('username') username: string, @Ctx() context: ResolverContext): Promise<boolean> {
283
293
  const { domain, tx } = context.state
284
- const user: User = await getRepository(User, tx).findOne({
285
- where: { email: ILike(email) },
286
- relations: ['domains', 'roles']
294
+ const userRepository = getRepository(User, tx)
295
+
296
+ var user: User = await userRepository.findOne({
297
+ where: { username },
298
+ relations: ['domains']
287
299
  })
288
300
 
301
+ if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
302
+ user = await userRepository.findOne({
303
+ where: { email: ILike(username) },
304
+ relations: ['domains']
305
+ })
306
+ }
307
+
289
308
  if (!user) {
290
- throw new Error('Failed to find user')
309
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
291
310
  }
292
311
 
293
312
  if (user.status !== UserStatus.ACTIVATED) {
@@ -311,15 +330,24 @@ export class UserMutation {
311
330
  @Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
312
331
  @Directive('@transaction')
313
332
  @Mutation(returns => Boolean, { description: 'To activate user' })
314
- async activateUser(@Arg('userId') userId: string, @Ctx() context: ResolverContext): Promise<boolean> {
333
+ async activateUser(@Arg('username') username: string, @Ctx() context: ResolverContext): Promise<boolean> {
315
334
  const { tx, domain } = context.state
335
+ const userRepository = getRepository(User, tx)
316
336
 
317
- const targetUser: User = await getRepository(User, tx).findOne({
318
- where: { id: userId },
337
+ var targetUser: User = await userRepository.findOne({
338
+ where: { username },
319
339
  relations: ['domains']
320
340
  })
341
+
342
+ if (!targetUser && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
343
+ targetUser = await userRepository.findOne({
344
+ where: { email: ILike(username) },
345
+ relations: ['domains']
346
+ })
347
+ }
348
+
321
349
  if (!targetUser) {
322
- throw new Error('No user found')
350
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
323
351
  }
324
352
 
325
353
  if (!targetUser?.domains?.find((userDomain: Domain) => userDomain.id === domain.id)) {
@@ -329,7 +357,7 @@ export class UserMutation {
329
357
  targetUser.failCount = 0
330
358
  targetUser.status = UserStatus.ACTIVATED
331
359
 
332
- await getRepository(User, tx).save(targetUser)
360
+ await userRepository.save(targetUser)
333
361
 
334
362
  return true
335
363
  }
@@ -337,15 +365,24 @@ export class UserMutation {
337
365
  @Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
338
366
  @Directive('@transaction')
339
367
  @Mutation(returns => Boolean, { description: 'To inactivate user' })
340
- async inactivateUser(@Arg('userId') userId: string, @Ctx() context: ResolverContext): Promise<boolean> {
368
+ async inactivateUser(@Arg('username') username: string, @Ctx() context: ResolverContext): Promise<boolean> {
341
369
  const { tx, domain } = context.state
370
+ const userRepository = getRepository(User, tx)
342
371
 
343
- const targetUser: User = await getRepository(User, tx).findOne({
344
- where: { id: userId },
372
+ var targetUser: User = await userRepository.findOne({
373
+ where: { username },
345
374
  relations: ['domains']
346
375
  })
376
+
377
+ if (!targetUser && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
378
+ targetUser = await userRepository.findOne({
379
+ where: { email: ILike(username) },
380
+ relations: ['domains']
381
+ })
382
+ }
383
+
347
384
  if (!targetUser) {
348
- throw new Error('No user found')
385
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
349
386
  }
350
387
 
351
388
  if (!targetUser?.domains?.find((userDomain: Domain) => userDomain.id === domain.id)) {
@@ -358,7 +395,7 @@ export class UserMutation {
358
395
 
359
396
  targetUser.status = UserStatus.INACTIVE
360
397
 
361
- await getRepository(User, tx).save(targetUser)
398
+ await userRepository.save(targetUser)
362
399
 
363
400
  return true
364
401
  }
@@ -366,7 +403,7 @@ export class UserMutation {
366
403
  @Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
367
404
  @Directive('@transaction')
368
405
  @Mutation(returns => Boolean, { description: 'To reset password to default' })
369
- async resetPasswordToDefault(@Arg('userId') userId: string, @Ctx() context: ResolverContext): Promise<boolean> {
406
+ async resetPasswordToDefault(@Arg('username') username: string, @Ctx() context: ResolverContext): Promise<boolean> {
370
407
  const { tx, domain } = context.state
371
408
 
372
409
  const { defaultPassword } = config.get('password')
@@ -374,12 +411,22 @@ export class UserMutation {
374
411
  throw new Error('No default password found')
375
412
  }
376
413
 
377
- const targetUser: User = await getRepository(User, tx).findOne({
378
- where: { id: userId },
414
+ const userRepository = getRepository(User, tx)
415
+
416
+ var targetUser: User = await userRepository.findOne({
417
+ where: { username },
379
418
  relations: ['domains']
380
419
  })
420
+
421
+ if (!targetUser && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
422
+ targetUser = await userRepository.findOne({
423
+ where: { email: ILike(username) },
424
+ relations: ['domains']
425
+ })
426
+ }
427
+
381
428
  if (!targetUser) {
382
- throw new Error('No user found')
429
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
383
430
  }
384
431
 
385
432
  if (!targetUser?.domains?.find((userDomain: Domain) => userDomain.id === domain.id)) {
@@ -388,7 +435,8 @@ export class UserMutation {
388
435
 
389
436
  targetUser.salt = User.generateSalt()
390
437
  targetUser.password = User.encode(defaultPassword, targetUser.salt)
391
- await getRepository(User, tx).save(targetUser)
438
+
439
+ await userRepository.save(targetUser)
392
440
 
393
441
  return true
394
442
  }
@@ -397,18 +445,28 @@ export class UserMutation {
397
445
  @Directive('@transaction')
398
446
  @Mutation(returns => User, { description: 'To update roles for a user' })
399
447
  async updateUserRoles(
400
- @Arg('userId') userId: string,
448
+ @Arg('username') username: string,
401
449
  @Arg('availableRoles', type => [ObjectRef]) availableRoles: ObjectRef[],
402
450
  @Arg('selectedRoles', type => [ObjectRef]) selectedRoles: ObjectRef[],
403
451
  @Ctx() context: ResolverContext
404
452
  ) {
405
453
  const { domain, tx } = context.state
406
- let user: User = await getRepository(User, tx).findOne({
407
- where: { id: userId },
454
+ const userRepository = getRepository(User, tx)
455
+
456
+ var user: User = await userRepository.findOne({
457
+ where: { username },
408
458
  relations: ['domains', 'roles']
409
459
  })
460
+
461
+ if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
462
+ user = await userRepository.findOne({
463
+ where: { email: ILike(username) },
464
+ relations: ['domains', 'roles']
465
+ })
466
+ }
467
+
410
468
  if (!user) {
411
- throw new Error('Failed to find user')
469
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
412
470
  }
413
471
 
414
472
  if (user.domains.map((d: Domain) => d.id).indexOf(domain.id) < 0) {
@@ -419,6 +477,6 @@ export class UserMutation {
419
477
  user.roles = user.roles.filter((r: Role) => availableRoleIds.indexOf(r.id) < 0)
420
478
  user.roles = user.roles.concat(selectedRoles as Role[])
421
479
 
422
- return await getRepository(User, tx).save(user)
480
+ return await userRepository.save(user)
423
481
  }
424
482
  }
@@ -59,6 +59,7 @@
59
59
  "text.signout successfully": "signout successfully",
60
60
  "text.user activated successfully": "user activated successfully",
61
61
  "text.user credential registered successfully": "device registration has been successfully completed. You can now use biometric authentication.",
62
+ "text.user inactivated successfully": "user inactivated successfully",
62
63
  "text.user registered successfully": "user registered successfully. find your email to activate account",
63
64
  "text.verification email sent": "verification email sent"
64
65
  }
@@ -59,6 +59,7 @@
59
59
  "text.signout successfully": "ログアウトに成功しました.",
60
60
  "text.user activated successfully": "ユーザーが正常に活性化されました.",
61
61
  "text.user credential registered successfully": "デバイスの登録が正常に完了しました。今後は生体認証を使用できます。",
62
+ "text.user inactivated successfully": "ユーザーが正常に非アクティブ化されました.",
62
63
  "text.user registered successfully": "ユーザーが正常に登録されました. 確認メールでアカウントを有効にしてください.",
63
64
  "text.verification email sent": "確認メールを送りました."
64
65
  }
@@ -59,6 +59,7 @@
59
59
  "text.signout successfully": "성공적으로 로그아웃 하였습니다.",
60
60
  "text.user activated successfully": "사용자가 성공적으로 활성화되었습니다.",
61
61
  "text.user credential registered successfully": "기기 등록이 성공적으로 완료되었습니다. 이제 바이오메트릭 인증을 사용할 수 있습니다.",
62
+ "text.user inactivated successfully": "사용자가 성공적으로 비활성화되었습니다.",
62
63
  "text.user registered successfully": "사용자가 성공적으로 등록되었습니다. 확인 이메일을 통해서 계정을 활성화하시기 바랍니다.",
63
64
  "text.verification email sent": "확인 이메일을 보냈습니다."
64
65
  }
@@ -59,6 +59,7 @@
59
59
  "text.signout successfully": "Berjaya keluar",
60
60
  "text.user activated successfully": "Pengguna diaktifkan dengan berjaya",
61
61
  "text.user credential registered successfully": "pendaftaran peranti berjaya diselesaikan. Kini anda boleh menggunakan pengesahan biometrik.",
62
+ "text.user inactivated successfully": "Pengguna tidak aktif dengan berjaya",
62
63
  "text.user registered successfully": "Pengguna berjaya didaftarkan. Cari e-mel anda untuk mengaktifkan akaun",
63
64
  "text.verification email sent": "E-mel pengesahan telah dihantar"
64
65
  }
@@ -60,6 +60,7 @@
60
60
  "text.signout successfully": "登出成功。",
61
61
  "text.user activated successfully": "用户激活成功",
62
62
  "text.user credential registered successfully": "设备注册已成功完成。现在可以使用生物识别认证。",
63
+ "text.user inactivated successfully": "用户已成功停用",
63
64
  "text.user registered successfully": "用户注册成功。 请查看电子邮件以激活帐户。",
64
65
  "text.verification email sent": "验证邮件已发送"
65
66
  }