@things-factory/auth-base 8.0.0-beta.0 → 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.
Files changed (142) hide show
  1. package/package.json +6 -6
  2. package/client/actions/auth.ts +0 -24
  3. package/client/auth.ts +0 -272
  4. package/client/bootstrap.ts +0 -47
  5. package/client/directive/privileged.ts +0 -28
  6. package/client/index.ts +0 -4
  7. package/client/profiled.ts +0 -83
  8. package/client/reducers/auth.ts +0 -31
  9. package/client/verify-webauthn.ts +0 -86
  10. package/server/constants/error-code.ts +0 -22
  11. package/server/constants/error-message.ts +0 -0
  12. package/server/constants/max-age.ts +0 -1
  13. package/server/controllers/auth.ts +0 -5
  14. package/server/controllers/change-pwd.ts +0 -100
  15. package/server/controllers/checkin.ts +0 -21
  16. package/server/controllers/delete-user.ts +0 -71
  17. package/server/controllers/invitation.ts +0 -163
  18. package/server/controllers/profile.ts +0 -55
  19. package/server/controllers/reset-password.ts +0 -126
  20. package/server/controllers/signin.ts +0 -98
  21. package/server/controllers/signup.ts +0 -72
  22. package/server/controllers/unlock-user.ts +0 -62
  23. package/server/controllers/utils/make-invitation-token.ts +0 -5
  24. package/server/controllers/utils/make-verification-token.ts +0 -4
  25. package/server/controllers/utils/password-rule.ts +0 -120
  26. package/server/controllers/utils/save-invitation-token.ts +0 -10
  27. package/server/controllers/utils/save-verification-token.ts +0 -12
  28. package/server/controllers/verification.ts +0 -84
  29. package/server/errors/auth-error.ts +0 -24
  30. package/server/errors/index.ts +0 -2
  31. package/server/errors/user-domain-not-match-error.ts +0 -29
  32. package/server/index.ts +0 -37
  33. package/server/middlewares/authenticate-401-middleware.ts +0 -114
  34. package/server/middlewares/domain-authenticate-middleware.ts +0 -78
  35. package/server/middlewares/graphql-authenticate-middleware.ts +0 -13
  36. package/server/middlewares/index.ts +0 -67
  37. package/server/middlewares/jwt-authenticate-middleware.ts +0 -84
  38. package/server/middlewares/signin-middleware.ts +0 -55
  39. package/server/middlewares/webauthn-middleware.ts +0 -126
  40. package/server/migrations/1548206416130-SeedUser.ts +0 -60
  41. package/server/migrations/1566805283882-SeedPrivilege.ts +0 -28
  42. package/server/migrations/index.ts +0 -9
  43. package/server/router/auth-checkin-router.ts +0 -113
  44. package/server/router/auth-private-process-router.ts +0 -114
  45. package/server/router/auth-public-process-router.ts +0 -314
  46. package/server/router/auth-signin-router.ts +0 -55
  47. package/server/router/auth-signup-router.ts +0 -95
  48. package/server/router/index.ts +0 -9
  49. package/server/router/oauth2/index.ts +0 -2
  50. package/server/router/oauth2/oauth2-authorize-router.ts +0 -81
  51. package/server/router/oauth2/oauth2-router.ts +0 -165
  52. package/server/router/oauth2/oauth2-server.ts +0 -262
  53. package/server/router/oauth2/passport-oauth2-client-password.ts +0 -87
  54. package/server/router/oauth2/passport-refresh-token.ts +0 -87
  55. package/server/router/path-base-domain-router.ts +0 -8
  56. package/server/router/site-root-router.ts +0 -48
  57. package/server/router/webauthn-router.ts +0 -149
  58. package/server/routes.ts +0 -80
  59. package/server/service/app-binding/app-binding-mutation.ts +0 -22
  60. package/server/service/app-binding/app-binding-query.ts +0 -92
  61. package/server/service/app-binding/app-binding-types.ts +0 -11
  62. package/server/service/app-binding/app-binding.ts +0 -17
  63. package/server/service/app-binding/index.ts +0 -4
  64. package/server/service/appliance/appliance-mutation.ts +0 -113
  65. package/server/service/appliance/appliance-query.ts +0 -76
  66. package/server/service/appliance/appliance-types.ts +0 -56
  67. package/server/service/appliance/appliance.ts +0 -133
  68. package/server/service/appliance/index.ts +0 -6
  69. package/server/service/application/application-mutation.ts +0 -104
  70. package/server/service/application/application-query.ts +0 -98
  71. package/server/service/application/application-types.ts +0 -76
  72. package/server/service/application/application.ts +0 -216
  73. package/server/service/application/index.ts +0 -6
  74. package/server/service/auth-provider/auth-provider-mutation.ts +0 -159
  75. package/server/service/auth-provider/auth-provider-parameter-spec.ts +0 -24
  76. package/server/service/auth-provider/auth-provider-query.ts +0 -88
  77. package/server/service/auth-provider/auth-provider-type.ts +0 -67
  78. package/server/service/auth-provider/auth-provider.ts +0 -155
  79. package/server/service/auth-provider/index.ts +0 -7
  80. package/server/service/domain-generator/domain-generator-mutation.ts +0 -117
  81. package/server/service/domain-generator/domain-generator-types.ts +0 -46
  82. package/server/service/domain-generator/index.ts +0 -3
  83. package/server/service/granted-role/granted-role-mutation.ts +0 -156
  84. package/server/service/granted-role/granted-role-query.ts +0 -60
  85. package/server/service/granted-role/granted-role.ts +0 -27
  86. package/server/service/granted-role/index.ts +0 -6
  87. package/server/service/index.ts +0 -90
  88. package/server/service/invitation/index.ts +0 -6
  89. package/server/service/invitation/invitation-mutation.ts +0 -78
  90. package/server/service/invitation/invitation-query.ts +0 -33
  91. package/server/service/invitation/invitation-types.ts +0 -11
  92. package/server/service/invitation/invitation.ts +0 -63
  93. package/server/service/login-history/index.ts +0 -5
  94. package/server/service/login-history/login-history-query.ts +0 -51
  95. package/server/service/login-history/login-history-type.ts +0 -12
  96. package/server/service/login-history/login-history.ts +0 -45
  97. package/server/service/partner/index.ts +0 -6
  98. package/server/service/partner/partner-mutation.ts +0 -61
  99. package/server/service/partner/partner-query.ts +0 -102
  100. package/server/service/partner/partner-types.ts +0 -11
  101. package/server/service/partner/partner.ts +0 -57
  102. package/server/service/password-history/index.ts +0 -3
  103. package/server/service/password-history/password-history.ts +0 -16
  104. package/server/service/privilege/index.ts +0 -6
  105. package/server/service/privilege/privilege-directive.ts +0 -77
  106. package/server/service/privilege/privilege-mutation.ts +0 -92
  107. package/server/service/privilege/privilege-query.ts +0 -94
  108. package/server/service/privilege/privilege-types.ts +0 -60
  109. package/server/service/privilege/privilege.ts +0 -102
  110. package/server/service/role/index.ts +0 -6
  111. package/server/service/role/role-mutation.ts +0 -109
  112. package/server/service/role/role-query.ts +0 -155
  113. package/server/service/role/role-types.ts +0 -81
  114. package/server/service/role/role.ts +0 -72
  115. package/server/service/user/domain-query.ts +0 -24
  116. package/server/service/user/index.ts +0 -7
  117. package/server/service/user/user-mutation.ts +0 -482
  118. package/server/service/user/user-query.ts +0 -145
  119. package/server/service/user/user-types.ts +0 -100
  120. package/server/service/user/user.ts +0 -381
  121. package/server/service/users-auth-providers/index.ts +0 -5
  122. package/server/service/users-auth-providers/users-auth-providers.ts +0 -71
  123. package/server/service/verification-token/index.ts +0 -3
  124. package/server/service/verification-token/verification-token.ts +0 -60
  125. package/server/service/web-auth-credential/index.ts +0 -3
  126. package/server/service/web-auth-credential/web-auth-credential.ts +0 -67
  127. package/server/templates/account-unlock-email.ts +0 -65
  128. package/server/templates/invitation-email.ts +0 -66
  129. package/server/templates/reset-password-email.ts +0 -65
  130. package/server/templates/verification-email.ts +0 -66
  131. package/server/types.ts +0 -21
  132. package/server/utils/accepts.ts +0 -11
  133. package/server/utils/access-token-cookie.ts +0 -61
  134. package/server/utils/check-permission.ts +0 -52
  135. package/server/utils/check-user-belongs-domain.ts +0 -19
  136. package/server/utils/check-user-has-role.ts +0 -29
  137. package/server/utils/encrypt-state.ts +0 -22
  138. package/server/utils/get-aes-256-key.ts +0 -13
  139. package/server/utils/get-domain-from-hostname.ts +0 -7
  140. package/server/utils/get-domain-users.ts +0 -38
  141. package/server/utils/get-secret.ts +0 -13
  142. package/server/utils/get-user-domains.ts +0 -112
@@ -1,100 +0,0 @@
1
- import { config } from '@things-factory/env'
2
- import { getRepository } from '@things-factory/shell'
3
-
4
- import {
5
- CONFIRM_PASSWORD_NOT_MATCHED,
6
- PASSWORD_NOT_MATCHED,
7
- PASSWORD_USED_PAST,
8
- USER_NOT_FOUND
9
- } from '../constants/error-code'
10
- import { AuthError } from '../errors/auth-error'
11
- import { PasswordHistory } from '../service/password-history/password-history'
12
- import { User } from '../service/user/user'
13
-
14
- const HISTORY_SIZE = config.get('password', { history: 0 }).history
15
-
16
- export async function changePwd(attrs, currentPass, newPass, confirmPass, context) {
17
- const { domain } = context.state
18
-
19
- // TODO 이 사용자가 이 도메인에 속한 사용자인지 확인해야함.
20
- const repository = getRepository(User)
21
-
22
- const user: User = await repository.findOne({ where: { id: attrs.id } })
23
-
24
- if (!user) {
25
- throw new AuthError({
26
- errorCode: USER_NOT_FOUND
27
- })
28
- }
29
-
30
- if (newPass !== confirmPass) {
31
- throw new AuthError({
32
- errorCode: CONFIRM_PASSWORD_NOT_MATCHED
33
- })
34
- }
35
-
36
- if (!User.verify(user.password, currentPass, user.salt)) {
37
- throw new AuthError({
38
- errorCode: PASSWORD_NOT_MATCHED,
39
- detail: {
40
- username: user.username,
41
- email: user.email,
42
- failCount: user.failCount
43
- }
44
- })
45
- }
46
-
47
- /* check if password is following the rule */
48
- User.validatePasswordByRule(newPass, context?.lng)
49
-
50
- user.password = User.encode(newPass, user.salt)
51
-
52
- if (HISTORY_SIZE > 0) {
53
- var passwordHistory: PasswordHistory = await getRepository(PasswordHistory).findOneBy({ userId: user.id })
54
- var history = []
55
-
56
- if (passwordHistory) {
57
- try {
58
- history = JSON.parse(passwordHistory.history)
59
- if (!(history instanceof Array)) {
60
- console.error('password history maybe currupted - not an array')
61
- history = []
62
- }
63
- } catch (e) {
64
- console.error('password history currupted - not json format')
65
- }
66
-
67
- const found = history.slice(0, HISTORY_SIZE).find(h => {
68
- return User.verify(h.password, newPass, h.salt)
69
- })
70
-
71
- if (found) {
72
- throw new AuthError({
73
- errorCode: PASSWORD_USED_PAST
74
- })
75
- }
76
- }
77
- }
78
-
79
- await repository.save({
80
- ...user,
81
- passwordUpdatedAt: new Date()
82
- })
83
-
84
- if (HISTORY_SIZE > 0) {
85
- history = [
86
- {
87
- password: user.password,
88
- salt: user.salt
89
- },
90
- ...history
91
- ].slice(0, HISTORY_SIZE)
92
-
93
- await getRepository(PasswordHistory).save({
94
- userId: user.id,
95
- history: JSON.stringify(history)
96
- })
97
- }
98
-
99
- return await user.sign({ subdomain: domain.subdomain })
100
- }
@@ -1,21 +0,0 @@
1
- import { Domain, getRepository } from '@things-factory/shell'
2
-
3
- import { User } from '../service/user/user'
4
- import { getUserDomains } from '../utils/get-user-domains'
5
-
6
- export async function checkin({ userId, subdomain }) {
7
- const userRepo = getRepository(User)
8
- const user = await userRepo.findOne({ where: { id: userId } })
9
- const domains: Partial<Domain>[] = await getUserDomains(user)
10
-
11
- if (!domains?.length) {
12
- return false
13
- }
14
-
15
- const domain = domains.find(domain => domain.subdomain == subdomain)
16
- if (!domain) {
17
- return false
18
- }
19
-
20
- return await user.sign({ subdomain })
21
- }
@@ -1,71 +0,0 @@
1
- import { EntityManager, ILike, In } from 'typeorm'
2
- import { User, UserStatus } from '../service/user/user'
3
- import { AuthError } from '../errors/auth-error'
4
- import { USER_NOT_FOUND } from '../constants/error-code'
5
-
6
- export async function deleteUser(attrs, tx?: EntityManager) {
7
- // TODO 이 사용자가 이 도메인에 속한 사용자인지 확인해야함.
8
- // TODO 다른 도메인에도 포함되어있다면, domains-users 관게와 해당 도메인 관련 정보만 삭제해야 함.
9
-
10
- const repository = tx?.getRepository(User)
11
- const { username } = attrs
12
-
13
- var user = await repository.findOne({
14
- where: { username },
15
- relations: ['domains']
16
- })
17
-
18
- if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
19
- user = await repository.findOne({
20
- where: { email: ILike(username) },
21
- relations: ['domains']
22
- })
23
- }
24
-
25
- if (!user) {
26
- throw new AuthError({
27
- errorCode: USER_NOT_FOUND
28
- })
29
- }
30
-
31
- user.status = UserStatus.DELETED
32
- user.domains = []
33
-
34
- await repository.save(user)
35
- }
36
-
37
- export async function deleteUsers(attrs, tx?: EntityManager) {
38
- // TODO 이 사용자가 이 도메인에 속한 사용자인지 확인해야함.
39
- // TODO 다른 도메인에도 포함되어있다면, domains-users 관게와 해당 도메인 관련 정보만 삭제해야 함.
40
-
41
- const { usernames } = attrs
42
-
43
- const repo = tx?.getRepository(User)
44
-
45
- const users = await repo.find({
46
- where: {
47
- username: In(usernames)
48
- }
49
- })
50
-
51
- const userIds = []
52
- users.forEach(user => {
53
- user.status = UserStatus.DELETED
54
- user.domains = []
55
-
56
- userIds.push(user.id)
57
- })
58
-
59
- await repo.save(users)
60
-
61
- // repository api는 작동하지 않음.
62
- // await txManager
63
- // .createQueryBuilder()
64
- // .delete()
65
- // .from('users_domains')
66
- // .where({
67
- // usersId: In(userIds)
68
- // })
69
- // .execute()
70
- return true
71
- }
@@ -1,163 +0,0 @@
1
- import { ILike } from 'typeorm'
2
- import { URL } from 'url'
3
-
4
- import { sendEmail } from '@things-factory/email-base'
5
- import { Domain, getRepository } from '@things-factory/shell'
6
-
7
- import { Invitation } from '../service/invitation/invitation'
8
- import { User, UserStatus } from '../service/user/user'
9
- import { getInvitationEmailForm } from '../templates/invitation-email'
10
- import { makeInvitationToken } from './utils/make-invitation-token'
11
- import { saveInvitationToken } from './utils/save-invitation-token'
12
-
13
- export async function invite(attrs, withEmailInvitation?: Boolean) {
14
- const { username, reference, type, context } = attrs
15
- const repository = getRepository(User)
16
-
17
- var user = await repository.findOne({
18
- where: { username },
19
- relations: ['domains']
20
- })
21
-
22
- if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
23
- user = await repository.findOne({
24
- where: { email: ILike(username) },
25
- relations: ['domains']
26
- })
27
- }
28
-
29
- var domains = user.domains
30
-
31
- // TODO reference should not be a domain.id (security reason)
32
-
33
- if (user) {
34
- const domain = domains.find(domain => domain.id == reference)
35
-
36
- if (domain) {
37
- const msg = `user already a member of the ${type}.`
38
- throw new Error(msg)
39
- }
40
- }
41
-
42
- if (withEmailInvitation) {
43
- const email = user.email
44
-
45
- // TODO 초대장의 유효기간을 설정할 수 있어야 함.
46
- var invitation = await getRepository(Invitation).findOneBy({
47
- email: ILike(email),
48
- reference,
49
- type
50
- })
51
-
52
- if (!invitation) {
53
- invitation = await getRepository(Invitation).save({
54
- email,
55
- reference,
56
- type
57
- })
58
- }
59
-
60
- return await sendInvitationEmail({
61
- invitation,
62
- user,
63
- context
64
- })
65
- }
66
-
67
- if (user) {
68
- user.domains = [...domains, await getRepository(Domain).findOneBy({ id: reference })]
69
- await getRepository(User).save(user)
70
- } else {
71
- // TODO need to signup
72
- }
73
- }
74
-
75
- export async function acceptInvitation(token) {
76
- var invitation = await getRepository(Invitation).findOneBy({
77
- token
78
- })
79
-
80
- if (!invitation) {
81
- throw new Error(`not found invitation.`)
82
- }
83
-
84
- var { email, reference, type } = invitation
85
-
86
- var user = await getRepository(User).findOne({ where: { email: ILike(email) }, relations: ['domains'] })
87
-
88
- if (user) {
89
- var domains = user.domains
90
- const domain = domains.find(domain => domain.id == reference)
91
-
92
- if (domain) {
93
- const msg = `user already a member of the ${type}.`
94
- throw new Error(msg)
95
- }
96
-
97
- user.domains = [...domains, await getRepository(Domain).findOneBy({ id: reference })]
98
- await getRepository(User).save(user)
99
-
100
- await getRepository(Invitation).delete(invitation.id)
101
- } else {
102
- // TODO goto signup
103
- }
104
-
105
- return true
106
- }
107
-
108
- export async function sendInvitationEmail({ invitation, user, context }) {
109
- try {
110
- var token = makeInvitationToken()
111
- var verifaction = await saveInvitationToken(invitation.id, token)
112
-
113
- if (verifaction) {
114
- var serviceUrl = new URL(`/auth/accept/${token}`, context.header.referer)
115
-
116
- await sendEmail({
117
- receiver: invitation.email,
118
- subject: 'Invitation',
119
- content: getInvitationEmailForm({
120
- username: user.username,
121
- email: invitation.email,
122
- acceptUrl: serviceUrl
123
- })
124
- })
125
-
126
- return true
127
- }
128
- } catch (e) {
129
- return false
130
- }
131
- }
132
-
133
- export async function resendInvitationEmail(
134
- { email, reference, type }: { email: string; reference: string; type: string },
135
- context
136
- ) {
137
- var invitation = await getRepository(Invitation).findOneBy({
138
- email: ILike(email),
139
- reference,
140
- type
141
- })
142
-
143
- if (!invitation) {
144
- throw new Error(`not found invitation.`)
145
- }
146
-
147
- var user = await getRepository(User).findOne({
148
- where: {
149
- email: ILike(email),
150
- status: UserStatus.ACTIVATED
151
- }
152
- })
153
-
154
- if (!user) {
155
- throw new Error(`user not found: ${email}`)
156
- }
157
-
158
- return await sendInvitationEmail({
159
- invitation,
160
- user,
161
- context
162
- })
163
- }
@@ -1,55 +0,0 @@
1
- import { ILike } from 'typeorm'
2
-
3
- import { getRepository } from '@things-factory/shell'
4
-
5
- import { USER_NOT_FOUND } from '../constants/error-code'
6
- import { AuthError } from '../errors/auth-error'
7
- import { User } from '../service/user/user'
8
-
9
- export async function updateProfile({ id }, newProfiles) {
10
- const repository = getRepository(User)
11
- const user = await repository.findOneBy({ id })
12
- if (!user) {
13
- throw new AuthError({
14
- errorCode: USER_NOT_FOUND
15
- })
16
- }
17
-
18
- /* only 'username', 'name', 'email' and 'locale' attributes can be changed */
19
- var allowed: {
20
- username?: string
21
- name?: string
22
- email?: string
23
- locale?: string
24
- } = ['username', 'name', 'email', 'locale']
25
- .filter(attr => attr in newProfiles)
26
- .reduce((sum, attr) => {
27
- sum[attr] = newProfiles[attr]
28
- return sum
29
- }, {})
30
-
31
- /* check if email and username is unique */
32
- if ('email' in allowed) {
33
- var found: User = await repository.findOne({ where: { email: ILike(allowed.email) } })
34
-
35
- if (found && found.id != id) {
36
- throw new AuthError({
37
- errorCode: AuthError.ERROR_CODES.EMAIL_ALREADY_EXISTS
38
- })
39
- }
40
- }
41
-
42
- if ('username' in allowed) {
43
- var found: User = await repository.findOne({ where: { username: allowed.username } })
44
- if (found && found.id != id) {
45
- throw new AuthError({
46
- errorCode: AuthError.ERROR_CODES.USERNAME_ALREADY_EXISTS
47
- })
48
- }
49
- }
50
-
51
- return await repository.save({
52
- ...user,
53
- ...allowed
54
- })
55
- }
@@ -1,126 +0,0 @@
1
- import { URL } from 'url'
2
-
3
- import { sendEmail } from '@things-factory/email-base'
4
- import { config } from '@things-factory/env'
5
- import { getRepository } from '@things-factory/shell'
6
-
7
- import { PASSWORD_USED_PAST } from '../constants/error-code'
8
- import { AuthError } from '../errors/auth-error'
9
- import { PasswordHistory } from '../service/password-history/password-history'
10
- import { User } from '../service/user/user'
11
- import { VerificationToken, VerificationTokenType } from '../service/verification-token/verification-token'
12
- import { getResetPasswordEmailForm } from '../templates/reset-password-email'
13
- import { makeVerificationToken } from './utils/make-verification-token'
14
- import { saveVerificationToken } from './utils/save-verification-token'
15
-
16
- const HISTORY_SIZE = config.get('password', { history: 0 }).history
17
-
18
- export async function sendPasswordResetEmail({ user, context }) {
19
- try {
20
- var token = makeVerificationToken()
21
- var verifaction = await saveVerificationToken(user.id, token, VerificationTokenType.PASSWORD_RESET)
22
-
23
- if (verifaction) {
24
- var serviceUrl = new URL(`/auth/reset-password?token=${token}`, context.header.referer)
25
- await sendEmail({
26
- receiver: user.email,
27
- subject: 'Reset your password',
28
- content: getResetPasswordEmailForm({
29
- name: user.name,
30
- resetUrl: serviceUrl
31
- })
32
- })
33
-
34
- return true
35
- }
36
- } catch (e) {
37
- return false
38
- }
39
- }
40
-
41
- export async function resetPassword(token, password, context) {
42
- const { t } = context
43
-
44
- const verificationToken = await getRepository(VerificationToken).findOne({
45
- where: {
46
- token,
47
- type: VerificationTokenType.PASSWORD_RESET
48
- }
49
- })
50
-
51
- if (!verificationToken) {
52
- throw new Error(t('text.invalid verification token'))
53
- }
54
-
55
- const { userId } = verificationToken
56
- if (!userId) {
57
- throw new Error(t('text.invalid verification token'))
58
- }
59
-
60
- var user = await getRepository(User).findOneBy({ id: userId })
61
- if (!user) {
62
- throw new Error(t('error.user not found'))
63
- }
64
-
65
- // if (user.status == UserStatus.INACTIVE) {
66
- // throw new Error(t('text.inactive user'))
67
- // }
68
-
69
- /* check if password is following the rule */
70
- User.validatePasswordByRule(password, context?.lng)
71
-
72
- user.password = User.encode(password, user.salt)
73
-
74
- if (HISTORY_SIZE > 0) {
75
- var passwordHistory: PasswordHistory = await getRepository(PasswordHistory).findOneBy({ userId: user.id })
76
- var history = []
77
-
78
- if (passwordHistory) {
79
- try {
80
- history = JSON.parse(passwordHistory.history)
81
- if (!(history instanceof Array)) {
82
- console.error('password history maybe currupted - not an array')
83
- history = []
84
- }
85
- } catch (e) {
86
- console.error('password history currupted - not json format')
87
- }
88
-
89
- const found = history.slice(0, HISTORY_SIZE).find(h => {
90
- return User.verify(h.password, password, h.salt)
91
- })
92
-
93
- if (found) {
94
- throw new AuthError({
95
- errorCode: PASSWORD_USED_PAST
96
- })
97
- }
98
- }
99
- }
100
-
101
- await getRepository(User).save({
102
- ...user,
103
- passwordUpdatedAt: new Date()
104
- })
105
-
106
- await getRepository(VerificationToken).delete({
107
- userId,
108
- token,
109
- type: VerificationTokenType.PASSWORD_RESET
110
- })
111
-
112
- if (HISTORY_SIZE > 0) {
113
- history = [
114
- {
115
- password: user.password,
116
- salt: user.salt
117
- },
118
- ...history
119
- ].slice(0, HISTORY_SIZE)
120
-
121
- await getRepository(PasswordHistory).save({
122
- userId: user.id,
123
- history: JSON.stringify(history)
124
- })
125
- }
126
- }
@@ -1,98 +0,0 @@
1
- import { ILike } from 'typeorm'
2
- import { getRepository } from '@things-factory/shell'
3
-
4
- import { sendUnlockUserEmail } from '../controllers/unlock-user'
5
- import { AuthError } from '../errors/auth-error'
6
- import { User, UserStatus } from '../service/user/user'
7
-
8
- export async function signin(attrs: { username: string; password: string }, context?) {
9
- const { domain } = context?.state || {}
10
- const { username } = attrs
11
-
12
- const repository = getRepository(User)
13
-
14
- var user = await repository.findOne({
15
- where: { username },
16
- relations: ['domains']
17
- })
18
-
19
- if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
20
- user = await repository.findOne({
21
- where: {
22
- email: ILike(username)
23
- },
24
- relations: ['domains']
25
- })
26
- }
27
-
28
- if (!user)
29
- throw new AuthError({
30
- errorCode: AuthError.ERROR_CODES.USER_NOT_FOUND
31
- })
32
-
33
- if (user.status == UserStatus.DELETED) {
34
- throw new AuthError({
35
- errorCode: AuthError.ERROR_CODES.USER_DELETED
36
- })
37
- }
38
-
39
- if (user.status == UserStatus.LOCKED) {
40
- sendUnlockUserEmail({
41
- user,
42
- context
43
- })
44
- throw new AuthError({
45
- errorCode: AuthError.ERROR_CODES.USER_LOCKED,
46
- detail: {
47
- username: user.username,
48
- email: user.email
49
- }
50
- })
51
- }
52
-
53
- if (!User.verify(user.password, attrs.password, user.salt)) {
54
- user.failCount++
55
- if (user.failCount >= 5) user.status = UserStatus.LOCKED
56
- await repository.save(user)
57
- if (user.status == UserStatus.LOCKED) {
58
- sendUnlockUserEmail({
59
- user,
60
- context
61
- })
62
- throw new AuthError({
63
- errorCode: AuthError.ERROR_CODES.USER_LOCKED,
64
- detail: {
65
- username: user.username,
66
- email: user.email
67
- }
68
- })
69
- }
70
- throw new AuthError({
71
- errorCode: AuthError.ERROR_CODES.PASSWORD_NOT_MATCHED,
72
- detail: {
73
- username: user.username,
74
- email: user.email,
75
- failCount: user.failCount
76
- }
77
- })
78
- } else {
79
- user.failCount = 0
80
- await repository.save(user)
81
- }
82
-
83
- if (user.status == UserStatus.INACTIVE) {
84
- throw new AuthError({
85
- errorCode: AuthError.ERROR_CODES.USER_NOT_ACTIVATED,
86
- detail: {
87
- username: user.username,
88
- email: user.email
89
- }
90
- })
91
- }
92
-
93
- return {
94
- user,
95
- token: await user.sign({ subdomain: domain?.subdomain }),
96
- domains: user.domains || []
97
- }
98
- }
@@ -1,72 +0,0 @@
1
- import { ILike } from 'typeorm'
2
- import { getRepository } from '@things-factory/shell'
3
-
4
- import { USER_DUPLICATED } from '../constants/error-code'
5
- import { AuthError } from '../errors/auth-error'
6
- import { User } from '../service/user/user'
7
- import { signin } from './signin'
8
- import { sendVerificationEmail } from './verification'
9
-
10
- export async function signup(attrs, withEmailVerification?: Boolean) {
11
- const { name, username, password, domain, context } = attrs
12
-
13
- /* check if password is following the rule */
14
- User.validatePasswordByRule(password, context.lng)
15
-
16
- const repository = getRepository(User)
17
-
18
- var duplicated = await repository.findOne({
19
- where: { username },
20
- relations: ['domains']
21
- })
22
-
23
- if (!duplicated && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
24
- user = await repository.findOne({
25
- where: { email: ILike(username) },
26
- relations: ['domains']
27
- })
28
- }
29
-
30
- if (duplicated) {
31
- throw new AuthError({
32
- errorCode: USER_DUPLICATED,
33
- detail: {
34
- name,
35
- username
36
- }
37
- })
38
- }
39
-
40
- const salt = User.generateSalt()
41
-
42
- var user = await repository.save({
43
- userType: 'user',
44
- ...attrs,
45
- salt,
46
- password: User.encode(password, salt),
47
- passwordUpdatedAt: new Date(),
48
- domains: domain ? [domain] : []
49
- })
50
-
51
- var succeed = false
52
- if (withEmailVerification) {
53
- succeed = await sendVerificationEmail({
54
- context,
55
- user
56
- })
57
- }
58
-
59
- try {
60
- return {
61
- token: await signin(
62
- {
63
- username,
64
- password
65
- },
66
- { domain }
67
- )
68
- }
69
- } catch (e) {
70
- return { token: null }
71
- }
72
- }