@things-factory/auth-base 8.0.0-beta.9 → 8.0.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 (212) hide show
  1. package/client/actions/auth.ts +24 -0
  2. package/client/auth.ts +272 -0
  3. package/client/bootstrap.ts +47 -0
  4. package/client/directive/privileged.ts +28 -0
  5. package/client/index.ts +3 -0
  6. package/client/profiled.ts +83 -0
  7. package/client/reducers/auth.ts +31 -0
  8. package/dist-client/index.d.ts +0 -1
  9. package/dist-client/index.js +0 -1
  10. package/dist-client/index.js.map +1 -1
  11. package/dist-client/tsconfig.tsbuildinfo +1 -1
  12. package/dist-server/constants/error-code.d.ts +0 -2
  13. package/dist-server/constants/error-code.js +1 -3
  14. package/dist-server/constants/error-code.js.map +1 -1
  15. package/dist-server/controllers/change-pwd.js +2 -2
  16. package/dist-server/controllers/change-pwd.js.map +1 -1
  17. package/dist-server/controllers/delete-user.js +12 -13
  18. package/dist-server/controllers/delete-user.js.map +1 -1
  19. package/dist-server/controllers/invitation.d.ts +1 -2
  20. package/dist-server/controllers/invitation.js +5 -30
  21. package/dist-server/controllers/invitation.js.map +1 -1
  22. package/dist-server/controllers/profile.d.ts +3 -4
  23. package/dist-server/controllers/profile.js +2 -20
  24. package/dist-server/controllers/profile.js.map +1 -1
  25. package/dist-server/controllers/signin.d.ts +1 -4
  26. package/dist-server/controllers/signin.js +1 -17
  27. package/dist-server/controllers/signin.js.map +1 -1
  28. package/dist-server/controllers/signup.js +4 -13
  29. package/dist-server/controllers/signup.js.map +1 -1
  30. package/dist-server/controllers/unlock-user.js +0 -1
  31. package/dist-server/controllers/unlock-user.js.map +1 -1
  32. package/dist-server/controllers/verification.js +0 -1
  33. package/dist-server/controllers/verification.js.map +1 -1
  34. package/dist-server/middlewares/signin-middleware.js +4 -9
  35. package/dist-server/middlewares/signin-middleware.js.map +1 -1
  36. package/dist-server/middlewares/webauthn-middleware.js.map +1 -1
  37. package/dist-server/migrations/1548206416130-SeedUser.js +1 -2
  38. package/dist-server/migrations/1548206416130-SeedUser.js.map +1 -1
  39. package/dist-server/router/auth-checkin-router.js +2 -8
  40. package/dist-server/router/auth-checkin-router.js.map +1 -1
  41. package/dist-server/router/auth-private-process-router.js +7 -12
  42. package/dist-server/router/auth-private-process-router.js.map +1 -1
  43. package/dist-server/router/auth-public-process-router.js +9 -20
  44. package/dist-server/router/auth-public-process-router.js.map +1 -1
  45. package/dist-server/router/auth-signin-router.js +3 -3
  46. package/dist-server/router/auth-signin-router.js.map +1 -1
  47. package/dist-server/router/webauthn-router.js +1 -51
  48. package/dist-server/router/webauthn-router.js.map +1 -1
  49. package/dist-server/service/invitation/invitation-mutation.d.ts +2 -3
  50. package/dist-server/service/invitation/invitation-mutation.js +8 -20
  51. package/dist-server/service/invitation/invitation-mutation.js.map +1 -1
  52. package/dist-server/service/user/user-mutation.d.ts +9 -10
  53. package/dist-server/service/user/user-mutation.js +54 -112
  54. package/dist-server/service/user/user-mutation.js.map +1 -1
  55. package/dist-server/service/user/user-types.d.ts +0 -1
  56. package/dist-server/service/user/user-types.js +0 -4
  57. package/dist-server/service/user/user-types.js.map +1 -1
  58. package/dist-server/service/user/user.d.ts +0 -1
  59. package/dist-server/service/user/user.js +14 -40
  60. package/dist-server/service/user/user.js.map +1 -1
  61. package/dist-server/templates/account-unlock-email.d.ts +1 -2
  62. package/dist-server/templates/account-unlock-email.js +1 -1
  63. package/dist-server/templates/account-unlock-email.js.map +1 -1
  64. package/dist-server/templates/invitation-email.d.ts +1 -2
  65. package/dist-server/templates/invitation-email.js +1 -1
  66. package/dist-server/templates/invitation-email.js.map +1 -1
  67. package/dist-server/templates/verification-email.d.ts +1 -2
  68. package/dist-server/templates/verification-email.js +1 -1
  69. package/dist-server/templates/verification-email.js.map +1 -1
  70. package/dist-server/tsconfig.tsbuildinfo +1 -1
  71. package/package.json +6 -6
  72. package/server/constants/error-code.ts +20 -0
  73. package/server/constants/error-message.ts +0 -0
  74. package/server/constants/max-age.ts +1 -0
  75. package/server/controllers/auth.ts +5 -0
  76. package/server/controllers/change-pwd.ts +99 -0
  77. package/server/controllers/checkin.ts +21 -0
  78. package/server/controllers/delete-user.ts +68 -0
  79. package/server/controllers/invitation.ts +132 -0
  80. package/server/controllers/profile.ts +28 -0
  81. package/server/controllers/reset-password.ts +126 -0
  82. package/server/controllers/signin.ts +79 -0
  83. package/server/controllers/signup.ts +60 -0
  84. package/server/controllers/unlock-user.ts +61 -0
  85. package/server/controllers/utils/make-invitation-token.ts +5 -0
  86. package/server/controllers/utils/make-verification-token.ts +4 -0
  87. package/server/controllers/utils/password-rule.ts +120 -0
  88. package/server/controllers/utils/save-invitation-token.ts +10 -0
  89. package/server/controllers/utils/save-verification-token.ts +12 -0
  90. package/server/controllers/verification.ts +83 -0
  91. package/server/errors/auth-error.ts +24 -0
  92. package/server/errors/index.ts +2 -0
  93. package/server/errors/user-domain-not-match-error.ts +29 -0
  94. package/server/index.ts +37 -0
  95. package/server/middlewares/authenticate-401-middleware.ts +114 -0
  96. package/server/middlewares/domain-authenticate-middleware.ts +78 -0
  97. package/server/middlewares/graphql-authenticate-middleware.ts +13 -0
  98. package/server/middlewares/index.ts +67 -0
  99. package/server/middlewares/jwt-authenticate-middleware.ts +84 -0
  100. package/server/middlewares/signin-middleware.ts +55 -0
  101. package/server/middlewares/webauthn-middleware.ts +127 -0
  102. package/server/migrations/1548206416130-SeedUser.ts +59 -0
  103. package/server/migrations/1566805283882-SeedPrivilege.ts +28 -0
  104. package/server/migrations/index.ts +9 -0
  105. package/server/router/auth-checkin-router.ts +107 -0
  106. package/server/router/auth-private-process-router.ts +107 -0
  107. package/server/router/auth-public-process-router.ts +302 -0
  108. package/server/router/auth-signin-router.ts +55 -0
  109. package/server/router/auth-signup-router.ts +95 -0
  110. package/server/router/index.ts +9 -0
  111. package/server/router/oauth2/index.ts +2 -0
  112. package/server/router/oauth2/oauth2-authorize-router.ts +81 -0
  113. package/server/router/oauth2/oauth2-router.ts +165 -0
  114. package/server/router/oauth2/oauth2-server.ts +262 -0
  115. package/server/router/oauth2/passport-oauth2-client-password.ts +87 -0
  116. package/server/router/oauth2/passport-refresh-token.ts +87 -0
  117. package/server/router/path-base-domain-router.ts +8 -0
  118. package/server/router/site-root-router.ts +48 -0
  119. package/server/router/webauthn-router.ts +87 -0
  120. package/server/routes.ts +80 -0
  121. package/server/service/app-binding/app-binding-mutation.ts +22 -0
  122. package/server/service/app-binding/app-binding-query.ts +92 -0
  123. package/server/service/app-binding/app-binding-types.ts +11 -0
  124. package/server/service/app-binding/app-binding.ts +17 -0
  125. package/server/service/app-binding/index.ts +4 -0
  126. package/server/service/appliance/appliance-mutation.ts +113 -0
  127. package/server/service/appliance/appliance-query.ts +76 -0
  128. package/server/service/appliance/appliance-types.ts +56 -0
  129. package/server/service/appliance/appliance.ts +133 -0
  130. package/server/service/appliance/index.ts +6 -0
  131. package/server/service/application/application-mutation.ts +104 -0
  132. package/server/service/application/application-query.ts +98 -0
  133. package/server/service/application/application-types.ts +76 -0
  134. package/server/service/application/application.ts +216 -0
  135. package/server/service/application/index.ts +6 -0
  136. package/server/service/auth-provider/auth-provider-mutation.ts +159 -0
  137. package/server/service/auth-provider/auth-provider-parameter-spec.ts +24 -0
  138. package/server/service/auth-provider/auth-provider-query.ts +88 -0
  139. package/server/service/auth-provider/auth-provider-type.ts +67 -0
  140. package/server/service/auth-provider/auth-provider.ts +155 -0
  141. package/server/service/auth-provider/index.ts +7 -0
  142. package/server/service/domain-generator/domain-generator-mutation.ts +117 -0
  143. package/server/service/domain-generator/domain-generator-types.ts +46 -0
  144. package/server/service/domain-generator/index.ts +3 -0
  145. package/server/service/granted-role/granted-role-mutation.ts +156 -0
  146. package/server/service/granted-role/granted-role-query.ts +60 -0
  147. package/server/service/granted-role/granted-role.ts +27 -0
  148. package/server/service/granted-role/index.ts +6 -0
  149. package/server/service/index.ts +90 -0
  150. package/server/service/invitation/index.ts +6 -0
  151. package/server/service/invitation/invitation-mutation.ts +63 -0
  152. package/server/service/invitation/invitation-query.ts +33 -0
  153. package/server/service/invitation/invitation-types.ts +11 -0
  154. package/server/service/invitation/invitation.ts +63 -0
  155. package/server/service/login-history/index.ts +5 -0
  156. package/server/service/login-history/login-history-query.ts +51 -0
  157. package/server/service/login-history/login-history-type.ts +12 -0
  158. package/server/service/login-history/login-history.ts +45 -0
  159. package/server/service/partner/index.ts +6 -0
  160. package/server/service/partner/partner-mutation.ts +61 -0
  161. package/server/service/partner/partner-query.ts +102 -0
  162. package/server/service/partner/partner-types.ts +11 -0
  163. package/server/service/partner/partner.ts +57 -0
  164. package/server/service/password-history/index.ts +3 -0
  165. package/server/service/password-history/password-history.ts +16 -0
  166. package/server/service/privilege/index.ts +6 -0
  167. package/server/service/privilege/privilege-directive.ts +77 -0
  168. package/server/service/privilege/privilege-mutation.ts +92 -0
  169. package/server/service/privilege/privilege-query.ts +94 -0
  170. package/server/service/privilege/privilege-types.ts +60 -0
  171. package/server/service/privilege/privilege.ts +102 -0
  172. package/server/service/role/index.ts +6 -0
  173. package/server/service/role/role-mutation.ts +109 -0
  174. package/server/service/role/role-query.ts +155 -0
  175. package/server/service/role/role-types.ts +81 -0
  176. package/server/service/role/role.ts +72 -0
  177. package/server/service/user/domain-query.ts +24 -0
  178. package/server/service/user/index.ts +7 -0
  179. package/server/service/user/user-mutation.ts +413 -0
  180. package/server/service/user/user-query.ts +145 -0
  181. package/server/service/user/user-types.ts +97 -0
  182. package/server/service/user/user.ts +354 -0
  183. package/server/service/users-auth-providers/index.ts +5 -0
  184. package/server/service/users-auth-providers/users-auth-providers.ts +71 -0
  185. package/server/service/verification-token/index.ts +3 -0
  186. package/server/service/verification-token/verification-token.ts +60 -0
  187. package/server/service/web-auth-credential/index.ts +3 -0
  188. package/server/service/web-auth-credential/web-auth-credential.ts +67 -0
  189. package/server/templates/account-unlock-email.ts +65 -0
  190. package/server/templates/invitation-email.ts +66 -0
  191. package/server/templates/reset-password-email.ts +65 -0
  192. package/server/templates/verification-email.ts +66 -0
  193. package/server/types.ts +21 -0
  194. package/server/utils/accepts.ts +11 -0
  195. package/server/utils/access-token-cookie.ts +61 -0
  196. package/server/utils/check-permission.ts +52 -0
  197. package/server/utils/check-user-belongs-domain.ts +19 -0
  198. package/server/utils/check-user-has-role.ts +29 -0
  199. package/server/utils/encrypt-state.ts +22 -0
  200. package/server/utils/get-aes-256-key.ts +13 -0
  201. package/server/utils/get-domain-from-hostname.ts +7 -0
  202. package/server/utils/get-domain-users.ts +38 -0
  203. package/server/utils/get-secret.ts +13 -0
  204. package/server/utils/get-user-domains.ts +112 -0
  205. package/translations/en.json +1 -5
  206. package/translations/ja.json +1 -5
  207. package/translations/ko.json +3 -6
  208. package/translations/ms.json +1 -5
  209. package/translations/zh.json +1 -5
  210. package/dist-client/verify-webauthn.d.ts +0 -13
  211. package/dist-client/verify-webauthn.js +0 -72
  212. package/dist-client/verify-webauthn.js.map +0 -1
@@ -0,0 +1,159 @@
1
+ import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { In } from 'typeorm'
3
+
4
+ import { AuthProvider } from './auth-provider'
5
+ import { NewAuthProvider, AuthProviderPatch } from './auth-provider-type'
6
+
7
+ @Resolver(AuthProvider)
8
+ export class AuthProviderMutation {
9
+ @Directive('@transaction')
10
+ @Mutation(returns => AuthProvider, { description: 'To create new AuthProvider' })
11
+ async createAuthProvider(
12
+ @Arg('authProvider') authProvider: NewAuthProvider,
13
+ @Ctx() context: ResolverContext
14
+ ): Promise<AuthProvider> {
15
+ const { domain, user, tx } = context.state
16
+
17
+ return await tx.getRepository(AuthProvider).save({
18
+ ...authProvider,
19
+ domain,
20
+ creator: user,
21
+ updater: user
22
+ })
23
+ }
24
+
25
+ @Directive('@transaction')
26
+ @Mutation(returns => AuthProvider, { description: 'To modify AuthProvider information' })
27
+ async updateAuthProvider(
28
+ @Arg('id') id: string,
29
+ @Arg('patch') patch: AuthProviderPatch,
30
+ @Ctx() context: ResolverContext
31
+ ): Promise<AuthProvider> {
32
+ const { domain, user, tx } = context.state
33
+
34
+ const repository = tx.getRepository(AuthProvider)
35
+ const authProvider = await repository.findOne({
36
+ where: { domain: { id: domain.id }, id }
37
+ })
38
+
39
+ return await repository.save({
40
+ ...authProvider,
41
+ ...patch,
42
+ updater: user
43
+ })
44
+ }
45
+
46
+ @Directive('@transaction')
47
+ @Mutation(returns => [AuthProvider])
48
+ async updateMultipleAuthProvider(
49
+ @Arg('patches', type => [AuthProviderPatch]) patches: AuthProviderPatch[],
50
+ @Ctx() context: ResolverContext
51
+ ): Promise<AuthProvider[]> {
52
+ const { domain, user, tx } = context.state
53
+
54
+ let results = []
55
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag === '+')
56
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
57
+
58
+ if (_createRecords.length > 0) {
59
+ for (let i = 0; i < _createRecords.length; i++) {
60
+ const newRecord = _createRecords[i]
61
+
62
+ let foundAuthProvider = await tx.getRepository(AuthProvider).findOne({
63
+ where: { domain: { id: domain.id }, type: newRecord.type }
64
+ })
65
+
66
+ if (foundAuthProvider) {
67
+ throw new Error('Duplicated authProvider found')
68
+ }
69
+
70
+ const result: AuthProvider = await tx.getRepository(AuthProvider).save({
71
+ domain: domain,
72
+ creator: user,
73
+ updater: user,
74
+ ...newRecord
75
+ })
76
+
77
+ results.push({ ...result, cuFlag: '+' })
78
+ }
79
+ }
80
+
81
+ if (_updateRecords.length > 0) {
82
+ for (let i = 0; i < _updateRecords.length; i++) {
83
+ const updatedRecord = _updateRecords[i]
84
+ const authProvider = await tx.getRepository(AuthProvider).findOne({
85
+ where: { domain: { id: domain.id }, id: updatedRecord.id }
86
+ })
87
+
88
+ const result = await tx.getRepository(AuthProvider).save({
89
+ ...authProvider,
90
+ ...updatedRecord,
91
+ updater: user
92
+ })
93
+
94
+ results.push({ ...result, cuFlag: 'M' })
95
+ }
96
+ }
97
+
98
+ return results
99
+ }
100
+
101
+ @Directive('@transaction')
102
+ @Mutation(returns => Boolean, { description: 'To delete AuthProvider' })
103
+ async deleteAuthProvider(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
104
+ const { domain, tx } = context.state
105
+
106
+ await tx.getRepository(AuthProvider).delete({ domain: { id: domain.id }, id })
107
+
108
+ return true
109
+ }
110
+
111
+ @Directive('@transaction')
112
+ @Mutation(returns => Boolean)
113
+ async deleteAuthProviders(
114
+ @Arg('ids', type => [String]) ids: string[],
115
+ @Ctx() context: ResolverContext
116
+ ): Promise<Boolean> {
117
+ const { domain, user, tx } = context.state
118
+
119
+ const authProviders = await tx.getRepository(AuthProvider).find({
120
+ where: {
121
+ domain: { id: domain.id },
122
+ id: In(ids)
123
+ }
124
+ })
125
+
126
+ await Promise.all(
127
+ authProviders.map(async (authProvider: AuthProvider) => {
128
+ await tx.getRepository(AuthProvider).save({
129
+ ...authProvider,
130
+ deletedAt: new Date(),
131
+ updater: user
132
+ })
133
+ })
134
+ )
135
+ return true
136
+ }
137
+
138
+ @Directive('@transaction')
139
+ @Directive('@privilege(superUserGranted:true)')
140
+ @Mutation(returns => Boolean, { description: 'To synchronize auth-providers users' })
141
+ async synchronizeAuthProviderUsers(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
142
+ const { domain, user, tx } = context.state
143
+
144
+ const repository = tx.getRepository(AuthProvider)
145
+ const authProvider = await repository.findOne({
146
+ where: { domain: { id: domain.id }, id },
147
+ relations: ['domain']
148
+ })
149
+
150
+ const { type } = authProvider
151
+ const { synchronizeUsers } = AuthProvider.getAuthProviderImpl(type) || {}
152
+
153
+ if (synchronizeUsers) {
154
+ return await synchronizeUsers(authProvider, context)
155
+ } else {
156
+ throw new Error(`No AuthProviderImpl for the type '${type}'`)
157
+ }
158
+ }
159
+ }
@@ -0,0 +1,24 @@
1
+ import { Field, ObjectType } from 'type-graphql'
2
+
3
+ import { ScalarObject } from '@things-factory/shell'
4
+
5
+ @ObjectType()
6
+ export class AuthProviderParameterSpec {
7
+ @Field()
8
+ type: string
9
+
10
+ @Field()
11
+ label: string
12
+
13
+ @Field()
14
+ name: string
15
+
16
+ @Field({ nullable: true })
17
+ placeholder?: string
18
+
19
+ @Field(type => ScalarObject, { nullable: true })
20
+ property?: { [key: string]: any }
21
+
22
+ @Field(type => ScalarObject, { nullable: true })
23
+ styles?: { [key: string]: any }
24
+ }
@@ -0,0 +1,88 @@
1
+ import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
+ import { User } from '../user/user'
4
+ import { AuthProvider, AuthProviderTypeList } from './auth-provider'
5
+ import { AuthProviderList } from './auth-provider-type'
6
+
7
+ @Resolver(AuthProvider)
8
+ export class AuthProviderQuery {
9
+ @Query(returns => AuthProviderTypeList!, { nullable: true, description: 'To fetch a AuthProvider' })
10
+ authProviderTypes(@Ctx() context: ResolverContext): AuthProviderTypeList {
11
+ const { domain } = context.state
12
+
13
+ return AuthProvider.getAuthProviderTypes()
14
+ }
15
+
16
+ @Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
17
+ @Query(returns => AuthProvider!, { nullable: true, description: 'To fetch a AuthProvider' })
18
+ async authProvider(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<AuthProvider> {
19
+ const { domain } = context.state
20
+
21
+ return await getRepository(AuthProvider).findOne({
22
+ where: { domain: { id: domain.id }, id }
23
+ })
24
+ }
25
+
26
+ @Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
27
+ @Query(returns => AuthProviderList, { description: 'To fetch multiple AuthProviders' })
28
+ async authProviders(
29
+ @Args(type => ListParam) params: ListParam,
30
+ @Ctx() context: ResolverContext
31
+ ): Promise<AuthProviderList> {
32
+ const { domain } = context.state
33
+
34
+ const queryBuilder = getQueryBuilderFromListParams({
35
+ domain,
36
+ params,
37
+ repository: await getRepository(AuthProvider),
38
+ searchables: ['type']
39
+ })
40
+
41
+ const [items, total] = await queryBuilder.getManyAndCount()
42
+
43
+ return { items, total }
44
+ }
45
+
46
+ @FieldResolver(type => String)
47
+ clientSecret(@Root() authProvider: AuthProvider): string {
48
+ const clientSecret = authProvider.clientSecret
49
+
50
+ if (!clientSecret || clientSecret.length <= 2) {
51
+ return clientSecret // 입력 문자열의 길이가 2 이하인 경우 그대로 반환
52
+ }
53
+ const firstChar = clientSecret.charAt(0)
54
+ const lastChar = clientSecret.charAt(clientSecret.length - 1)
55
+ const maskedPart = '*'.repeat(clientSecret.length - 2)
56
+
57
+ return firstChar + maskedPart + lastChar
58
+ }
59
+
60
+ @FieldResolver(type => String)
61
+ privateKey(@Root() authProvider: AuthProvider): string {
62
+ const privateKey = authProvider.privateKey
63
+
64
+ if (!privateKey || privateKey.length <= 2) {
65
+ return privateKey // 입력 문자열의 길이가 2 이하인 경우 그대로 반환
66
+ }
67
+ const firstChar = privateKey.charAt(0)
68
+ const lastChar = privateKey.charAt(privateKey.length - 1)
69
+ const maskedPart = '*'.repeat(privateKey.length - 2)
70
+
71
+ return firstChar + maskedPart + lastChar
72
+ }
73
+
74
+ @FieldResolver(type => Domain)
75
+ async domain(@Root() authProvider: AuthProvider): Promise<Domain> {
76
+ return authProvider.domainId && (await getRepository(Domain).findOneBy({ id: authProvider.domainId }))
77
+ }
78
+
79
+ @FieldResolver(type => User)
80
+ async updater(@Root() authProvider: AuthProvider): Promise<User> {
81
+ return authProvider.updaterId && (await getRepository(User).findOneBy({ id: authProvider.updaterId }))
82
+ }
83
+
84
+ @FieldResolver(type => User)
85
+ async creator(@Root() authProvider: AuthProvider): Promise<User> {
86
+ return authProvider.creatorId && (await getRepository(User).findOneBy({ id: authProvider.creatorId }))
87
+ }
88
+ }
@@ -0,0 +1,67 @@
1
+ import { ObjectType, Field, InputType, Int, ID } from 'type-graphql'
2
+
3
+ import { ScalarObject } from '@things-factory/shell'
4
+ import { AuthProvider } from './auth-provider'
5
+
6
+ @InputType()
7
+ export class NewAuthProvider {
8
+ @Field()
9
+ type: string
10
+
11
+ @Field({ nullable: true })
12
+ active?: boolean
13
+
14
+ @Field({ nullable: true })
15
+ tenantId?: string
16
+
17
+ @Field({ nullable: true })
18
+ clientId?: string
19
+
20
+ @Field({ nullable: true })
21
+ clientSecret?: string
22
+
23
+ @Field({ nullable: true })
24
+ privateKey?: string
25
+
26
+ @Field(type => ScalarObject, { nullable: true })
27
+ params?: { [key: string]: any }
28
+ }
29
+
30
+ @InputType()
31
+ export class AuthProviderPatch {
32
+ @Field(type => ID, { nullable: true })
33
+ id?: string
34
+
35
+ @Field({ nullable: true })
36
+ type?: string
37
+
38
+ @Field({ nullable: true })
39
+ active?: boolean
40
+
41
+ @Field({ nullable: true })
42
+ tenantId?: string
43
+
44
+ @Field({ nullable: true })
45
+ clientId?: string
46
+
47
+ @Field({ nullable: true })
48
+ clientSecret?: string
49
+
50
+ @Field({ nullable: true })
51
+ privateKey?: string
52
+
53
+ @Field(type => ScalarObject, { nullable: true })
54
+ params?: { [key: string]: any }
55
+
56
+ @Field({ nullable: true })
57
+ cuFlag?: string
58
+ }
59
+
60
+ @ObjectType()
61
+ export class AuthProviderList {
62
+ @Field(type => [AuthProvider])
63
+ items: AuthProvider[]
64
+
65
+ @Field(type => Int)
66
+ total: number
67
+ }
@@ -0,0 +1,155 @@
1
+ import {
2
+ CreateDateColumn,
3
+ UpdateDateColumn,
4
+ Entity,
5
+ Index,
6
+ Column,
7
+ RelationId,
8
+ ManyToOne,
9
+ OneToMany,
10
+ PrimaryGeneratedColumn
11
+ } from 'typeorm'
12
+ import { Directive, ObjectType, Field, Int, ID } from 'type-graphql'
13
+
14
+ import { Domain, ScalarObject, encryptTransformer } from '@things-factory/shell'
15
+ import { User } from '../user/user'
16
+ import { UsersAuthProviders } from '../users-auth-providers/users-auth-providers'
17
+ import { AuthProviderParameterSpec } from './auth-provider-parameter-spec'
18
+
19
+ export type AuthProviderImpl = {
20
+ type: string
21
+ description: string
22
+ help: string
23
+ parameterSpec: AuthProviderParameterSpec
24
+ synchronizeUsers: (authProvider: AuthProvider, context: ResolverContext) => Promise<boolean>
25
+ }
26
+
27
+ export type AuthProviderRegistry = {
28
+ [type: string]: AuthProviderImpl
29
+ }
30
+
31
+ @ObjectType()
32
+ export class AuthProviderType {
33
+ @Field()
34
+ type: string
35
+
36
+ @Field({ nullable: true })
37
+ description: string
38
+
39
+ @Field({ nullable: true })
40
+ help: string
41
+
42
+ @Field(type => [AuthProviderParameterSpec], { nullable: true })
43
+ parameterSpec: AuthProviderParameterSpec[]
44
+ }
45
+
46
+ @ObjectType()
47
+ export class AuthProviderTypeList {
48
+ @Field(type => [AuthProviderType])
49
+ items: AuthProviderType[]
50
+
51
+ @Field(type => Int)
52
+ total: number
53
+ }
54
+
55
+ @Entity()
56
+ @Index('ix_auth_provider_0', (authProvider: AuthProvider) => [authProvider.domain, authProvider.type], {
57
+ unique: true
58
+ })
59
+ @ObjectType({ description: 'Entity for AuthProvider' })
60
+ export class AuthProvider {
61
+ @PrimaryGeneratedColumn('uuid')
62
+ @Field(type => ID)
63
+ readonly id: string
64
+
65
+ @ManyToOne(type => Domain)
66
+ @Field(type => Domain)
67
+ domain?: Domain
68
+
69
+ @RelationId((authProvider: AuthProvider) => authProvider.domain)
70
+ domainId?: string
71
+
72
+ @Column()
73
+ @Field({ nullable: true })
74
+ type?: string
75
+
76
+ @Column({ nullable: true })
77
+ @Field({ nullable: true })
78
+ active?: boolean
79
+
80
+ @Directive('@privilege(category: "security", privilege: "query", domainOwnerGranted: true)')
81
+ @Column({ nullable: true })
82
+ @Field({ nullable: true })
83
+ tenantId?: string
84
+
85
+ @Directive('@privilege(category: "security", privilege: "query", domainOwnerGranted: true)')
86
+ @Column({ nullable: true })
87
+ @Field({ nullable: true })
88
+ clientId?: string
89
+
90
+ @Directive('@privilege(category: "security", privilege: "query", domainOwnerGranted: true)')
91
+ @Column({ nullable: true, transformer: encryptTransformer })
92
+ @Field({ nullable: true })
93
+ clientSecret?: string
94
+
95
+ @Directive('@privilege(category: "security", privilege: "query", domainOwnerGranted: true)')
96
+ @Column({ nullable: true, transformer: encryptTransformer })
97
+ @Field({ nullable: true })
98
+ privateKey?: string
99
+
100
+ @Column('simple-json', { nullable: true })
101
+ @Field(type => ScalarObject, { nullable: true })
102
+ params?: { [key: string]: any }
103
+
104
+ @OneToMany(() => UsersAuthProviders, usersAuthProviders => usersAuthProviders.authProvider)
105
+ @Field(type => [UsersAuthProviders], { nullable: true })
106
+ usersAuthProviders?: UsersAuthProviders[]
107
+
108
+ @CreateDateColumn()
109
+ @Field({ nullable: true })
110
+ createdAt?: Date
111
+
112
+ @UpdateDateColumn()
113
+ @Field({ nullable: true })
114
+ updatedAt?: Date
115
+
116
+ @ManyToOne(type => User, { nullable: true })
117
+ @Field(type => User, { nullable: true })
118
+ creator?: User
119
+
120
+ @RelationId((authProvider: AuthProvider) => authProvider.creator)
121
+ creatorId?: string
122
+
123
+ @ManyToOne(type => User, { nullable: true })
124
+ @Field(type => User, { nullable: true })
125
+ updater?: User
126
+
127
+ @RelationId((authProvider: AuthProvider) => authProvider.updater)
128
+ updaterId?: string
129
+
130
+ static registry = {}
131
+
132
+ public static register(type: string, provider: AuthProviderImpl) {
133
+ AuthProvider.registry[type] = provider
134
+ }
135
+
136
+ public static getAuthProviderTypes(): AuthProviderTypeList {
137
+ const items = Object.values(AuthProvider.registry).map(({ type, description, help, parameterSpec }) => {
138
+ return {
139
+ type,
140
+ description,
141
+ help,
142
+ parameterSpec
143
+ }
144
+ })
145
+
146
+ return {
147
+ items,
148
+ total: items.length
149
+ }
150
+ }
151
+
152
+ public static getAuthProviderImpl(type: string) {
153
+ return AuthProvider.registry[type]
154
+ }
155
+ }
@@ -0,0 +1,7 @@
1
+ import { AuthProvider } from './auth-provider'
2
+ import { AuthProviderQuery } from './auth-provider-query'
3
+ import { AuthProviderMutation } from './auth-provider-mutation'
4
+
5
+ export const entities = [AuthProvider]
6
+ export const resolvers = [AuthProviderQuery, AuthProviderMutation]
7
+ export const subscribers = []
@@ -0,0 +1,117 @@
1
+ import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
2
+ import { ILike, In, Repository } from 'typeorm'
3
+
4
+ import { Domain, getRepository } from '@things-factory/shell'
5
+ import { slugger } from '@things-factory/utils'
6
+
7
+ import { Privilege } from '../privilege/privilege'
8
+ import { Role } from '../role/role'
9
+ import { User } from '../user/user'
10
+ import { DomainGeneratorInput, DomainUserRoleInput } from './domain-generator-types'
11
+
12
+ @Resolver()
13
+ export class DomainGeneratorMutation {
14
+ @Directive('@privilege(superUserGranted: true)')
15
+ @Directive('@transaction')
16
+ @Mutation(returns => Domain)
17
+ async domainRegister(
18
+ @Arg('domainInput') domainInput: DomainGeneratorInput,
19
+ @Ctx() context: ResolverContext
20
+ ): Promise<Domain> {
21
+ const { user } = context.state
22
+ const { name, description } = domainInput
23
+ const domainRepo: Repository<Domain> = getRepository(Domain)
24
+ const subdomain: string = slugger(name)
25
+
26
+ const domain: Domain = await domainRepo.findOneBy({ subdomain })
27
+ if (domain) {
28
+ throw new Error('domain is duplicated')
29
+ }
30
+
31
+ return await domainRepo.save({ name, description, subdomain, owner: user.id })
32
+ }
33
+
34
+ @Directive('@transaction')
35
+ @Mutation(returns => Domain)
36
+ async domainUserRoleRegister(
37
+ @Arg('newDomainInfo') newDomainInfo: DomainUserRoleInput,
38
+ @Ctx() context: ResolverContext
39
+ ): Promise<Domain> {
40
+ const { tx } = context.state
41
+ // 도메인 생성
42
+ const { domain, users, roles } = newDomainInfo
43
+ const domainOwner = users.find(user => user.owner === true)
44
+
45
+ const domainRepository: Repository<Domain> = tx.getRepository(Domain)
46
+ const roleRepository: Repository<Role> = tx.getRepository(Role)
47
+ const userRepository: Repository<User> = tx.getRepository(User)
48
+ const privilegeRepository: Repository<Privilege> = tx.getRepository(Privilege)
49
+
50
+ const subdomain: string = slugger(domain.name)
51
+
52
+ const newDomain = await domainRepository.save({
53
+ name: domain.name,
54
+ description: domain.description,
55
+ subdomain
56
+ })
57
+
58
+ // 역할 생성
59
+ const newRoles: Role[] = await Promise.all(
60
+ roles.map(async (role: Role) => {
61
+ if (role.privileges?.length) {
62
+ const privilegeIds: string[] = role.privileges.map((p: Privilege) => p.id)
63
+ role.privileges = await privilegeRepository.findBy({
64
+ id: In(privilegeIds)
65
+ })
66
+ }
67
+
68
+ role.domain = newDomain
69
+ return await roleRepository.save(role)
70
+ })
71
+ )
72
+
73
+ // 사용자 생성
74
+ let inviteUsers = []
75
+ let createUsers = []
76
+ users.forEach(user => (user.isInvitee ? inviteUsers.push(user) : createUsers.push(user)))
77
+
78
+ // create user
79
+ await Promise.all(
80
+ createUsers.map(async user => {
81
+ user.domains = [newDomain]
82
+ user.password = User.encode(user.password, user.salt)
83
+ user.salt = User.generateSalt()
84
+ user.passwordUpdatedAt = new Date()
85
+ user.userType = 'user'
86
+ user.roles = filterUserRoles(user.roles, newRoles)
87
+
88
+ return await userRepository.save(user)
89
+ })
90
+ )
91
+
92
+ // invite user
93
+ await Promise.all(
94
+ inviteUsers.map(async inviteUser => {
95
+ const user: User = await userRepository.findOne({
96
+ where: { email: inviteUser.email },
97
+ relations: ['domains', 'roles']
98
+ })
99
+
100
+ user.domains = [...user.domains, newDomain]
101
+ user.roles = [...user.roles, ...filterUserRoles(inviteUser.roles, newRoles)]
102
+
103
+ return await userRepository.save(user)
104
+ })
105
+ )
106
+
107
+ // domain owner
108
+ const { id } = await userRepository.findOne({ where: { email: ILike(domainOwner.email) } })
109
+ newDomain.owner = id
110
+ return await domainRepository.save(newDomain)
111
+ }
112
+ }
113
+
114
+ function filterUserRoles(userRoles: Role[], newRoles: Role[]): Role[] {
115
+ const userRoleNames: string[] = userRoles.map((r: Role) => r.name)
116
+ return newRoles.filter((r: Role) => userRoleNames.indexOf(r.name) >= 0)
117
+ }
@@ -0,0 +1,46 @@
1
+ import { Field, InputType } from 'type-graphql'
2
+ import { GraphQLEmailAddress } from 'graphql-scalars'
3
+ import { DomainInput } from '@things-factory/shell'
4
+ import { NewRole } from '../role/role-types'
5
+
6
+ @InputType()
7
+ export class DomainGeneratorInput {
8
+ @Field()
9
+ name: string
10
+
11
+ @Field({ nullable: true })
12
+ description?: string
13
+ }
14
+
15
+ @InputType()
16
+ export class DomainUserRoleInput {
17
+ @Field(type => DomainInput)
18
+ domain: DomainInput
19
+
20
+ @Field(type => [NewUserByDomainWizardInput])
21
+ users: NewUserByDomainWizardInput[]
22
+
23
+ @Field(type => [NewRole])
24
+ roles: NewRole[]
25
+ }
26
+
27
+ @InputType()
28
+ export class NewUserByDomainWizardInput {
29
+ @Field()
30
+ name: string
31
+
32
+ @Field(type => GraphQLEmailAddress)
33
+ email: string
34
+
35
+ @Field({ nullable: true })
36
+ password: string
37
+
38
+ @Field({ nullable: true })
39
+ isInvitee: Boolean
40
+
41
+ @Field()
42
+ owner: Boolean
43
+
44
+ @Field(type => [NewRole])
45
+ roles: NewRole[]
46
+ }
@@ -0,0 +1,3 @@
1
+ import { DomainGeneratorMutation } from './domain-generator-mutation'
2
+
3
+ export const resolvers = [DomainGeneratorMutation]