@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.
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,149 +0,0 @@
1
- import Router from 'koa-router'
2
- import { getRepository } from '@things-factory/shell'
3
- import { appPackage } from '@things-factory/env'
4
-
5
- import { generateRegistrationOptions, generateAuthenticationOptions } from '@simplewebauthn/server'
6
-
7
- import { WebAuthCredential } from '../service/web-auth-credential/web-auth-credential'
8
- import { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/server/script/deps'
9
- import { setAccessTokenCookie } from '../utils/access-token-cookie'
10
- import { createWebAuthnMiddleware } from '../middlewares/webauthn-middleware'
11
-
12
- export const webAuthnGlobalPublicRouter = new Router()
13
- export const webAuthnGlobalPrivateRouter = new Router()
14
-
15
- const { name: rpName } = appPackage as any
16
-
17
- // Generate authentication challenge for the currently logged-in user
18
- webAuthnGlobalPrivateRouter.get('/auth/verify-webauthn/challenge', async (context, next) => {
19
- const { user } = context.state
20
- const rpID = context.hostname
21
-
22
- if (!user) {
23
- context.status = 401
24
- context.body = { error: 'User not authenticated' }
25
- return
26
- }
27
-
28
- const webAuthCredentials = await getRepository(WebAuthCredential).find({
29
- where: { user: { id: user.id } }
30
- })
31
-
32
- if (webAuthCredentials.length === 0) {
33
- context.status = 400
34
- context.body = { error: 'No biometric credentials registered for this user' }
35
- return
36
- }
37
-
38
- const options = await generateAuthenticationOptions({
39
- rpID,
40
- userVerification: 'preferred',
41
- allowCredentials: webAuthCredentials.map(credential => ({
42
- id: credential.credentialId,
43
- type: 'public-key'
44
- }))
45
- })
46
-
47
- context.session.challenge = options.challenge
48
- context.body = options
49
- })
50
-
51
- // Verify biometric authentication
52
- webAuthnGlobalPrivateRouter.post(
53
- '/auth/verify-webauthn',
54
- /* reuse webauthn-login as webauthn-verify strategy */
55
- createWebAuthnMiddleware('webauthn-login'),
56
- async (context, next) => {
57
- const { user } = context.state
58
- const { request } = context
59
- const { body: reqBody } = request
60
-
61
- if (!user) {
62
- context.status = 401
63
- context.body = { verified: false, message: 'User not authenticated' }
64
- return
65
- }
66
-
67
- context.body = {
68
- verified: true,
69
- message: 'Biometric authentication successful'
70
- }
71
-
72
- await next()
73
- }
74
- )
75
-
76
- // Generate registration challenge for the currently logged-in user
77
- webAuthnGlobalPrivateRouter.get('/auth/register-webauthn/challenge', async (context, next) => {
78
- const { user } = context.state
79
- const rpID = context.hostname
80
-
81
- const webAuthCredentials = await getRepository(WebAuthCredential).find({
82
- where: {
83
- user: { id: user.id }
84
- }
85
- })
86
-
87
- const options: PublicKeyCredentialCreationOptionsJSON = await generateRegistrationOptions({
88
- rpName,
89
- rpID,
90
- userName: user.email,
91
- userDisplayName: user.name,
92
- // Don't prompt users for additional information about the authenticator
93
- // (Recommended for smoother UX)
94
- attestationType: 'none',
95
- // Prevent users from re-registering existing authenticators
96
- excludeCredentials: webAuthCredentials.map(credential => ({
97
- id: credential.credentialId
98
- // Optional
99
- // transports: credential.transports
100
- })),
101
- authenticatorSelection: {
102
- // Defaults
103
- residentKey: 'preferred',
104
- userVerification: 'preferred',
105
- // Optional
106
- authenticatorAttachment: 'platform'
107
- }
108
- })
109
-
110
- context.session.challenge = options.challenge
111
- context.body = options
112
- })
113
-
114
- // Verify registration
115
- webAuthnGlobalPrivateRouter.post('/auth/verify-registration', createWebAuthnMiddleware('webauthn-register'))
116
-
117
- // Generate sign-in challenge
118
- webAuthnGlobalPublicRouter.get('/auth/signin-webauthn/challenge', async (context, next) => {
119
- const rpID = context.hostname
120
-
121
- const options = await generateAuthenticationOptions({
122
- rpID,
123
- userVerification: 'preferred'
124
- })
125
-
126
- context.session.challenge = options.challenge
127
- context.body = options
128
- })
129
-
130
- // Sign in with biometric authentication
131
- webAuthnGlobalPublicRouter.post(
132
- '/auth/signin-webauthn',
133
- createWebAuthnMiddleware('webauthn-login'),
134
- async (context, next) => {
135
- const { domain, user } = context.state
136
- const { request } = context
137
- const { body: reqBody } = request
138
-
139
- const token = await user.sign({ subdomain: domain?.subdomain })
140
- setAccessTokenCookie(context, token)
141
-
142
- var redirectURL = `/auth/checkin${domain ? '/' + domain.subdomain : ''}?redirect_to=${encodeURIComponent(reqBody.redirectTo || '/')}`
143
-
144
- /* Due to the two-step interaction, it will be processed by fetch(...) in the browser, so it cannot be handled with a redirect(3xx) response. Therefore, respond with redirectURL as data. */
145
- context.body = { redirectURL, verified: true }
146
-
147
- await next()
148
- }
149
- )
package/server/routes.ts DELETED
@@ -1,80 +0,0 @@
1
- import { config } from '@things-factory/env'
2
-
3
- import { domainAuthenticateMiddleware, jwtAuthenticateMiddleware } from './middlewares'
4
- import {
5
- authCheckinRouter,
6
- authPrivateProcessRouter,
7
- authPublicProcessRouter,
8
- authSigninRouter,
9
- authSignupRouter,
10
- oauth2AuthorizeRouter,
11
- oauth2Router,
12
- pathBaseDomainRouter,
13
- siteRootRouter,
14
- webAuthnGlobalPublicRouter,
15
- webAuthnGlobalPrivateRouter
16
- } from './router'
17
-
18
- import { setAccessTokenCookie } from './utils/access-token-cookie'
19
-
20
- const isPathBaseDomain = !config.get('subdomain') && !config.get('useVirtualHostBasedDomain')
21
-
22
- process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
23
- globalPublicRouter.use(siteRootRouter.routes(), siteRootRouter.allowedMethods())
24
- globalPublicRouter.use(authPublicProcessRouter.routes(), authPublicProcessRouter.allowedMethods())
25
-
26
- /* ssoMiddleware가 정의되어있다면, /auth/sso-signin 패스를 활성화한다. */
27
- if (app.ssoMiddlewares.length > 0) {
28
- authSigninRouter.get('/auth/sso-signin', app.ssoMiddlewares[0], async context => {
29
- const { user } = context.state
30
-
31
- const token = await user.sign()
32
- setAccessTokenCookie(context, token)
33
-
34
- context.redirect('/auth/checkin')
35
- })
36
- }
37
- })
38
-
39
- process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
40
- globalPrivateRouter.use(jwtAuthenticateMiddleware)
41
-
42
- /* globalPrivateRouter based nested-routers */
43
- globalPrivateRouter.use(authCheckinRouter.routes(), authCheckinRouter.allowedMethods())
44
- globalPrivateRouter.use(authPrivateProcessRouter.routes(), authPrivateProcessRouter.allowedMethods())
45
- globalPrivateRouter.use(webAuthnGlobalPrivateRouter.routes(), webAuthnGlobalPrivateRouter.allowedMethods())
46
- })
47
-
48
- process.on('bootstrap-module-domain-public-route' as any, (app, domainPublicRouter) => {
49
- /* domainPublicRouter based nested-routers */
50
- domainPublicRouter.use(authSigninRouter.routes(), authSigninRouter.allowedMethods())
51
- domainPublicRouter.use(authSignupRouter.routes(), authSignupRouter.allowedMethods())
52
- domainPublicRouter.use(webAuthnGlobalPublicRouter.routes(), webAuthnGlobalPublicRouter.allowedMethods())
53
-
54
- /* path '/admin/oauth/...' is deprecated. should use path '/oauth/...' for oauth2 related routing */
55
- domainPublicRouter.use('/oauth', oauth2Router.routes(), oauth2Router.allowedMethods()) // if i use context
56
- })
57
-
58
- process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRouter) => {
59
- domainPrivateRouter.use(jwtAuthenticateMiddleware)
60
- domainPrivateRouter.use(domainAuthenticateMiddleware)
61
-
62
- /* domainPrivateRouter based nested-routers */
63
- if (isPathBaseDomain) {
64
- // pathBaseDomainRouter는 history-fallback의 경우에 인증 처리를 하기 위한 라우터이다.
65
- // (보통, URL 링크등을 통해서 domain path URL로 바로 요청하는 경우에 해당한다.)
66
- // pathBaseDomainRouter는 domain path를 domain-private-router를 사용하는 것을 전제로 한다.
67
- domainPrivateRouter.use('/domain/:domain/oauth', oauth2AuthorizeRouter.routes(), oauth2AuthorizeRouter.allowedMethods())
68
- domainPrivateRouter.use('/domain', pathBaseDomainRouter.routes(), pathBaseDomainRouter.allowedMethods())
69
- }
70
-
71
- // Client Routing : path 확장자가 없는 경우는 대부분 client 라우팅에 해당한다.
72
- // 즉, browser-history-fallback 으로 index.html을 send 하는 경우에, 사용자 로그인이 필요한 경우에,
73
- // 화면깜박임없이 signin page로 redirect 하고자하는 목적의 설정이다.
74
- // domain-private 라우트를 통과하고 싶지 않다면, regexp를 조정한다.
75
- // '(.[^.]+)' 은 '', '/'는 제외하고, '/xxx', '/yyy/zzz' 등 모두를 포함하지만, path에 '.'가 있는 경우는 제외한다.
76
- // (테스트는 여기서 : http://forbeslindesay.github.io/express-route-tester/)
77
- domainPrivateRouter.get('(.[^.]+)', async (context, next) => {
78
- await next()
79
- })
80
- })
@@ -1,22 +0,0 @@
1
- import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'
2
-
3
- import { getRepository } from '@things-factory/shell'
4
-
5
- import { User } from '../user/user'
6
- import { AppBinding } from './app-binding'
7
-
8
- @Resolver(AppBinding)
9
- export class AppBindingMutation {
10
- @Mutation(returns => Boolean)
11
- async deleteAppBinding(@Arg('id') id: string, @Ctx() context: ResolverContext) {
12
- const { domain } = context.state
13
-
14
- // TODO 이 사용자가 이 도메인에 속한 사용자인지 확인해야함.
15
- // TODO 다른 도메인에도 포함되어있다면, domains-users 관게와 해당 도메인 관련 정보만 삭제해야 함.
16
- await getRepository(User).delete({
17
- id
18
- })
19
-
20
- return true
21
- }
22
- }
@@ -1,92 +0,0 @@
1
- import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
2
- import { SelectQueryBuilder } from 'typeorm'
3
-
4
- import { buildQuery, getRepository, ListParam } from '@things-factory/shell'
5
-
6
- import { buildDomainUsersQueryBuilder } from '../../utils/get-domain-users'
7
- import { Application } from '../application/application'
8
- import { User } from '../user/user'
9
- import { UserList } from '../user/user-types'
10
- import { AppBinding } from './app-binding'
11
- import { AppBindingList } from './app-binding-types'
12
-
13
- @Resolver(AppBinding)
14
- export class AppBindingQuery {
15
- @Query(returns => AppBinding)
16
- async appBinding(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<User> {
17
- const { domain } = context.state
18
-
19
- // TODO should check domain is available
20
- return await getRepository(User).findOneBy({ id, userType: 'application' })
21
- }
22
-
23
- /* TODO optimize query */
24
- @Query(returns => AppBindingList)
25
- async appBindings(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<UserList> {
26
- const { domain } = context.state
27
-
28
- // const convertedParams = convertListParams(params)
29
- // convertedParams.where = {
30
- // ...convertedParams.where,
31
- // userType: 'application'
32
- // } as any
33
-
34
- const alias: string = 'USER'
35
- const qb: SelectQueryBuilder<User> = buildDomainUsersQueryBuilder(domain.id, alias)
36
- buildQuery(qb, params, null, { domainRef: false })
37
- var [items] = await qb
38
- // .leftJoinAndSelect(`${alias}.roles`, 'ROLES')
39
- // .leftJoinAndSelect(`${alias}.creator`, 'CREATOR')
40
- // .leftJoinAndSelect(`${alias}.updater`, 'UPDATER')
41
- .getManyAndCount()
42
-
43
- items = items.filter((user: User) => user.userType == 'application')
44
-
45
- // var boundApps = await Promise.all(
46
- // items
47
- // .filter((user: User) => user.userType == 'application')
48
- // .map(async (user: User) => {
49
- // const email = user.email
50
- // const appKey = email.substr(0, email.lastIndexOf('@'))
51
- // const application = await getRepository(Application).findOneBy({
52
- // appKey
53
- // })
54
-
55
- // return {
56
- // ...user,
57
- // application,
58
- // scope: user.roles.map(role => role.name).join(','),
59
- // refreshToken: user.password
60
- // }
61
- // })
62
- // )
63
-
64
- return { items, total: items.length }
65
- }
66
-
67
- @FieldResolver(type => Application)
68
- async application(@Root() appBinding: AppBinding): Promise<Application> {
69
- return await getRepository(Application).findOneBy({ id: appBinding.reference })
70
- }
71
-
72
- @FieldResolver(type => String)
73
- async scope(@Root() appBinding: AppBinding): Promise<string> {
74
- const u = await getRepository(User).findOne({ where: { reference: appBinding.reference }, relations: ['roles'] })
75
- return u.roles.map(role => role.name).join(',')
76
- }
77
-
78
- @FieldResolver(type => String)
79
- async refreshToken(@Root() appBinding: AppBinding): Promise<string> {
80
- return appBinding.password
81
- }
82
-
83
- @FieldResolver(type => User)
84
- async updater(@Root() appBinding: AppBinding): Promise<User> {
85
- return await getRepository(User).findOneBy({ id: appBinding.updaterId })
86
- }
87
-
88
- @FieldResolver(type => User)
89
- async creator(@Root() appBinding: AppBinding): Promise<User> {
90
- return await getRepository(User).findOneBy({ id: appBinding.creatorId })
91
- }
92
- }
@@ -1,11 +0,0 @@
1
- import { Field, Int, ObjectType } from 'type-graphql'
2
- import { AppBinding } from './app-binding'
3
-
4
- @ObjectType()
5
- export class AppBindingList {
6
- @Field(type => [AppBinding], { nullable: true })
7
- items?: [AppBinding]
8
-
9
- @Field(type => Int, { nullable: true })
10
- total?: number
11
- }
@@ -1,17 +0,0 @@
1
- import { ObjectType, Field, Directive } from 'type-graphql'
2
- import { Domain } from '@things-factory/shell'
3
- import { Application } from '../application/application'
4
- import { User, UserStatus } from '../user/user'
5
-
6
- @ObjectType()
7
- export class AppBinding extends User {
8
- @Field({ nullable: true })
9
- application: Application
10
-
11
- @Field({ nullable: true })
12
- scope: string
13
-
14
- @Field({ nullable: true })
15
- @Directive('@privilege(category: "security", privilege: "query", domainOwnerGranted: true)')
16
- refreshToken: string
17
- }
@@ -1,4 +0,0 @@
1
- import { AppBindingQuery } from './app-binding-query'
2
- import { AppBindingMutation } from './app-binding-mutation'
3
-
4
- export const resolvers = [AppBindingQuery, AppBindingMutation]
@@ -1,113 +0,0 @@
1
- import { Directive, Arg, Ctx, Mutation, Resolver } from 'type-graphql'
2
-
3
- import { getRepository } from '@things-factory/shell'
4
-
5
- import { User, UserStatus } from '../user/user'
6
- import { Appliance } from './appliance'
7
- import { AppliancePatch, NewAppliance } from './appliance-types'
8
-
9
- const crypto = require('crypto')
10
-
11
- @Resolver(Appliance)
12
- export class ApplianceMutation {
13
- @Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
14
- @Mutation(returns => Appliance, { description: 'To create new appliance' })
15
- async createAppliance(
16
- @Arg('appliance') appliance: NewAppliance,
17
- @Ctx() context: ResolverContext
18
- ): Promise<Appliance> {
19
- return await getRepository(Appliance).save({
20
- domain: context.state.domain,
21
- creator: context.state.user,
22
- updater: context.state.user,
23
- ...appliance
24
- })
25
- }
26
-
27
- @Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
28
- @Mutation(returns => Boolean, { description: 'To delete appliance' })
29
- async deleteAppliance(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Boolean> {
30
- const { domain } = context.state
31
- // TODO 이 사용자가 이 도메인에 속한 사용자인지 확인해야함.
32
- // TODO 다른 도메인에도 포함되어있다면, domains-users 관게와 해당 도메인 관련 정보만 삭제해야 함.
33
- await getRepository(User).delete({
34
- reference: id,
35
- userType: 'appliance'
36
- })
37
-
38
- await getRepository(Appliance).delete({ domain: { id: domain.id }, id })
39
-
40
- return true
41
- }
42
-
43
- @Directive('@privilege(category: "security", privilege: "mutation", domainOwnerGranted: true)')
44
- @Mutation(returns => Appliance)
45
- async generateApplianceSecret(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Appliance> {
46
- const { domain, user } = context.state
47
-
48
- const appliance: Appliance = await getRepository(Appliance).findOneBy({ domain: { id: domain.id }, id })
49
-
50
- const appuserEmail = `${crypto.randomUUID()}@${domain?.subdomain}`
51
- let appuser: User = await getRepository(User).findOne({
52
- where: {
53
- reference: id,
54
- userType: 'appliance'
55
- },
56
- relations: ['domains']
57
- })
58
-
59
- if (!appuser) {
60
- /* newly create appuser */
61
- appuser = await getRepository(User).save({
62
- email: appuserEmail,
63
- name: appliance.name,
64
- userType: 'appliance',
65
- reference: id,
66
- status: UserStatus.ACTIVATED,
67
- domains: [domain],
68
- updater: user,
69
- creator: user
70
- })
71
- }
72
-
73
- if (!appuser.domains.find(d => d.id === domain.id)) {
74
- context.throw(401, 'appliance is not allowed for this domain')
75
- }
76
-
77
- appuser.password = Appliance.generateAccessToken(domain, appuser, appliance)
78
-
79
- await getRepository(User).save(appuser)
80
-
81
- return await getRepository(Appliance).save({
82
- ...appliance,
83
- accessToken: appuser.password,
84
- updater: user
85
- })
86
- }
87
-
88
- @Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
89
- @Mutation(returns => Appliance)
90
- async updateAppliance(
91
- @Arg('id') id: string,
92
- @Arg('patch') patch: AppliancePatch,
93
- @Ctx() context: ResolverContext
94
- ): Promise<Appliance> {
95
- const { domain } = context.state
96
-
97
- const applianceRepository = getRepository(Appliance)
98
- const userRepository = getRepository(User)
99
- const appliance = await applianceRepository.findOne({ where: { domain: { id: domain.id }, id } })
100
- const user = await userRepository.findOne({ where: { reference: id, userType: 'appliance' } })
101
-
102
- userRepository.save({
103
- ...user,
104
- name: patch?.name || user.name
105
- })
106
-
107
- return await applianceRepository.save({
108
- ...appliance,
109
- ...patch,
110
- updater: context.state.user
111
- })
112
- }
113
- }
@@ -1,76 +0,0 @@
1
- import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'
2
-
3
- import { getQueryBuilderFromListParams, Domain, getRepository, ListParam } from '@things-factory/shell'
4
-
5
- import { Appliance } from '../appliance/appliance'
6
- import { User } from '../user/user'
7
- import { ApplianceList } from './appliance-types'
8
-
9
- @Resolver(Appliance)
10
- export class ApplianceQuery {
11
- @Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
12
- @Query(returns => Appliance, { description: ' To fetch appliance' })
13
- async appliance(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Appliance> {
14
- const { domain } = context.state
15
- return await getRepository(Appliance).findOneBy({ domain: { id: domain.id }, id })
16
- }
17
-
18
- @Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
19
- @Query(returns => ApplianceList, { description: 'To fetch multiple appliance' })
20
- async appliances(
21
- @Args(type => ListParam) params: ListParam,
22
- @Ctx() context: ResolverContext
23
- ): Promise<ApplianceList> {
24
- const { domain } = context.state
25
-
26
- const queryBuilder = getQueryBuilderFromListParams({
27
- domain,
28
- params,
29
- repository: getRepository(Appliance),
30
- alias: 'appliance',
31
- searchables: ['name', 'description']
32
- })
33
-
34
- const [items, total] = await queryBuilder.getManyAndCount()
35
-
36
- return { items, total }
37
- }
38
-
39
- @Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
40
- @Query(returns => ApplianceList, { description: 'To fetch multiple appliance' })
41
- async edges(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ApplianceList> {
42
- const { domain } = context.state
43
-
44
- const queryBuilder = getQueryBuilderFromListParams({
45
- domain,
46
- params,
47
- repository: getRepository(Appliance),
48
- alias: 'appliance',
49
- searchables: ['name', 'description']
50
- })
51
-
52
- const [items, total] = await queryBuilder.getManyAndCount()
53
-
54
- return { items, total }
55
- }
56
-
57
- @FieldResolver(type => String)
58
- async accessToken(@Root() appliance: Appliance, @Ctx() context: ResolverContext) {
59
- return appliance.accessToken
60
- }
61
-
62
- @FieldResolver(type => Domain)
63
- async domain(@Ctx() context: ResolverContext) {
64
- return context.state.domain
65
- }
66
-
67
- @FieldResolver(type => User)
68
- async updater(@Root() appliance: Appliance): Promise<User> {
69
- return await getRepository(User).findOneBy({ id: appliance.updaterId })
70
- }
71
-
72
- @FieldResolver(type => User)
73
- async creator(@Root() appliance: Appliance): Promise<User> {
74
- return await getRepository(User).findOneBy({ id: appliance.creatorId })
75
- }
76
- }
@@ -1,56 +0,0 @@
1
- import { ObjectType, InputType, Field, ID, Int } from 'type-graphql'
2
- import { Appliance } from './appliance'
3
-
4
- @ObjectType()
5
- export class ApplianceList {
6
- @Field(type => [Appliance], { nullable: true })
7
- items?: Appliance[]
8
-
9
- @Field(type => Int, { nullable: true })
10
- total?: number
11
- }
12
-
13
- @InputType()
14
- export class AppliancePatch {
15
- @Field(type => ID, { nullable: true })
16
- id?: string
17
-
18
- @Field({ nullable: true })
19
- serialNo?: string
20
-
21
- @Field({ nullable: true })
22
- name?: string
23
-
24
- @Field({ nullable: true })
25
- brand?: string
26
-
27
- @Field({ nullable: true })
28
- model?: string
29
-
30
- @Field({ nullable: true })
31
- description?: string
32
-
33
- @Field({ nullable: true })
34
- netmask?: string
35
- }
36
-
37
- @InputType()
38
- export class NewAppliance {
39
- @Field()
40
- serialNo: string
41
-
42
- @Field()
43
- name: string
44
-
45
- @Field()
46
- brand: string
47
-
48
- @Field()
49
- model: string
50
-
51
- @Field({ nullable: true })
52
- description?: string
53
-
54
- @Field({ nullable: true })
55
- netmask?: string
56
- }