@things-factory/auth-base 8.0.5 → 8.0.8
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/client/auth.ts +0 -4
- package/dist-client/auth.js +0 -3
- package/dist-client/auth.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/constants/error-code.d.ts +2 -0
- package/dist-server/constants/error-code.js +3 -1
- package/dist-server/constants/error-code.js.map +1 -1
- package/dist-server/controllers/change-pwd.js +2 -2
- package/dist-server/controllers/change-pwd.js.map +1 -1
- package/dist-server/controllers/delete-user.js +13 -12
- package/dist-server/controllers/delete-user.js.map +1 -1
- package/dist-server/controllers/invitation.d.ts +2 -1
- package/dist-server/controllers/invitation.js +30 -5
- package/dist-server/controllers/invitation.js.map +1 -1
- package/dist-server/controllers/profile.d.ts +4 -3
- package/dist-server/controllers/profile.js +20 -2
- package/dist-server/controllers/profile.js.map +1 -1
- package/dist-server/controllers/signin.d.ts +4 -1
- package/dist-server/controllers/signin.js +17 -1
- package/dist-server/controllers/signin.js.map +1 -1
- package/dist-server/controllers/signup.js +13 -4
- package/dist-server/controllers/signup.js.map +1 -1
- package/dist-server/controllers/unlock-user.js +1 -0
- package/dist-server/controllers/unlock-user.js.map +1 -1
- package/dist-server/controllers/verification.js +1 -0
- package/dist-server/controllers/verification.js.map +1 -1
- package/dist-server/middlewares/domain-authenticate-middleware.js +0 -4
- package/dist-server/middlewares/domain-authenticate-middleware.js.map +1 -1
- package/dist-server/middlewares/signin-middleware.js +5 -4
- package/dist-server/middlewares/signin-middleware.js.map +1 -1
- package/dist-server/middlewares/webauthn-middleware.js +9 -6
- package/dist-server/middlewares/webauthn-middleware.js.map +1 -1
- package/dist-server/migrations/1548206416130-SeedUser.js +2 -1
- package/dist-server/migrations/1548206416130-SeedUser.js.map +1 -1
- package/dist-server/router/auth-checkin-router.js +16 -9
- package/dist-server/router/auth-checkin-router.js.map +1 -1
- package/dist-server/router/auth-private-process-router.js +24 -11
- package/dist-server/router/auth-private-process-router.js.map +1 -1
- package/dist-server/router/auth-public-process-router.js +20 -9
- package/dist-server/router/auth-public-process-router.js.map +1 -1
- package/dist-server/router/auth-signin-router.js +10 -4
- package/dist-server/router/auth-signin-router.js.map +1 -1
- package/dist-server/router/webauthn-router.js.map +1 -1
- package/dist-server/routes.js +2 -2
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/invitation/invitation-mutation.d.ts +3 -2
- package/dist-server/service/invitation/invitation-mutation.js +20 -8
- package/dist-server/service/invitation/invitation-mutation.js.map +1 -1
- package/dist-server/service/user/user-mutation.d.ts +10 -9
- package/dist-server/service/user/user-mutation.js +112 -54
- package/dist-server/service/user/user-mutation.js.map +1 -1
- package/dist-server/service/user/user-types.d.ts +1 -0
- package/dist-server/service/user/user-types.js +4 -0
- package/dist-server/service/user/user-types.js.map +1 -1
- package/dist-server/service/user/user.d.ts +1 -0
- package/dist-server/service/user/user.js +40 -14
- package/dist-server/service/user/user.js.map +1 -1
- package/dist-server/service/web-auth-credential/web-auth-credential.js.map +1 -1
- package/dist-server/templates/account-unlock-email.d.ts +2 -1
- package/dist-server/templates/account-unlock-email.js +1 -1
- package/dist-server/templates/account-unlock-email.js.map +1 -1
- package/dist-server/templates/invitation-email.d.ts +2 -1
- package/dist-server/templates/invitation-email.js +1 -1
- package/dist-server/templates/invitation-email.js.map +1 -1
- package/dist-server/templates/verification-email.d.ts +2 -1
- package/dist-server/templates/verification-email.js +1 -1
- package/dist-server/templates/verification-email.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/dist-server/utils/access-token-cookie.js +0 -9
- package/dist-server/utils/access-token-cookie.js.map +1 -1
- package/dist-server/utils/check-user-has-role.d.ts +1 -1
- package/dist-server/utils/check-user-has-role.js +2 -2
- package/dist-server/utils/check-user-has-role.js.map +1 -1
- package/dist-server/utils/get-user-domains.d.ts +1 -2
- package/dist-server/utils/get-user-domains.js +27 -23
- package/dist-server/utils/get-user-domains.js.map +1 -1
- package/package.json +9 -9
- package/server/constants/error-code.ts +2 -0
- package/server/controllers/change-pwd.ts +3 -2
- package/server/controllers/delete-user.ts +16 -13
- package/server/controllers/invitation.ts +36 -5
- package/server/controllers/profile.ts +29 -2
- package/server/controllers/signin.ts +21 -2
- package/server/controllers/signup.ts +16 -4
- package/server/controllers/unlock-user.ts +1 -0
- package/server/controllers/verification.ts +1 -0
- package/server/middlewares/domain-authenticate-middleware.ts +0 -5
- package/server/middlewares/signin-middleware.ts +5 -4
- package/server/middlewares/webauthn-middleware.ts +14 -10
- package/server/migrations/1548206416130-SeedUser.ts +2 -1
- package/server/router/auth-checkin-router.ts +19 -11
- package/server/router/auth-private-process-router.ts +26 -11
- package/server/router/auth-public-process-router.ts +22 -10
- package/server/router/auth-signin-router.ts +27 -16
- package/server/router/webauthn-router.ts +6 -8
- package/server/routes.ts +6 -2
- package/server/service/invitation/invitation-mutation.ts +24 -9
- package/server/service/user/user-mutation.ts +123 -54
- package/server/service/user/user-types.ts +3 -0
- package/server/service/user/user.ts +41 -14
- package/server/service/web-auth-credential/web-auth-credential.ts +0 -1
- package/server/templates/account-unlock-email.ts +1 -1
- package/server/templates/invitation-email.ts +1 -1
- package/server/templates/verification-email.ts +1 -1
- package/server/utils/access-token-cookie.ts +0 -11
- package/server/utils/check-user-has-role.ts +2 -2
- package/server/utils/get-user-domains.ts +30 -27
- package/translations/en.json +5 -1
- package/translations/ja.json +5 -1
- package/translations/ko.json +6 -3
- package/translations/ms.json +5 -1
- package/translations/zh.json +5 -1
- package/dist-server/utils/get-domain-from-hostname.d.ts +0 -1
- package/dist-server/utils/get-domain-from-hostname.js +0 -9
- package/dist-server/utils/get-domain-from-hostname.js.map +0 -1
- 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 {
|
11
|
-
|
12
|
-
|
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.
|
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.
|
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
|
-
|
84
|
-
|
85
|
-
|
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(
|
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
|
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 (
|
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: {
|
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
|
-
|
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?
|
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 (
|
86
|
-
domains = domains.filter(d => d.extType ==
|
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
|
-
|
100
|
-
|
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
|
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
|
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 {
|
46
|
+
var { id: userId } = user
|
47
47
|
|
48
|
-
var { password,
|
48
|
+
var { password, username } = context.request.body
|
49
49
|
|
50
50
|
const userRepo = getRepository(User)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
},
|
51
|
+
|
52
|
+
var userInfo = await userRepo.findOne({
|
53
|
+
where: { username },
|
55
54
|
relations: ['domains']
|
56
55
|
})
|
57
56
|
|
58
|
-
if (
|
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
|
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 {
|
35
|
+
const { username } = context.request.body || {}
|
35
36
|
|
36
|
-
const
|
37
|
-
|
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?
|
52
|
+
context.redirect(`/auth/signin?username=${username}`)
|
42
53
|
} else {
|
43
|
-
context.redirect(`/auth/signup?
|
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
|
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: '
|
259
|
-
elementScript: '/auth/
|
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,
|
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
|
-
|
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(
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
63
|
+
if (!accepts(header.accept, ['text/html', '*/*'])) {
|
64
|
+
context.body = token
|
65
|
+
return
|
66
|
+
}
|
57
67
|
|
58
|
-
|
59
|
-
|
60
|
-
|
68
|
+
var redirectTo = `/auth/checkin${domain ? '/' + domain.subdomain : ''}?redirect_to=${encodeURIComponent(
|
69
|
+
reqBody.redirectTo || '/'
|
70
|
+
)}`
|
61
71
|
|
62
|
-
|
72
|
+
setAccessTokenCookie(context, token)
|
63
73
|
|
64
|
-
|
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',
|
68
|
+
'/auth/signin-webauthn',
|
69
|
+
createWebAuthnMiddleware('webauthn-login'),
|
72
70
|
async (context, next) => {
|
73
|
-
const { domain, user } = context.
|
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
@@ -17,7 +17,7 @@ import {
|
|
17
17
|
|
18
18
|
import { setAccessTokenCookie } from './utils/access-token-cookie'
|
19
19
|
|
20
|
-
const isPathBaseDomain = !config.get('subdomain')
|
20
|
+
const isPathBaseDomain = !config.get('subdomain')
|
21
21
|
|
22
22
|
process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
|
23
23
|
globalPublicRouter.use(siteRootRouter.routes(), siteRootRouter.allowedMethods())
|
@@ -64,7 +64,11 @@ process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRo
|
|
64
64
|
// pathBaseDomainRouter는 history-fallback의 경우에 인증 처리를 하기 위한 라우터이다.
|
65
65
|
// (보통, URL 링크등을 통해서 domain path URL로 바로 요청하는 경우에 해당한다.)
|
66
66
|
// pathBaseDomainRouter는 domain path를 domain-private-router를 사용하는 것을 전제로 한다.
|
67
|
-
domainPrivateRouter.use(
|
67
|
+
domainPrivateRouter.use(
|
68
|
+
'/:domainType/:domain/oauth',
|
69
|
+
oauth2AuthorizeRouter.routes(),
|
70
|
+
oauth2AuthorizeRouter.allowedMethods()
|
71
|
+
)
|
68
72
|
domainPrivateRouter.use('/domain', pathBaseDomainRouter.routes(), pathBaseDomainRouter.allowedMethods())
|
69
73
|
}
|
70
74
|
|
@@ -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
|
38
|
+
const { user: updater } = context.state
|
39
|
+
const invitationRepository = getRepository(Invitation)
|
36
40
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
+
var user = await getRepository(User).findOne({
|
42
|
+
where: {
|
43
|
+
email: ILike(email),
|
44
|
+
status: UserStatus.ACTIVATED
|
45
|
+
}
|
41
46
|
})
|
42
47
|
|
43
|
-
|
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
|
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
|
-
|
60
|
-
updater: context.state.user
|
75
|
+
updater: updater
|
61
76
|
})
|
62
77
|
}
|
63
78
|
}
|