@things-factory/auth-base 8.0.0-beta.1 → 8.0.0-beta.2
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 +6 -6
- package/client/actions/auth.ts +0 -24
- package/client/auth.ts +0 -272
- package/client/bootstrap.ts +0 -47
- package/client/directive/privileged.ts +0 -28
- package/client/index.ts +0 -4
- package/client/profiled.ts +0 -83
- package/client/reducers/auth.ts +0 -31
- package/client/verify-webauthn.ts +0 -86
- package/server/constants/error-code.ts +0 -22
- package/server/constants/error-message.ts +0 -0
- package/server/constants/max-age.ts +0 -1
- package/server/controllers/auth.ts +0 -5
- package/server/controllers/change-pwd.ts +0 -100
- package/server/controllers/checkin.ts +0 -21
- package/server/controllers/delete-user.ts +0 -71
- package/server/controllers/invitation.ts +0 -163
- package/server/controllers/profile.ts +0 -55
- package/server/controllers/reset-password.ts +0 -126
- package/server/controllers/signin.ts +0 -98
- package/server/controllers/signup.ts +0 -72
- package/server/controllers/unlock-user.ts +0 -62
- package/server/controllers/utils/make-invitation-token.ts +0 -5
- package/server/controllers/utils/make-verification-token.ts +0 -4
- package/server/controllers/utils/password-rule.ts +0 -120
- package/server/controllers/utils/save-invitation-token.ts +0 -10
- package/server/controllers/utils/save-verification-token.ts +0 -12
- package/server/controllers/verification.ts +0 -84
- package/server/errors/auth-error.ts +0 -24
- package/server/errors/index.ts +0 -2
- package/server/errors/user-domain-not-match-error.ts +0 -29
- package/server/index.ts +0 -37
- package/server/middlewares/authenticate-401-middleware.ts +0 -114
- package/server/middlewares/domain-authenticate-middleware.ts +0 -78
- package/server/middlewares/graphql-authenticate-middleware.ts +0 -13
- package/server/middlewares/index.ts +0 -67
- package/server/middlewares/jwt-authenticate-middleware.ts +0 -84
- package/server/middlewares/signin-middleware.ts +0 -55
- package/server/middlewares/webauthn-middleware.ts +0 -126
- package/server/migrations/1548206416130-SeedUser.ts +0 -60
- package/server/migrations/1566805283882-SeedPrivilege.ts +0 -28
- package/server/migrations/index.ts +0 -9
- package/server/router/auth-checkin-router.ts +0 -113
- package/server/router/auth-private-process-router.ts +0 -114
- package/server/router/auth-public-process-router.ts +0 -314
- package/server/router/auth-signin-router.ts +0 -55
- package/server/router/auth-signup-router.ts +0 -95
- package/server/router/index.ts +0 -9
- package/server/router/oauth2/index.ts +0 -2
- package/server/router/oauth2/oauth2-authorize-router.ts +0 -81
- package/server/router/oauth2/oauth2-router.ts +0 -165
- package/server/router/oauth2/oauth2-server.ts +0 -262
- package/server/router/oauth2/passport-oauth2-client-password.ts +0 -87
- package/server/router/oauth2/passport-refresh-token.ts +0 -87
- package/server/router/path-base-domain-router.ts +0 -8
- package/server/router/site-root-router.ts +0 -48
- package/server/router/webauthn-router.ts +0 -149
- package/server/routes.ts +0 -80
- package/server/service/app-binding/app-binding-mutation.ts +0 -22
- package/server/service/app-binding/app-binding-query.ts +0 -92
- package/server/service/app-binding/app-binding-types.ts +0 -11
- package/server/service/app-binding/app-binding.ts +0 -17
- package/server/service/app-binding/index.ts +0 -4
- package/server/service/appliance/appliance-mutation.ts +0 -113
- package/server/service/appliance/appliance-query.ts +0 -76
- package/server/service/appliance/appliance-types.ts +0 -56
- package/server/service/appliance/appliance.ts +0 -133
- package/server/service/appliance/index.ts +0 -6
- package/server/service/application/application-mutation.ts +0 -104
- package/server/service/application/application-query.ts +0 -98
- package/server/service/application/application-types.ts +0 -76
- package/server/service/application/application.ts +0 -216
- package/server/service/application/index.ts +0 -6
- package/server/service/auth-provider/auth-provider-mutation.ts +0 -159
- package/server/service/auth-provider/auth-provider-parameter-spec.ts +0 -24
- package/server/service/auth-provider/auth-provider-query.ts +0 -88
- package/server/service/auth-provider/auth-provider-type.ts +0 -67
- package/server/service/auth-provider/auth-provider.ts +0 -155
- package/server/service/auth-provider/index.ts +0 -7
- package/server/service/domain-generator/domain-generator-mutation.ts +0 -117
- package/server/service/domain-generator/domain-generator-types.ts +0 -46
- package/server/service/domain-generator/index.ts +0 -3
- package/server/service/granted-role/granted-role-mutation.ts +0 -156
- package/server/service/granted-role/granted-role-query.ts +0 -60
- package/server/service/granted-role/granted-role.ts +0 -27
- package/server/service/granted-role/index.ts +0 -6
- package/server/service/index.ts +0 -90
- package/server/service/invitation/index.ts +0 -6
- package/server/service/invitation/invitation-mutation.ts +0 -78
- package/server/service/invitation/invitation-query.ts +0 -33
- package/server/service/invitation/invitation-types.ts +0 -11
- package/server/service/invitation/invitation.ts +0 -63
- package/server/service/login-history/index.ts +0 -5
- package/server/service/login-history/login-history-query.ts +0 -51
- package/server/service/login-history/login-history-type.ts +0 -12
- package/server/service/login-history/login-history.ts +0 -45
- package/server/service/partner/index.ts +0 -6
- package/server/service/partner/partner-mutation.ts +0 -61
- package/server/service/partner/partner-query.ts +0 -102
- package/server/service/partner/partner-types.ts +0 -11
- package/server/service/partner/partner.ts +0 -57
- package/server/service/password-history/index.ts +0 -3
- package/server/service/password-history/password-history.ts +0 -16
- package/server/service/privilege/index.ts +0 -6
- package/server/service/privilege/privilege-directive.ts +0 -77
- package/server/service/privilege/privilege-mutation.ts +0 -92
- package/server/service/privilege/privilege-query.ts +0 -94
- package/server/service/privilege/privilege-types.ts +0 -60
- package/server/service/privilege/privilege.ts +0 -102
- package/server/service/role/index.ts +0 -6
- package/server/service/role/role-mutation.ts +0 -109
- package/server/service/role/role-query.ts +0 -155
- package/server/service/role/role-types.ts +0 -81
- package/server/service/role/role.ts +0 -72
- package/server/service/user/domain-query.ts +0 -24
- package/server/service/user/index.ts +0 -7
- package/server/service/user/user-mutation.ts +0 -482
- package/server/service/user/user-query.ts +0 -145
- package/server/service/user/user-types.ts +0 -100
- package/server/service/user/user.ts +0 -381
- package/server/service/users-auth-providers/index.ts +0 -5
- package/server/service/users-auth-providers/users-auth-providers.ts +0 -71
- package/server/service/verification-token/index.ts +0 -3
- package/server/service/verification-token/verification-token.ts +0 -60
- package/server/service/web-auth-credential/index.ts +0 -3
- package/server/service/web-auth-credential/web-auth-credential.ts +0 -67
- package/server/templates/account-unlock-email.ts +0 -65
- package/server/templates/invitation-email.ts +0 -66
- package/server/templates/reset-password-email.ts +0 -65
- package/server/templates/verification-email.ts +0 -66
- package/server/types.ts +0 -21
- package/server/utils/accepts.ts +0 -11
- package/server/utils/access-token-cookie.ts +0 -61
- package/server/utils/check-permission.ts +0 -52
- package/server/utils/check-user-belongs-domain.ts +0 -19
- package/server/utils/check-user-has-role.ts +0 -29
- package/server/utils/encrypt-state.ts +0 -22
- package/server/utils/get-aes-256-key.ts +0 -13
- package/server/utils/get-domain-from-hostname.ts +0 -7
- package/server/utils/get-domain-users.ts +0 -38
- package/server/utils/get-secret.ts +0 -13
- package/server/utils/get-user-domains.ts +0 -112
@@ -1,62 +0,0 @@
|
|
1
|
-
import { URL } from 'url'
|
2
|
-
|
3
|
-
import { sendEmail } from '@things-factory/email-base'
|
4
|
-
import { getRepository } from '@things-factory/shell'
|
5
|
-
|
6
|
-
import { User, UserStatus } from '../service/user/user'
|
7
|
-
import { VerificationToken, VerificationTokenType } from '../service/verification-token/verification-token'
|
8
|
-
import { getUnlockUserEmailForm } from '../templates/account-unlock-email'
|
9
|
-
import { makeVerificationToken } from './utils/make-verification-token'
|
10
|
-
import { saveVerificationToken } from './utils/save-verification-token'
|
11
|
-
|
12
|
-
export async function sendUnlockUserEmail({ user, context }) {
|
13
|
-
try {
|
14
|
-
var token = makeVerificationToken()
|
15
|
-
var verifaction = await saveVerificationToken(user.id, token, VerificationTokenType.UNLOCK)
|
16
|
-
|
17
|
-
if (verifaction) {
|
18
|
-
var serviceUrl = new URL(`/auth/unlock-user?token=${token}`, context.header.referer)
|
19
|
-
await sendEmail({
|
20
|
-
receiver: user.email,
|
21
|
-
subject: 'Your account is locked',
|
22
|
-
content: getUnlockUserEmailForm({
|
23
|
-
username: user.username,
|
24
|
-
name: user.name,
|
25
|
-
resetUrl: serviceUrl
|
26
|
-
})
|
27
|
-
})
|
28
|
-
|
29
|
-
return true
|
30
|
-
}
|
31
|
-
} catch (e) {
|
32
|
-
return false
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
export async function unlockUser(token, password) {
|
37
|
-
var { userId } = await getRepository(VerificationToken).findOne({
|
38
|
-
where: {
|
39
|
-
token,
|
40
|
-
type: VerificationTokenType.UNLOCK
|
41
|
-
}
|
42
|
-
})
|
43
|
-
|
44
|
-
if (!userId) return false
|
45
|
-
|
46
|
-
var userInfo = await getRepository(User).findOneBy({ id: userId })
|
47
|
-
if (!userInfo) return false
|
48
|
-
if (userInfo.status != UserStatus.LOCKED) return false
|
49
|
-
|
50
|
-
userInfo.status = UserStatus.ACTIVATED
|
51
|
-
userInfo.password = User.encode(password, userInfo.salt)
|
52
|
-
userInfo.failCount = 0
|
53
|
-
|
54
|
-
await getRepository(User).save(userInfo)
|
55
|
-
await getRepository(VerificationToken).delete({
|
56
|
-
userId,
|
57
|
-
token,
|
58
|
-
type: VerificationTokenType.UNLOCK
|
59
|
-
})
|
60
|
-
|
61
|
-
return true
|
62
|
-
}
|
@@ -1,120 +0,0 @@
|
|
1
|
-
import i18next from 'i18next'
|
2
|
-
|
3
|
-
import { config } from '@things-factory/env'
|
4
|
-
|
5
|
-
import { PASSWORD_PATTERN_NOT_MATCHED } from '../../constants/error-code'
|
6
|
-
import { AuthError } from '../../errors/auth-error'
|
7
|
-
|
8
|
-
const passwordConfig = config.get('password') || {
|
9
|
-
lowerCase: true,
|
10
|
-
upperCase: true,
|
11
|
-
digit: true,
|
12
|
-
specialCharacter: true,
|
13
|
-
allowRepeat: false,
|
14
|
-
useTightPattern: true,
|
15
|
-
useLoosePattern: false,
|
16
|
-
tightCharacterLength: 8,
|
17
|
-
looseCharacterLength: 15
|
18
|
-
}
|
19
|
-
|
20
|
-
function generatePasswordPatternRegExp({
|
21
|
-
lowerCase = true,
|
22
|
-
upperCase = true,
|
23
|
-
digit = true,
|
24
|
-
specialCharacter = true,
|
25
|
-
allowRepeat = false,
|
26
|
-
useTightPattern = true,
|
27
|
-
useLoosePattern = false,
|
28
|
-
tightCharacterLength = 8,
|
29
|
-
looseCharacterLength = 15
|
30
|
-
} = {}) {
|
31
|
-
var tightChecklist = useTightPattern
|
32
|
-
? [
|
33
|
-
lowerCase ? '(?=.*[a-z])' : '', // has at least one lower case character
|
34
|
-
upperCase ? '(?=.*[A-Z])' : '', // has at least one upper case character
|
35
|
-
digit ? '(?=.*\\d)' : '', // has at least one digit
|
36
|
-
specialCharacter ? '(?=.*[!@#$%^&*()])' : '', // has at least one special character
|
37
|
-
!allowRepeat ? '(?!.*(.)\\1(?=\\1{1,}))' : '', // has not an repeated character more than twice
|
38
|
-
`.{${tightCharacterLength},}` // has a length of 8 and more
|
39
|
-
]
|
40
|
-
: []
|
41
|
-
|
42
|
-
var looseChecklist = useLoosePattern
|
43
|
-
? [
|
44
|
-
`.{${looseCharacterLength},}` // has a length of 15 and more
|
45
|
-
]
|
46
|
-
: []
|
47
|
-
|
48
|
-
var checkList = [
|
49
|
-
'^', // from start
|
50
|
-
...tightChecklist,
|
51
|
-
tightChecklist.length && looseChecklist.length ? '|' : '',
|
52
|
-
...looseChecklist,
|
53
|
-
'$' //to the end"
|
54
|
-
]
|
55
|
-
|
56
|
-
return new RegExp(checkList.join(''))
|
57
|
-
}
|
58
|
-
|
59
|
-
export function generatePasswordPatternHelp(
|
60
|
-
{
|
61
|
-
lowerCase = true,
|
62
|
-
upperCase = true,
|
63
|
-
digit = true,
|
64
|
-
specialCharacter = true,
|
65
|
-
allowRepeat = false,
|
66
|
-
useTightPattern = true,
|
67
|
-
useLoosePattern = false,
|
68
|
-
tightCharacterLength = 8,
|
69
|
-
looseCharacterLength = 15
|
70
|
-
} = {},
|
71
|
-
lng
|
72
|
-
) {
|
73
|
-
lng = lng || 'en-US'
|
74
|
-
var descriptions = []
|
75
|
-
|
76
|
-
const t = i18next.getFixedT(lng, 'translations')
|
77
|
-
|
78
|
-
if (useLoosePattern) {
|
79
|
-
descriptions.push(`more than ${looseCharacterLength} characters`)
|
80
|
-
}
|
81
|
-
|
82
|
-
if (useTightPattern) {
|
83
|
-
!useLoosePattern &&
|
84
|
-
descriptions.push(
|
85
|
-
t('text.pattern_minimum_charaters', {
|
86
|
-
length: tightCharacterLength
|
87
|
-
})
|
88
|
-
)
|
89
|
-
lowerCase && descriptions.push(t('text.pattern_atleast_1_lowercase'))
|
90
|
-
upperCase && descriptions.push(t('text.pattern_atleast_1_uppercase'))
|
91
|
-
digit && descriptions.push(t('text.pattern_atleast_1_digit'))
|
92
|
-
specialCharacter && descriptions.push(t('text.pattern_atleast_1_special'))
|
93
|
-
!allowRepeat && descriptions.push(t('text.pattern_not_allowed'))
|
94
|
-
}
|
95
|
-
|
96
|
-
return descriptions.join(', ')
|
97
|
-
}
|
98
|
-
|
99
|
-
export const passwordPattern = generatePasswordPatternRegExp(passwordConfig)
|
100
|
-
export function passwordHelp(lng) {
|
101
|
-
return generatePasswordPatternHelp(passwordConfig, lng)
|
102
|
-
}
|
103
|
-
|
104
|
-
export function validatePasswordByRule(password, lng) {
|
105
|
-
if (!passwordPattern) {
|
106
|
-
return
|
107
|
-
}
|
108
|
-
|
109
|
-
if (passwordPattern.test(password)) {
|
110
|
-
return
|
111
|
-
}
|
112
|
-
|
113
|
-
const rule = generatePasswordPatternHelp(passwordConfig, lng)
|
114
|
-
throw new AuthError({
|
115
|
-
errorCode: PASSWORD_PATTERN_NOT_MATCHED,
|
116
|
-
detail: {
|
117
|
-
rule
|
118
|
-
}
|
119
|
-
})
|
120
|
-
}
|
@@ -1,12 +0,0 @@
|
|
1
|
-
import { getRepository } from '@things-factory/shell'
|
2
|
-
|
3
|
-
import { VerificationToken, VerificationTokenType } from '../../service/verification-token/verification-token'
|
4
|
-
|
5
|
-
export async function saveVerificationToken(id, token, type = VerificationTokenType.ACTIVATION) {
|
6
|
-
const verificationRepo = getRepository(VerificationToken)
|
7
|
-
return await verificationRepo.save({
|
8
|
-
userId: id,
|
9
|
-
token,
|
10
|
-
type
|
11
|
-
})
|
12
|
-
}
|
@@ -1,84 +0,0 @@
|
|
1
|
-
import { URL } from 'url'
|
2
|
-
|
3
|
-
import { sendEmail } from '@things-factory/email-base'
|
4
|
-
import { getRepository } from '@things-factory/shell'
|
5
|
-
|
6
|
-
import { AuthError } from '../errors/auth-error'
|
7
|
-
import { User, UserStatus } from '../service/user/user'
|
8
|
-
import { VerificationToken } from '../service/verification-token/verification-token'
|
9
|
-
import { getVerificationEmailForm } from '../templates/verification-email'
|
10
|
-
import { makeVerificationToken } from './utils/make-verification-token'
|
11
|
-
import { saveVerificationToken } from './utils/save-verification-token'
|
12
|
-
|
13
|
-
export async function sendVerificationEmail({ user, context }) {
|
14
|
-
try {
|
15
|
-
var token = makeVerificationToken()
|
16
|
-
var verifaction = await saveVerificationToken(user.id, token)
|
17
|
-
|
18
|
-
if (verifaction) {
|
19
|
-
var serviceUrl = new URL(`/auth/verify/${token}`, context.header.referer)
|
20
|
-
await sendEmail({
|
21
|
-
receiver: user.email,
|
22
|
-
subject: 'Verify your email',
|
23
|
-
content: getVerificationEmailForm({
|
24
|
-
username: user.username,
|
25
|
-
name: user.name,
|
26
|
-
verifyUrl: serviceUrl
|
27
|
-
})
|
28
|
-
})
|
29
|
-
|
30
|
-
return true
|
31
|
-
}
|
32
|
-
} catch (e) {
|
33
|
-
return false
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
export async function verify(token) {
|
38
|
-
var verification = await getRepository(VerificationToken).findOne({
|
39
|
-
where: {
|
40
|
-
token
|
41
|
-
}
|
42
|
-
})
|
43
|
-
|
44
|
-
if (!verification) {
|
45
|
-
throw new AuthError({
|
46
|
-
errorCode: AuthError.ERROR_CODES.VERIFICATION_ERROR
|
47
|
-
})
|
48
|
-
}
|
49
|
-
|
50
|
-
var userInfo = await getRepository(User).findOneBy({ id: verification.userId })
|
51
|
-
if (!userInfo) {
|
52
|
-
throw new AuthError({
|
53
|
-
errorCode: AuthError.ERROR_CODES.VERIFICATION_ERROR
|
54
|
-
})
|
55
|
-
}
|
56
|
-
|
57
|
-
if (!(userInfo.status == UserStatus.INACTIVE || userInfo.status == UserStatus.LOCKED)) {
|
58
|
-
throw new AuthError({
|
59
|
-
errorCode: AuthError.ERROR_CODES.VERIFICATION_ERROR
|
60
|
-
})
|
61
|
-
}
|
62
|
-
|
63
|
-
userInfo.status = UserStatus.ACTIVATED
|
64
|
-
userInfo.failCount = 0
|
65
|
-
|
66
|
-
await getRepository(User).save(userInfo)
|
67
|
-
await getRepository(VerificationToken).delete(verification)
|
68
|
-
}
|
69
|
-
|
70
|
-
export async function resendVerificationEmail(email, context) {
|
71
|
-
var user = await getRepository(User).findOne({
|
72
|
-
where: {
|
73
|
-
email
|
74
|
-
}
|
75
|
-
})
|
76
|
-
|
77
|
-
if (!user) return false
|
78
|
-
if (user.status == UserStatus.ACTIVATED) return false
|
79
|
-
|
80
|
-
return await sendVerificationEmail({
|
81
|
-
user,
|
82
|
-
context
|
83
|
-
})
|
84
|
-
}
|
@@ -1,24 +0,0 @@
|
|
1
|
-
import * as ERROR_CODES from '../constants/error-code'
|
2
|
-
|
3
|
-
type AuthErrorArgument = {
|
4
|
-
errorCode: string
|
5
|
-
detail?: Object
|
6
|
-
}
|
7
|
-
export class AuthError extends Error {
|
8
|
-
static get ERROR_CODES(): any {
|
9
|
-
return {
|
10
|
-
...ERROR_CODES
|
11
|
-
}
|
12
|
-
}
|
13
|
-
|
14
|
-
errorCode: any
|
15
|
-
detail: Object
|
16
|
-
|
17
|
-
constructor({ errorCode, detail }: AuthErrorArgument) {
|
18
|
-
super(errorCode)
|
19
|
-
|
20
|
-
this.name = 'auth-error'
|
21
|
-
this.errorCode = errorCode
|
22
|
-
this.detail = detail
|
23
|
-
}
|
24
|
-
}
|
package/server/errors/index.ts
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
NO_AVAILABLE_DOMAIN,
|
3
|
-
NO_SELECTED_DOMAIN,
|
4
|
-
REDIRECT_TO_DEFAULT_DOMAIN,
|
5
|
-
UNAVAILABLE_DOMAIN
|
6
|
-
} from '../constants/error-code'
|
7
|
-
import { AuthError } from './auth-error'
|
8
|
-
|
9
|
-
export class DomainError extends AuthError {
|
10
|
-
static get ERROR_CODES(): any {
|
11
|
-
return {
|
12
|
-
UNAVAILABLE_DOMAIN,
|
13
|
-
NO_AVAILABLE_DOMAIN,
|
14
|
-
NO_SELECTED_DOMAIN,
|
15
|
-
REDIRECT_TO_DEFAULT_DOMAIN
|
16
|
-
}
|
17
|
-
}
|
18
|
-
|
19
|
-
domains: any
|
20
|
-
|
21
|
-
constructor({ errorCode = UNAVAILABLE_DOMAIN, domains }) {
|
22
|
-
super({
|
23
|
-
errorCode
|
24
|
-
})
|
25
|
-
|
26
|
-
this.name = 'user-domain-not-match'
|
27
|
-
this.domains = domains
|
28
|
-
}
|
29
|
-
}
|
package/server/index.ts
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
import { getRepository } from '@things-factory/shell'
|
2
|
-
import { Privilege } from './service/privilege/privilege'
|
3
|
-
|
4
|
-
import './routes'
|
5
|
-
|
6
|
-
export * from './service'
|
7
|
-
export * from './migrations'
|
8
|
-
|
9
|
-
export * from './middlewares'
|
10
|
-
export * from './routes'
|
11
|
-
export * from './router'
|
12
|
-
|
13
|
-
export * from './utils/get-domain-users'
|
14
|
-
export * from './utils/get-user-domains'
|
15
|
-
export * from './utils/get-secret'
|
16
|
-
export * from './utils/check-user-belongs-domain'
|
17
|
-
export * from './utils/access-token-cookie'
|
18
|
-
export * from './utils/encrypt-state'
|
19
|
-
export * from './utils/check-permission'
|
20
|
-
export * from './utils/check-user-has-role'
|
21
|
-
|
22
|
-
export * from './errors'
|
23
|
-
|
24
|
-
export * from './types'
|
25
|
-
|
26
|
-
process.on('bootstrap-module-start' as any, async ({ app, config, client }: any) => {
|
27
|
-
const privileges = process['PRIVILEGES']
|
28
|
-
const privilegeRepository = getRepository(Privilege)
|
29
|
-
|
30
|
-
for (const [category, name] of Object.values(privileges as [string, string])) {
|
31
|
-
if (0 == (await privilegeRepository.count({ where: { category, name } }))) {
|
32
|
-
await privilegeRepository.save({ category, name })
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
console.log('[auth-base:bootstrap] Synchronization for privilege master has just done.')
|
37
|
-
})
|
@@ -1,114 +0,0 @@
|
|
1
|
-
import { config } from '@things-factory/env'
|
2
|
-
|
3
|
-
import { SUBDOMAIN_NOTFOUND, USER_DUPLICATED, USER_LOCKED, USER_NOT_ACTIVATED } from '../constants/error-code'
|
4
|
-
import { AuthError } from '../errors/auth-error'
|
5
|
-
import { accepts } from '../utils/accepts'
|
6
|
-
|
7
|
-
const disableUserSignupProcess = config.get('disableUserSignupProcess', false)
|
8
|
-
const disableUserFavoredLanguage = config.get('i18n/disableUserFavoredLanguage', false)
|
9
|
-
const languages = config.get('i18n/languages', false)
|
10
|
-
|
11
|
-
export async function authenticate401Middleware(context, next) {
|
12
|
-
try {
|
13
|
-
await next()
|
14
|
-
} catch (err) {
|
15
|
-
var message
|
16
|
-
|
17
|
-
if (err instanceof AuthError) {
|
18
|
-
message = (context.t && context.t(`error.${err.errorCode}`, err.detail || {})) || err.errorCode
|
19
|
-
} else {
|
20
|
-
if (err?.status !== 401) {
|
21
|
-
throw err
|
22
|
-
}
|
23
|
-
|
24
|
-
message = err.message
|
25
|
-
}
|
26
|
-
|
27
|
-
context.status = 401
|
28
|
-
context.body = message
|
29
|
-
|
30
|
-
/*
|
31
|
-
* 클라이언트 라우팅을 위한 ApiHistoryFallback의 상황과,
|
32
|
-
* 서버라우팅의 상황에서 발생하는 던져지는 401 에러인 경우에는
|
33
|
-
* error code에 맞춰서 적절하게 rewriting 되도록 한다.
|
34
|
-
*/
|
35
|
-
|
36
|
-
const { method, header, path, originalUrl } = context
|
37
|
-
|
38
|
-
if (method == 'POST' && path.startsWith('/graphql')) {
|
39
|
-
if (err.errorCode == SUBDOMAIN_NOTFOUND) {
|
40
|
-
context.status = 403
|
41
|
-
}
|
42
|
-
return
|
43
|
-
}
|
44
|
-
|
45
|
-
if (!accepts(header.accept, ['text/html', '*/*'])) {
|
46
|
-
return
|
47
|
-
}
|
48
|
-
|
49
|
-
const { redirect_to } = context.query
|
50
|
-
const { redirectTo = redirect_to || originalUrl } = context.request.body || {}
|
51
|
-
|
52
|
-
switch (err.errorCode) {
|
53
|
-
case SUBDOMAIN_NOTFOUND:
|
54
|
-
context.redirect(`/auth/checkin?redirect_to=${encodeURIComponent(redirectTo)}`)
|
55
|
-
break
|
56
|
-
|
57
|
-
case USER_LOCKED:
|
58
|
-
return await context.render('auth-page', {
|
59
|
-
pageElement: 'auth-activate',
|
60
|
-
elementScript: '/auth/activate.js',
|
61
|
-
data: {
|
62
|
-
...err.detail,
|
63
|
-
message,
|
64
|
-
redirectTo,
|
65
|
-
disableUserSignupProcess,
|
66
|
-
disableUserFavoredLanguage,
|
67
|
-
languages
|
68
|
-
}
|
69
|
-
})
|
70
|
-
|
71
|
-
case USER_NOT_ACTIVATED:
|
72
|
-
return await context.render('auth-page', {
|
73
|
-
pageElement: 'auth-activate',
|
74
|
-
elementScript: '/auth/activate.js',
|
75
|
-
data: {
|
76
|
-
...err.detail,
|
77
|
-
message,
|
78
|
-
redirectTo,
|
79
|
-
disableUserSignupProcess,
|
80
|
-
disableUserFavoredLanguage,
|
81
|
-
languages
|
82
|
-
}
|
83
|
-
})
|
84
|
-
|
85
|
-
case USER_DUPLICATED:
|
86
|
-
return await context.render('auth-page', {
|
87
|
-
pageElement: 'auth-signup',
|
88
|
-
elementScript: '/auth/signup.js',
|
89
|
-
data: {
|
90
|
-
...err.detail,
|
91
|
-
message,
|
92
|
-
redirectTo,
|
93
|
-
disableUserSignupProcess,
|
94
|
-
disableUserFavoredLanguage,
|
95
|
-
languages
|
96
|
-
}
|
97
|
-
})
|
98
|
-
|
99
|
-
default:
|
100
|
-
return await context.render('auth-page', {
|
101
|
-
pageElement: 'auth-signin',
|
102
|
-
elementScript: '/auth/signin.js',
|
103
|
-
data: {
|
104
|
-
...err.detail,
|
105
|
-
message: err instanceof AuthError ? message : '',
|
106
|
-
redirectTo,
|
107
|
-
disableUserSignupProcess,
|
108
|
-
disableUserFavoredLanguage,
|
109
|
-
languages
|
110
|
-
}
|
111
|
-
})
|
112
|
-
}
|
113
|
-
}
|
114
|
-
}
|
@@ -1,78 +0,0 @@
|
|
1
|
-
import { config } from '@things-factory/env'
|
2
|
-
import { Domain, getRepository } from '@things-factory/shell'
|
3
|
-
|
4
|
-
import { AuthError } from '../errors/auth-error'
|
5
|
-
import { User } from '../service/user/user'
|
6
|
-
import { getUserDomains } from '../utils/get-user-domains'
|
7
|
-
|
8
|
-
const useVirtualHostBasedDomain = !!config.get('useVirtualHostBasedDomain')
|
9
|
-
const fixed = config.get('subdomain')
|
10
|
-
const subdomainOffset = config.getNumber('subdomainOffset', 2)
|
11
|
-
|
12
|
-
declare global {
|
13
|
-
namespace NodeJS {
|
14
|
-
interface Process {
|
15
|
-
domainOwnerGranted: (domain: Domain, user: User) => Promise<boolean>
|
16
|
-
superUserGranted: (domain: Domain, user: User) => Promise<boolean>
|
17
|
-
}
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
process.domainOwnerGranted = async (domain: Domain, user: User): Promise<boolean> => {
|
22
|
-
return user && domain && domain.owner === user.id
|
23
|
-
}
|
24
|
-
|
25
|
-
process.superUserGranted = async (domain: Domain, user: User): Promise<boolean> => {
|
26
|
-
if (!user) {
|
27
|
-
return false
|
28
|
-
}
|
29
|
-
|
30
|
-
if (!user.domains.length) {
|
31
|
-
user = await getRepository(User).findOne({
|
32
|
-
where: { id: user.id },
|
33
|
-
relations: ['domains']
|
34
|
-
})
|
35
|
-
}
|
36
|
-
|
37
|
-
const systemDomain: Domain = user.domains.find((domain: Domain) => domain.subdomain === 'system')
|
38
|
-
if (!systemDomain) {
|
39
|
-
return false
|
40
|
-
}
|
41
|
-
|
42
|
-
return systemDomain.owner === user.id
|
43
|
-
}
|
44
|
-
|
45
|
-
/*
|
46
|
-
* 현재 subdomain 과 user의 domain list와의 비교를 통해서,
|
47
|
-
* 인증 성공 또는 인증 에러를 발생시킬 것인지를 결정한다.
|
48
|
-
* 1. 현재 subdomain 이 결정되지 않은 경우.
|
49
|
-
* - checkin로 이동한다.
|
50
|
-
* 2. superUser 판단
|
51
|
-
* 3. 현재 subdomain 이 결정된 경우.
|
52
|
-
* - user의 domains 리스트에 해당 subdomain이 없다면, 인증 오류를 발생한다.
|
53
|
-
*/
|
54
|
-
|
55
|
-
export async function domainAuthenticateMiddleware(context: any, next: any) {
|
56
|
-
const { t } = context
|
57
|
-
const { domain, user } = context.state
|
58
|
-
|
59
|
-
const subdomain: string = domain?.subdomain
|
60
|
-
|
61
|
-
// 1. 현재 subdomain 이 결정되지 않은 경우.
|
62
|
-
// - checkin로 이동한다.
|
63
|
-
if (!subdomain) {
|
64
|
-
throw new AuthError({
|
65
|
-
errorCode: AuthError.ERROR_CODES.SUBDOMAIN_NOTFOUND
|
66
|
-
})
|
67
|
-
}
|
68
|
-
|
69
|
-
// 2. 현재 subdomain 이 결정된 경우.
|
70
|
-
const userDomains: Partial<Domain>[] = await getUserDomains(user)
|
71
|
-
if (userDomains.find(domain => domain.subdomain == subdomain) || (await process.superUserGranted(domain, user))) {
|
72
|
-
return await next()
|
73
|
-
}
|
74
|
-
|
75
|
-
throw new AuthError({
|
76
|
-
errorCode: AuthError.ERROR_CODES.SUBDOMAIN_NOTFOUND
|
77
|
-
})
|
78
|
-
}
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import { domainAuthenticateMiddleware } from './domain-authenticate-middleware'
|
2
|
-
import { jwtAuthenticateMiddleware } from './jwt-authenticate-middleware'
|
3
|
-
|
4
|
-
export async function graphqlAuthenticateMiddleware(context, next) {
|
5
|
-
const { method, path } = context
|
6
|
-
|
7
|
-
if (method == 'POST' && path.startsWith('/graphql')) {
|
8
|
-
await jwtAuthenticateMiddleware(context, () => {})
|
9
|
-
await domainAuthenticateMiddleware(context, () => {})
|
10
|
-
}
|
11
|
-
|
12
|
-
await next()
|
13
|
-
}
|
@@ -1,67 +0,0 @@
|
|
1
|
-
import session from 'koa-session'
|
2
|
-
import passport from 'koa-passport'
|
3
|
-
|
4
|
-
import { config } from '@things-factory/env'
|
5
|
-
import { SECRET } from '../utils/get-secret'
|
6
|
-
|
7
|
-
import { authenticate401Middleware } from './authenticate-401-middleware'
|
8
|
-
import { domainAuthenticateMiddleware } from './domain-authenticate-middleware'
|
9
|
-
import { graphqlAuthenticateMiddleware } from './graphql-authenticate-middleware'
|
10
|
-
import { jwtAuthenticateMiddleware } from './jwt-authenticate-middleware'
|
11
|
-
|
12
|
-
import { User } from '../service/user/user'
|
13
|
-
import { MAX_AGE } from '../constants/max-age'
|
14
|
-
|
15
|
-
const accessTokenCookieKey = config.get('accessTokenCookieKey', 'access_token')
|
16
|
-
|
17
|
-
export function initMiddlewares(app: any) {
|
18
|
-
/* oauth2orize-koa 에서 oauth 트랜잭션 관리를 위해서 session을 사용함. */
|
19
|
-
app.keys = [SECRET]
|
20
|
-
app.use(
|
21
|
-
session(
|
22
|
-
{
|
23
|
-
key: 'tfsession',
|
24
|
-
maxAge: MAX_AGE,
|
25
|
-
overwrite: true,
|
26
|
-
httpOnly: true,
|
27
|
-
signed: true,
|
28
|
-
rolling: false,
|
29
|
-
renew: false
|
30
|
-
},
|
31
|
-
app
|
32
|
-
)
|
33
|
-
)
|
34
|
-
|
35
|
-
passport.serializeUser((profile, done) => {
|
36
|
-
done(null, profile)
|
37
|
-
})
|
38
|
-
|
39
|
-
passport.deserializeUser(async (profile, done) => {
|
40
|
-
done(null, await User.checkAuth(profile))
|
41
|
-
})
|
42
|
-
|
43
|
-
/* passport initialize */
|
44
|
-
app.use(passport.initialize())
|
45
|
-
|
46
|
-
/* passport use session - for oauth transaction */
|
47
|
-
app.use(passport.session())
|
48
|
-
|
49
|
-
/* authentication error handling */
|
50
|
-
app.use(authenticate401Middleware)
|
51
|
-
|
52
|
-
/*
|
53
|
-
* post:graphql 에 대해서는 graphqlAuthenticationMiddleware를 적용한다.
|
54
|
-
* graphql app을 router에 적용하지 못하기 때문임.
|
55
|
-
*/
|
56
|
-
app.use(graphqlAuthenticateMiddleware)
|
57
|
-
}
|
58
|
-
|
59
|
-
process.on('bootstrap-module-subscription' as any, (app, subscriptionMiddleware) => {
|
60
|
-
subscriptionMiddleware.push(jwtAuthenticateMiddleware, domainAuthenticateMiddleware)
|
61
|
-
})
|
62
|
-
|
63
|
-
export * from './jwt-authenticate-middleware'
|
64
|
-
export * from './domain-authenticate-middleware'
|
65
|
-
export * from './signin-middleware'
|
66
|
-
export * from './webauthn-middleware'
|
67
|
-
export * from './authenticate-401-middleware'
|