@things-factory/auth-base 8.0.5 → 8.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.
Files changed (116) hide show
  1. package/client/auth.ts +0 -4
  2. package/dist-client/auth.js +0 -3
  3. package/dist-client/auth.js.map +1 -1
  4. package/dist-client/tsconfig.tsbuildinfo +1 -1
  5. package/dist-server/constants/error-code.d.ts +2 -0
  6. package/dist-server/constants/error-code.js +3 -1
  7. package/dist-server/constants/error-code.js.map +1 -1
  8. package/dist-server/controllers/change-pwd.js +2 -2
  9. package/dist-server/controllers/change-pwd.js.map +1 -1
  10. package/dist-server/controllers/delete-user.js +13 -12
  11. package/dist-server/controllers/delete-user.js.map +1 -1
  12. package/dist-server/controllers/invitation.d.ts +2 -1
  13. package/dist-server/controllers/invitation.js +30 -5
  14. package/dist-server/controllers/invitation.js.map +1 -1
  15. package/dist-server/controllers/profile.d.ts +4 -3
  16. package/dist-server/controllers/profile.js +20 -2
  17. package/dist-server/controllers/profile.js.map +1 -1
  18. package/dist-server/controllers/signin.d.ts +4 -1
  19. package/dist-server/controllers/signin.js +17 -1
  20. package/dist-server/controllers/signin.js.map +1 -1
  21. package/dist-server/controllers/signup.js +13 -4
  22. package/dist-server/controllers/signup.js.map +1 -1
  23. package/dist-server/controllers/unlock-user.js +1 -0
  24. package/dist-server/controllers/unlock-user.js.map +1 -1
  25. package/dist-server/controllers/verification.js +1 -0
  26. package/dist-server/controllers/verification.js.map +1 -1
  27. package/dist-server/middlewares/domain-authenticate-middleware.js +0 -4
  28. package/dist-server/middlewares/domain-authenticate-middleware.js.map +1 -1
  29. package/dist-server/middlewares/signin-middleware.js +5 -4
  30. package/dist-server/middlewares/signin-middleware.js.map +1 -1
  31. package/dist-server/middlewares/webauthn-middleware.js +9 -6
  32. package/dist-server/middlewares/webauthn-middleware.js.map +1 -1
  33. package/dist-server/migrations/1548206416130-SeedUser.js +2 -1
  34. package/dist-server/migrations/1548206416130-SeedUser.js.map +1 -1
  35. package/dist-server/router/auth-checkin-router.js +16 -9
  36. package/dist-server/router/auth-checkin-router.js.map +1 -1
  37. package/dist-server/router/auth-private-process-router.js +24 -11
  38. package/dist-server/router/auth-private-process-router.js.map +1 -1
  39. package/dist-server/router/auth-public-process-router.js +20 -9
  40. package/dist-server/router/auth-public-process-router.js.map +1 -1
  41. package/dist-server/router/auth-signin-router.js +10 -4
  42. package/dist-server/router/auth-signin-router.js.map +1 -1
  43. package/dist-server/router/webauthn-router.js.map +1 -1
  44. package/dist-server/routes.js +5 -4
  45. package/dist-server/routes.js.map +1 -1
  46. package/dist-server/service/invitation/invitation-mutation.d.ts +3 -2
  47. package/dist-server/service/invitation/invitation-mutation.js +20 -8
  48. package/dist-server/service/invitation/invitation-mutation.js.map +1 -1
  49. package/dist-server/service/user/user-mutation.d.ts +10 -9
  50. package/dist-server/service/user/user-mutation.js +112 -54
  51. package/dist-server/service/user/user-mutation.js.map +1 -1
  52. package/dist-server/service/user/user-types.d.ts +1 -0
  53. package/dist-server/service/user/user-types.js +4 -0
  54. package/dist-server/service/user/user-types.js.map +1 -1
  55. package/dist-server/service/user/user.d.ts +1 -0
  56. package/dist-server/service/user/user.js +40 -14
  57. package/dist-server/service/user/user.js.map +1 -1
  58. package/dist-server/service/web-auth-credential/web-auth-credential.js.map +1 -1
  59. package/dist-server/templates/account-unlock-email.d.ts +2 -1
  60. package/dist-server/templates/account-unlock-email.js +1 -1
  61. package/dist-server/templates/account-unlock-email.js.map +1 -1
  62. package/dist-server/templates/invitation-email.d.ts +2 -1
  63. package/dist-server/templates/invitation-email.js +1 -1
  64. package/dist-server/templates/invitation-email.js.map +1 -1
  65. package/dist-server/templates/verification-email.d.ts +2 -1
  66. package/dist-server/templates/verification-email.js +1 -1
  67. package/dist-server/templates/verification-email.js.map +1 -1
  68. package/dist-server/tsconfig.tsbuildinfo +1 -1
  69. package/dist-server/utils/access-token-cookie.js +0 -9
  70. package/dist-server/utils/access-token-cookie.js.map +1 -1
  71. package/dist-server/utils/check-user-has-role.d.ts +1 -1
  72. package/dist-server/utils/check-user-has-role.js +2 -2
  73. package/dist-server/utils/check-user-has-role.js.map +1 -1
  74. package/dist-server/utils/get-user-domains.d.ts +1 -2
  75. package/dist-server/utils/get-user-domains.js +27 -23
  76. package/dist-server/utils/get-user-domains.js.map +1 -1
  77. package/package.json +9 -9
  78. package/server/constants/error-code.ts +2 -0
  79. package/server/controllers/change-pwd.ts +3 -2
  80. package/server/controllers/delete-user.ts +16 -13
  81. package/server/controllers/invitation.ts +36 -5
  82. package/server/controllers/profile.ts +29 -2
  83. package/server/controllers/signin.ts +21 -2
  84. package/server/controllers/signup.ts +16 -4
  85. package/server/controllers/unlock-user.ts +1 -0
  86. package/server/controllers/verification.ts +1 -0
  87. package/server/middlewares/domain-authenticate-middleware.ts +0 -5
  88. package/server/middlewares/signin-middleware.ts +5 -4
  89. package/server/middlewares/webauthn-middleware.ts +14 -10
  90. package/server/migrations/1548206416130-SeedUser.ts +2 -1
  91. package/server/router/auth-checkin-router.ts +19 -11
  92. package/server/router/auth-private-process-router.ts +26 -11
  93. package/server/router/auth-public-process-router.ts +22 -10
  94. package/server/router/auth-signin-router.ts +27 -16
  95. package/server/router/webauthn-router.ts +6 -8
  96. package/server/routes.ts +13 -4
  97. package/server/service/invitation/invitation-mutation.ts +24 -9
  98. package/server/service/user/user-mutation.ts +123 -54
  99. package/server/service/user/user-types.ts +3 -0
  100. package/server/service/user/user.ts +41 -14
  101. package/server/service/web-auth-credential/web-auth-credential.ts +0 -1
  102. package/server/templates/account-unlock-email.ts +1 -1
  103. package/server/templates/invitation-email.ts +1 -1
  104. package/server/templates/verification-email.ts +1 -1
  105. package/server/utils/access-token-cookie.ts +0 -11
  106. package/server/utils/check-user-has-role.ts +2 -2
  107. package/server/utils/get-user-domains.ts +30 -27
  108. package/translations/en.json +5 -1
  109. package/translations/ja.json +5 -1
  110. package/translations/ko.json +6 -3
  111. package/translations/ms.json +5 -1
  112. package/translations/zh.json +5 -1
  113. package/dist-server/utils/get-domain-from-hostname.d.ts +0 -1
  114. package/dist-server/utils/get-domain-from-hostname.js +0 -9
  115. package/dist-server/utils/get-domain-from-hostname.js.map +0 -1
  116. package/server/utils/get-domain-from-hostname.ts +0 -7
@@ -7,9 +7,11 @@ import { User } from '../service/user/user'
7
7
  import { AuthError } from '../errors/auth-error'
8
8
 
9
9
  import { WebAuthCredential } from '../service/web-auth-credential/web-auth-credential'
10
- import { verifyRegistrationResponse, verifyAuthenticationResponse } from '@simplewebauthn/server'
11
-
12
- import { AuthenticatorAssertionResponse } from '@simplewebauthn/types'
10
+ import {
11
+ AuthenticatorAssertionResponse,
12
+ verifyRegistrationResponse,
13
+ verifyAuthenticationResponse
14
+ } from '@simplewebauthn/server'
13
15
 
14
16
  passport.use(
15
17
  'webauthn-register',
@@ -29,15 +31,17 @@ passport.use(
29
31
 
30
32
  if (verification.verified) {
31
33
  const { registrationInfo } = verification
32
- const publicKey = Buffer.from(registrationInfo.credentialPublicKey).toString('base64')
33
-
34
+ const publicKey = Buffer.from(registrationInfo.credential.publicKey).toString('base64')
35
+ if (!registrationInfo) {
36
+ return done(null, false)
37
+ }
34
38
  if (user) {
35
39
  const webAuthRepository = getRepository(WebAuthCredential)
36
40
  await webAuthRepository.save({
37
41
  user,
38
- credentialId: registrationInfo.credentialID,
42
+ credentialId: registrationInfo.credential.id,
39
43
  publicKey,
40
- counter: registrationInfo.counter,
44
+ counter: registrationInfo.credential.counter,
41
45
  creator: user,
42
46
  updater: user
43
47
  })
@@ -80,9 +84,9 @@ passport.use(
80
84
  expectedOrigin: origin,
81
85
  expectedRPID: hostname,
82
86
  requireUserVerification: false,
83
- authenticator: {
84
- credentialID: credential.credentialId,
85
- credentialPublicKey: new Uint8Array(Buffer.from(credential.publicKey, 'base64')),
87
+ credential: {
88
+ id: credential.credentialId,
89
+ publicKey: new Uint8Array(Buffer.from(credential.publicKey, 'base64')),
86
90
  counter: credential.counter
87
91
  }
88
92
  })
@@ -6,6 +6,7 @@ import { Domain, getRepository } from '@things-factory/shell'
6
6
  import { User, UserStatus } from '../service/user/user'
7
7
 
8
8
  const ADMIN_ACCOUNT = config.get('adminAccount', {
9
+ username: 'admin',
9
10
  name: 'Admin',
10
11
  email: 'admin@hatiolab.com',
11
12
  password: 'admin'
@@ -42,7 +43,7 @@ export class SeedUsers1548206416130 implements MigrationInterface {
42
43
  logger.error(e)
43
44
  }
44
45
 
45
- const admin = await userRepository.findOne({ where: { email: ILike('admin@hatiolab.com') } })
46
+ const admin = await userRepository.findOne({ where: { email: ILike(ADMIN_ACCOUNT.email) } })
46
47
  domain.owner = admin.id
47
48
 
48
49
  await domainRepository.save(domain)
@@ -9,7 +9,7 @@ import { accepts } from '../utils/accepts'
9
9
  import { clearAccessTokenCookie } from '../utils/access-token-cookie'
10
10
  import { getUserDomains } from '../utils/get-user-domains'
11
11
 
12
- const domainType = config.get('domainType')
12
+ const domainTypes = config.get('domainTypes')
13
13
 
14
14
  export const authCheckinRouter = new Router()
15
15
 
@@ -20,7 +20,9 @@ authCheckinRouter.get('/auth/checkin/:subdomain?', async (context, next) => {
20
20
  let { subdomain } = context.params
21
21
 
22
22
  let domains: Partial<Domain>[] = await getUserDomains(user)
23
- if (domainType) domains = domains.filter(d => d.extType == domainType)
23
+ if (domainTypes) {
24
+ domains = domains.filter(d => !d.extType || domainTypes.includes(d.extType))
25
+ }
24
26
 
25
27
  if (!accepts(header.accept, ['text/html', '*/*'])) {
26
28
  // When request expects non html response
@@ -63,9 +65,15 @@ authCheckinRouter.get('/auth/checkin/:subdomain?', async (context, next) => {
63
65
  pageElement: 'auth-checkin',
64
66
  elementScript: '/auth/checkin.js',
65
67
  data: {
66
- user: { email: user.email, locale: user.locale, name: user.name, userType: user.userType },
68
+ user: {
69
+ username: user.username,
70
+ email: user.email,
71
+ locale: user.locale,
72
+ name: user.name,
73
+ userType: user.userType
74
+ },
67
75
  domains,
68
- domainType,
76
+ domainTypes,
69
77
  redirectTo,
70
78
  message
71
79
  }
@@ -73,7 +81,7 @@ authCheckinRouter.get('/auth/checkin/:subdomain?', async (context, next) => {
73
81
  } catch (e) {
74
82
  clearAccessTokenCookie(context)
75
83
  context.redirect(
76
- `/auth/signin?email=${encodeURIComponent(user.email)}&redirect_to=${encodeURIComponent(redirectTo)}`
84
+ `/auth/signin?username=${encodeURIComponent(user.username)}&redirect_to=${encodeURIComponent(redirectTo)}`
77
85
  )
78
86
  }
79
87
  }
@@ -82,8 +90,8 @@ authCheckinRouter.get('/auth/checkin/:subdomain?', async (context, next) => {
82
90
  authCheckinRouter.get('/auth/domains', async context => {
83
91
  const { user } = context.state
84
92
  var domains = await getUserDomains(user)
85
- if (domainType) {
86
- domains = domains.filter(d => d.extType == domainType)
93
+ if (domainTypes) {
94
+ domains = domains.filter(d => d.extType == domainTypes)
87
95
  }
88
96
 
89
97
  context.body = domains
@@ -95,13 +103,13 @@ async function checkIn(
95
103
  context: ResolverContext
96
104
  ): Promise<void> {
97
105
  const { user }: { user: User } = context.state
98
- const remoteAddress = context.req.headers['x-forwarded-for']
99
- ? (context.req.headers['x-forwarded-for'] as string).split(',')[0].trim()
100
- : context.req.connection.remoteAddress
106
+ const remoteAddress = context.req.headers['x-forwarded-for']
107
+ ? (context.req.headers['x-forwarded-for'] as string).split(',')[0].trim()
108
+ : context.req.connection.remoteAddress
101
109
 
102
110
  await LoginHistory.stamp(checkInDomain, user, remoteAddress)
103
111
 
104
112
  if (redirectTo) {
105
- return context.redirect(getRedirectSubdomainPath(context, checkInDomain.subdomain, redirectTo))
113
+ return context.redirect(getRedirectSubdomainPath(context, checkInDomain, redirectTo))
106
114
  }
107
115
  }
@@ -11,7 +11,7 @@ import { User } from '../service/user/user'
11
11
  import { clearAccessTokenCookie, setAccessTokenCookie } from '../utils/access-token-cookie'
12
12
  import { getUserDomains } from '../utils/get-user-domains'
13
13
 
14
- const domainType = config.get('domainType')
14
+ const domainTypes = config.get('domainTypes')
15
15
  const languages = config.get('i18n/languages') || []
16
16
 
17
17
  export const authPrivateProcessRouter = new Router({
@@ -43,19 +43,25 @@ authPrivateProcessRouter
43
43
  .post('/delete-user', async (context, next) => {
44
44
  const { t, session } = context
45
45
  var { user } = context.state
46
- var { email: userEmail } = user
46
+ var { id: userId } = user
47
47
 
48
- var { password, email } = context.request.body
48
+ var { password, username } = context.request.body
49
49
 
50
50
  const userRepo = getRepository(User)
51
- const userInfo = await userRepo.findOne({
52
- where: {
53
- email: ILike(userEmail)
54
- },
51
+
52
+ var userInfo = await userRepo.findOne({
53
+ where: { username },
55
54
  relations: ['domains']
56
55
  })
57
56
 
58
- if (email != userEmail || !User.verify(userInfo.password, password, userInfo.salt)) {
57
+ if (!userInfo && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
58
+ userInfo = await userRepo.findOne({
59
+ where: { email: ILike(username) },
60
+ relations: ['domains']
61
+ })
62
+ }
63
+
64
+ if (userInfo.id != userId || !User.verify(userInfo.password, password, userInfo.salt)) {
59
65
  context.status = 401
60
66
  context.body = t('error.user validation failed')
61
67
  return
@@ -77,7 +83,7 @@ authPrivateProcessRouter
77
83
  }
78
84
 
79
85
  let domains: Partial<Domain>[] = await getUserDomains(user)
80
- domains = domains.filter((d: Domain) => d.extType == domainType)
86
+ domains = domains.filter((d: Domain) => !d.extType || domainTypes.includes(d.extType))
81
87
 
82
88
  var privileges = await User.getPrivilegesByDomain(user, domain)
83
89
 
@@ -89,6 +95,7 @@ authPrivateProcessRouter
89
95
 
90
96
  context.body = {
91
97
  user: {
98
+ username: user.username,
92
99
  email: user.email,
93
100
  name: user.name,
94
101
  userType: user.userType,
@@ -97,10 +104,18 @@ authPrivateProcessRouter
97
104
  unsafeIP,
98
105
  privileges
99
106
  },
100
- domains,
107
+ domains: domains.map(({ id, name, description, subdomain, extType, brandName, brandImage }) => {
108
+ return {
109
+ name,
110
+ description,
111
+ subdomain,
112
+ extType
113
+ }
114
+ }),
101
115
  domain: domain && {
102
116
  name: domain.name,
103
- subdomain: domain.subdomain
117
+ subdomain: domain.subdomain,
118
+ type: domain.extType
104
119
  },
105
120
  languages
106
121
  }
@@ -1,4 +1,5 @@
1
1
  import Router from 'koa-router'
2
+ import { ILike } from 'typeorm'
2
3
 
3
4
  import { config } from '@things-factory/env'
4
5
  import { getRepository, getSiteRootPath } from '@things-factory/shell'
@@ -31,16 +32,26 @@ export const authPublicProcessRouter = new Router({
31
32
  })
32
33
 
33
34
  authPublicProcessRouter.post('/join', async (context, next) => {
34
- const { email } = context.request.body || {}
35
+ const { username } = context.request.body || {}
35
36
 
36
- const user: User = await getRepository(User).findOneBy({
37
- email
37
+ const repository = getRepository(User)
38
+
39
+ var user = await repository.findOne({
40
+ where: { username },
41
+ relations: ['domains']
38
42
  })
39
43
 
44
+ if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
45
+ user = await repository.findOne({
46
+ where: { email: ILike(username) },
47
+ relations: ['domains']
48
+ })
49
+ }
50
+
40
51
  if (user) {
41
- context.redirect(`/auth/signin?email=${email}`)
52
+ context.redirect(`/auth/signin?username=${username}`)
42
53
  } else {
43
- context.redirect(`/auth/signup?email=${email}`)
54
+ context.redirect(`/auth/signup?username=${username}`)
44
55
  }
45
56
  })
46
57
 
@@ -200,10 +211,9 @@ authPublicProcessRouter.post('/forgot-password', async (context, next) => {
200
211
 
201
212
  authPublicProcessRouter.post('/reset-password', async (context, next) => {
202
213
  const { header, t } = context
214
+ const { password, token } = context.request.body
203
215
 
204
216
  try {
205
- const { password, token } = context.request.body
206
-
207
217
  if (!(token && password)) {
208
218
  let message = t('error.token or password is invalid')
209
219
 
@@ -232,7 +242,7 @@ authPublicProcessRouter.post('/reset-password', async (context, next) => {
232
242
 
233
243
  await resetPassword(token, password, context)
234
244
 
235
- var message = t('text.password reset succeed')
245
+ var message = t('text.password changed successfully')
236
246
  context.body = message
237
247
 
238
248
  clearAccessTokenCookie(context)
@@ -255,10 +265,12 @@ authPublicProcessRouter.post('/reset-password', async (context, next) => {
255
265
 
256
266
  if (accepts(header.accept, ['text/html', '*/*'])) {
257
267
  await context.render('auth-page', {
258
- pageElement: 'auth-result',
259
- elementScript: '/auth/result.js',
268
+ pageElement: 'reset-password',
269
+ elementScript: '/auth/reset-password.js',
260
270
  data: {
271
+ token,
261
272
  message: e.message,
273
+ passwordRule,
262
274
  disableUserSignupProcess,
263
275
  disableUserFavoredLanguage,
264
276
  languages
@@ -28,13 +28,13 @@ authSigninRouter.get(
28
28
  await next()
29
29
  },
30
30
  async (context, next) => {
31
- const { redirect_to, email } = context.query
31
+ const { redirect_to, username } = context.query
32
32
 
33
33
  await context.render('auth-page', {
34
34
  pageElement: 'auth-signin',
35
35
  elementScript: '/auth/signin.js',
36
36
  data: {
37
- email,
37
+ username,
38
38
  redirectTo: redirect_to,
39
39
  ssoLinks: SSOLinks,
40
40
  disableUserSignupProcess,
@@ -45,21 +45,32 @@ authSigninRouter.get(
45
45
  }
46
46
  )
47
47
 
48
- authSigninRouter.post('/auth/signin', signinMiddleware, async (context, next) => {
49
- const { request, t } = context
50
- const { token, user, domain } = context.state
51
- const { body: reqBody, header } = request
48
+ authSigninRouter.post(
49
+ '/auth/signin',
50
+ async (ctx, next) => {
51
+ /* For backward compatibility, cover the case of logging in with email instead of username */
52
+ if (!ctx.request.body.username && ctx.request.body.email) {
53
+ ctx.request.body.username = ctx.request.body.email
54
+ }
55
+ await next()
56
+ },
57
+ signinMiddleware,
58
+ async (context, next) => {
59
+ const { request, t } = context
60
+ const { token, domain } = context.state
61
+ const { body: reqBody, header } = request
52
62
 
53
- if (!accepts(header.accept, ['text/html', '*/*'])) {
54
- context.body = token
55
- return
56
- }
63
+ if (!accepts(header.accept, ['text/html', '*/*'])) {
64
+ context.body = token
65
+ return
66
+ }
57
67
 
58
- var redirectTo = `/auth/checkin${domain ? '/' + domain.subdomain : ''}?redirect_to=${encodeURIComponent(
59
- reqBody.redirectTo || '/'
60
- )}`
68
+ var redirectTo = `/auth/checkin${domain ? '/' + domain.subdomain : ''}?redirect_to=${encodeURIComponent(
69
+ reqBody.redirectTo || '/'
70
+ )}`
61
71
 
62
- setAccessTokenCookie(context, token)
72
+ setAccessTokenCookie(context, token)
63
73
 
64
- context.redirect(redirectTo)
65
- })
74
+ context.redirect(redirectTo)
75
+ }
76
+ )
@@ -5,11 +5,8 @@ import { appPackage } from '@things-factory/env'
5
5
  import { generateRegistrationOptions, generateAuthenticationOptions } from '@simplewebauthn/server'
6
6
 
7
7
  import { WebAuthCredential } from '../service/web-auth-credential/web-auth-credential'
8
- import {
9
- PublicKeyCredentialCreationOptionsJSON,
10
- } from '@simplewebauthn/server/script/deps'
11
8
  import { setAccessTokenCookie } from '../utils/access-token-cookie'
12
- import { createWebAuthnMiddleware } from '../middlewares/webauthn-middleware';
9
+ import { createWebAuthnMiddleware } from '../middlewares/webauthn-middleware'
13
10
 
14
11
  export const webAuthnGlobalPublicRouter = new Router()
15
12
  export const webAuthnGlobalPrivateRouter = new Router()
@@ -53,7 +50,7 @@ webAuthnGlobalPrivateRouter.get('/auth/register-webauthn/challenge', async (cont
53
50
  context.body = options
54
51
  })
55
52
 
56
- webAuthnGlobalPrivateRouter.post('/auth/verify-registration', createWebAuthnMiddleware('webauthn-register'));
53
+ webAuthnGlobalPrivateRouter.post('/auth/verify-registration', createWebAuthnMiddleware('webauthn-register'))
57
54
 
58
55
  webAuthnGlobalPublicRouter.get('/auth/signin-webauthn/challenge', async (context, next) => {
59
56
  const rpID = context.hostname
@@ -68,9 +65,10 @@ webAuthnGlobalPublicRouter.get('/auth/signin-webauthn/challenge', async (context
68
65
  })
69
66
 
70
67
  webAuthnGlobalPublicRouter.post(
71
- '/auth/signin-webauthn', createWebAuthnMiddleware('webauthn-login'),
68
+ '/auth/signin-webauthn',
69
+ createWebAuthnMiddleware('webauthn-login'),
72
70
  async (context, next) => {
73
- const { domain, user } = context. state
71
+ const { domain, user } = context.state
74
72
  const { request } = context
75
73
  const { body: reqBody } = request
76
74
 
@@ -82,6 +80,6 @@ webAuthnGlobalPublicRouter.post(
82
80
  /* 2단계 인터렉션 때문에 브라우저에서 fetch(...)로 진행될 것이므로, redirect(3xx) 응답으로 처리할 수 없다. 따라서, 데이타로 redirectURL를 응답한다. */
83
81
  context.body = { redirectURL, verified: true }
84
82
 
85
- await next();
83
+ await next()
86
84
  }
87
85
  )
package/server/routes.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { config } from '@things-factory/env'
2
+ import { getRoutePrefixForDomainType } from '@things-factory/shell'
2
3
 
3
4
  import { domainAuthenticateMiddleware, jwtAuthenticateMiddleware } from './middlewares'
4
5
  import {
@@ -17,7 +18,7 @@ import {
17
18
 
18
19
  import { setAccessTokenCookie } from './utils/access-token-cookie'
19
20
 
20
- const isPathBaseDomain = !config.get('subdomain') && !config.get('useVirtualHostBasedDomain')
21
+ const isPathBaseDomain = !config.get('subdomain')
21
22
 
22
23
  process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
23
24
  globalPublicRouter.use(siteRootRouter.routes(), siteRootRouter.allowedMethods())
@@ -39,8 +40,8 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
39
40
  process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
40
41
  globalPrivateRouter.use(jwtAuthenticateMiddleware)
41
42
 
42
- /* globalPrivateRouter based nested-routers */
43
43
  globalPrivateRouter.use(authCheckinRouter.routes(), authCheckinRouter.allowedMethods())
44
+ /* globalPrivateRouter based nested-routers */
44
45
  globalPrivateRouter.use(authPrivateProcessRouter.routes(), authPrivateProcessRouter.allowedMethods())
45
46
  globalPrivateRouter.use(webAuthnGlobalPrivateRouter.routes(), webAuthnGlobalPrivateRouter.allowedMethods())
46
47
  })
@@ -64,8 +65,16 @@ process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRo
64
65
  // pathBaseDomainRouter는 history-fallback의 경우에 인증 처리를 하기 위한 라우터이다.
65
66
  // (보통, URL 링크등을 통해서 domain path URL로 바로 요청하는 경우에 해당한다.)
66
67
  // pathBaseDomainRouter는 domain path를 domain-private-router를 사용하는 것을 전제로 한다.
67
- domainPrivateRouter.use('/domain/:domain/oauth', oauth2AuthorizeRouter.routes(), oauth2AuthorizeRouter.allowedMethods())
68
- domainPrivateRouter.use('/domain', pathBaseDomainRouter.routes(), pathBaseDomainRouter.allowedMethods())
68
+ domainPrivateRouter.use(
69
+ `/${getRoutePrefixForDomainType()}/:domain/oauth`,
70
+ oauth2AuthorizeRouter.routes(),
71
+ oauth2AuthorizeRouter.allowedMethods()
72
+ )
73
+ domainPrivateRouter.use(
74
+ `/${getRoutePrefixForDomainType()}`,
75
+ pathBaseDomainRouter.routes(),
76
+ pathBaseDomainRouter.allowedMethods()
77
+ )
69
78
  }
70
79
 
71
80
  // Client Routing : path 확장자가 없는 경우는 대부분 client 라우팅에 해당한다.
@@ -1,8 +1,11 @@
1
+ import { ILike } from 'typeorm'
2
+
1
3
  import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'
2
4
  import { GraphQLEmailAddress } from 'graphql-scalars'
3
5
 
4
6
  import { getRepository } from '@things-factory/shell'
5
7
 
8
+ import { User, UserStatus } from '../../service/user/user'
6
9
  import { sendInvitationEmail } from '../../controllers/invitation'
7
10
  import { Invitation } from './invitation'
8
11
 
@@ -32,32 +35,44 @@ export class InvitationMutation {
32
35
  @Arg('type') type: string,
33
36
  @Ctx() context: ResolverContext
34
37
  ) {
35
- const repository = getRepository(Invitation)
38
+ const { user: updater } = context.state
39
+ const invitationRepository = getRepository(Invitation)
36
40
 
37
- const oldone = await repository.findOneBy({
38
- email,
39
- type,
40
- reference
41
+ var user = await getRepository(User).findOne({
42
+ where: {
43
+ email: ILike(email),
44
+ status: UserStatus.ACTIVATED
45
+ }
41
46
  })
42
47
 
43
- // TODO send invitation
48
+ if (!user) {
49
+ throw new Error(`user not found: ${email}`)
50
+ }
51
+
44
52
  await sendInvitationEmail({
45
53
  invitation: {
46
54
  email,
47
55
  reference,
48
56
  type
49
57
  },
58
+ user,
50
59
  context
51
60
  })
52
61
 
62
+ const oldone = await invitationRepository.findOneBy({
63
+ email,
64
+ type,
65
+ reference
66
+ })
67
+
53
68
  // update or create
54
- return await repository.save({
69
+ return await invitationRepository.save({
70
+ creator: updater,
55
71
  ...oldone, // take only id from oldone for update
56
72
  email,
57
73
  reference,
58
74
  type,
59
- creator: context.state.user,
60
- updater: context.state.user
75
+ updater: updater
61
76
  })
62
77
  }
63
78
  }