@things-factory/shell 6.2.48 → 6.2.50

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 (31) hide show
  1. package/dist-server/middlewares/domain-middleware.js +45 -9
  2. package/dist-server/middlewares/domain-middleware.js.map +1 -1
  3. package/dist-server/server-dev.js +0 -23
  4. package/dist-server/server-dev.js.map +1 -1
  5. package/dist-server/server.js +0 -23
  6. package/dist-server/server.js.map +1 -1
  7. package/dist-server/service/domain/{domain-resolver.d.ts → domain-Mutation.d.ts} +4 -7
  8. package/dist-server/service/domain/{domain-resolver.js → domain-Mutation.js} +25 -61
  9. package/dist-server/service/domain/domain-Mutation.js.map +1 -0
  10. package/dist-server/service/domain/domain-query.d.ts +9 -0
  11. package/dist-server/service/domain/domain-query.js +74 -0
  12. package/dist-server/service/domain/domain-query.js.map +1 -0
  13. package/dist-server/service/domain/domain-types.js.map +1 -1
  14. package/dist-server/service/domain/domain.d.ts +10 -0
  15. package/dist-server/service/domain/domain.js +5 -0
  16. package/dist-server/service/domain/domain.js.map +1 -1
  17. package/dist-server/service/domain/index.d.ts +3 -2
  18. package/dist-server/service/domain/index.js +3 -2
  19. package/dist-server/service/domain/index.js.map +1 -1
  20. package/dist-server/service/index.d.ts +1 -1
  21. package/dist-server/tsconfig.tsbuildinfo +1 -1
  22. package/package.json +2 -2
  23. package/server/middlewares/domain-middleware.ts +52 -9
  24. package/server/server-dev.ts +0 -30
  25. package/server/server.ts +0 -30
  26. package/server/service/domain/{domain-resolver.ts → domain-mutation.ts} +24 -45
  27. package/server/service/domain/domain-query.ts +52 -0
  28. package/server/service/domain/domain-types.ts +1 -1
  29. package/server/service/domain/domain.ts +14 -0
  30. package/server/service/domain/index.ts +3 -2
  31. package/dist-server/service/domain/domain-resolver.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/shell",
3
- "version": "6.2.48",
3
+ "version": "6.2.50",
4
4
  "description": "Core module for framework",
5
5
  "bin": {
6
6
  "things-factory": "bin/things-factory",
@@ -133,5 +133,5 @@
133
133
  "pg": "^8.7.3",
134
134
  "sqlite3": "^5.0.8"
135
135
  },
136
- "gitHead": "70ed4f01ef662cde4d99911dc9374abd564cbe0e"
136
+ "gitHead": "4dc51db04b745ac434d2bb874038ac4c3b47989b"
137
137
  }
@@ -1,17 +1,60 @@
1
+ import requestIp from 'request-ip'
1
2
  import { getDomainFromURL } from '../utils'
2
3
 
3
4
  export async function domainMiddleware(context: any, next: any) {
4
- const { domain } = context.state
5
+ var { domain } = context.state
6
+ if (!domain) {
7
+ /*
8
+ * The domainType should be checked only when signin and checkin.
9
+ * For purposes such as API calls, the target domainType may be different from the system domainType.
10
+ * So, we don't check domainType here.
11
+ */
12
+ domain = await getDomainFromURL(context)
13
+ }
14
+
5
15
  if (domain) {
6
- return await next()
16
+ const ip = context.ip || requestIp.getClientIp(context.req)
17
+ const { whitelist = [], blacklist = [], protectedlist = [], privileges = [] } = domain.iplist || {}
18
+
19
+ if (Array.isArray(whitelist) && whitelist.length > 0) {
20
+ /* whitelist 우선 */
21
+ const whitelisted =
22
+ Array.isArray(whitelist) &&
23
+ whitelist.some(item => {
24
+ return new RegExp(item).test(ip)
25
+ })
26
+
27
+ if (!whitelisted) {
28
+ context.status = 403
29
+ return
30
+ }
31
+ } else {
32
+ const blacklisted =
33
+ Array.isArray(blacklist) &&
34
+ blacklist.some(item => {
35
+ return new RegExp(item).test(ip)
36
+ })
37
+
38
+ if (blacklisted) {
39
+ context.status = 403
40
+ return
41
+ }
42
+ }
43
+
44
+ if (Array.isArray(protectedlist) && protectedlist.length > 0) {
45
+ const protectedIP = protectedlist.some(item => {
46
+ return new RegExp(item).test(ip)
47
+ })
48
+
49
+ context.state.unsafeIP = !protectedIP
50
+
51
+ if (!protectedIP) {
52
+ context.state.prohibitedPrivileges = privileges
53
+ }
54
+ }
7
55
  }
8
56
 
9
- /*
10
- * The domainType should be checked only when signin and checkin.
11
- * For purposes such as API calls, the target domainType may be different from the system domainType.
12
- * So, we don't check domainType here.
13
- */
14
- context.state.domain = await getDomainFromURL(context)
57
+ context.state.domain = domain
15
58
 
16
- await next()
59
+ return next()
17
60
  }
@@ -15,14 +15,12 @@ import { useServer } from 'graphql-ws/lib/use/ws'
15
15
  import { createServer } from 'http'
16
16
  import Koa from 'koa'
17
17
  import koaBodyParser from 'koa-bodyparser'
18
- import ip from 'koa-ip'
19
18
  import koaStatic from 'koa-static'
20
19
  import compose from 'koa-compose'
21
20
  import { historyApiFallback } from 'koa2-connect-history-api-fallback'
22
21
  import { WebSocketServer } from 'ws'
23
22
  import co from 'co'
24
23
  import http from 'http'
25
- import requestIp from 'request-ip'
26
24
 
27
25
  import koaWebpack from '@hatiolab/koa-webpack'
28
26
  import cors from '@koa/cors'
@@ -116,34 +114,6 @@ const bootstrap = async () => {
116
114
  })
117
115
  )
118
116
 
119
- const whitelist = config.get('whitelist')
120
- const blacklist = config.get('blacklist')
121
- const protectedlist = config.get('protectedlist')
122
-
123
- if (whitelist || blacklist) {
124
- app.use(
125
- ip({
126
- whitelist,
127
- blacklist,
128
- handler: async (ctx, next) => {
129
- ctx.status = 403
130
- }
131
- })
132
- )
133
- }
134
-
135
- if (protectedlist) {
136
- app.use((context, next) => {
137
- const ip = context.ip || requestIp.getClientIp(context.req)
138
-
139
- context.state.protected = protectedlist.some(item => {
140
- return new RegExp(item).test(ip)
141
- })
142
-
143
- return next()
144
- })
145
- }
146
-
147
117
  var subscriptionMiddleware = []
148
118
  process.emit('bootstrap-module-subscription' as any, app, subscriptionMiddleware)
149
119
 
package/server/server.ts CHANGED
@@ -15,14 +15,12 @@ import { useServer } from 'graphql-ws/lib/use/ws'
15
15
  import { createServer } from 'http'
16
16
  import Koa from 'koa'
17
17
  import koaBodyParser from 'koa-bodyparser'
18
- import ip from 'koa-ip'
19
18
  import koaStatic from 'koa-static'
20
19
  import compose from 'koa-compose'
21
20
  import { historyApiFallback } from 'koa2-connect-history-api-fallback'
22
21
  import { WebSocketServer } from 'ws'
23
22
  import co from 'co'
24
23
  import http from 'http'
25
- import requestIp from 'request-ip'
26
24
 
27
25
  import cors from '@koa/cors'
28
26
  import { config, loader, logger, orderedModuleNames } from '@things-factory/env'
@@ -91,34 +89,6 @@ const bootstrap = async () => {
91
89
  })
92
90
  )
93
91
 
94
- const whitelist = config.get('whitelist')
95
- const blacklist = config.get('blacklist')
96
- const protectedlist = config.get('protectedlist')
97
-
98
- if (whitelist || blacklist) {
99
- app.use(
100
- ip({
101
- whitelist,
102
- blacklist,
103
- handler: async (ctx, next) => {
104
- ctx.status = 403
105
- }
106
- })
107
- )
108
- }
109
-
110
- if (protectedlist) {
111
- app.use((context, next) => {
112
- const ip = context.ip || requestIp.getClientIp(context.req)
113
-
114
- context.state.protected = protectedlist.some(item => {
115
- return new RegExp(item).test(ip)
116
- })
117
-
118
- return next()
119
- })
120
- }
121
-
122
92
  var subscriptionMiddleware = []
123
93
  process.emit('bootstrap-module-subscription' as any, app, subscriptionMiddleware)
124
94
 
@@ -1,53 +1,16 @@
1
- import { Arg, Args, Ctx, Directive, Mutation, Query, Resolver, FieldResolver, Root } from 'type-graphql'
1
+ import { Arg, Args, Ctx, Directive, Mutation, Query, Resolver, Root } from 'type-graphql'
2
2
  import { In, Repository } from 'typeorm'
3
3
 
4
4
  import { slugger } from '@things-factory/utils'
5
5
 
6
6
  import { getRepository } from '../../initializers/database'
7
- import { getQueryBuilderFromListParams } from '../../utils/get-query-builder-from-list-params'
8
7
 
9
- import { ListParam } from '../common-types/list-param'
10
- import { Domain } from './domain'
11
- import { DomainList, DomainPatch } from './domain-types'
8
+ import { Domain, IPList } from './domain'
9
+ import { DomainPatch } from './domain-types'
10
+ import { ScalarObject } from '../common-types'
12
11
 
13
12
  @Resolver(Domain)
14
- export class DomainResolver {
15
- @Directive('@privilege(category: "system", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
16
- @Query(returns => Domain, { description: 'To fetch domain' })
17
- async domain(@Arg('id') id: string, @Ctx() context: any): Promise<Domain> {
18
- const repository = getRepository(Domain)
19
-
20
- return await repository.findOneBy({ id })
21
- }
22
-
23
- @Directive('@privilege(superUserGranted: true)')
24
- @Query(returns => DomainList, { description: 'To fetch all domains (Only superuser is granted this privilege.)' })
25
- async domains(@Args() params: ListParam, @Ctx() context: any): Promise<DomainList> {
26
- const queryBuilder = await getQueryBuilderFromListParams({
27
- repository: getRepository(Domain),
28
- alias: 'ContactPoint',
29
- params,
30
- searchables: ['name', 'description', 'subdomain']
31
- })
32
-
33
- const [items, total] = await queryBuilder.getManyAndCount()
34
-
35
- return { items, total }
36
- }
37
-
38
- // @Query(returns => Boolean, { description: 'To check if given domain is exist' })
39
- // async checkExistsDomain(@Arg('name') name: string) {
40
- // const domainRepository: Repository<Domain> = getRepository(Domain)
41
- // const targetSubdomain: string = slugger(name)
42
-
43
- // const oldDomain = await domainRepository.findOneBy({ subdomain: targetSubdomain })
44
- // if (oldDomain) {
45
- // throw new Error('domain is duplicated')
46
- // }
47
-
48
- // return true
49
- // }
50
-
13
+ export class DomainMutation {
51
14
  @Directive('@transaction')
52
15
  @Directive('@privilege(superUserGranted: true)')
53
16
  @Mutation(returns => Domain, { description: 'To create domain (Only superuser is granted this privilege.)' })
@@ -134,8 +97,24 @@ export class DomainResolver {
134
97
  return true
135
98
  }
136
99
 
137
- @FieldResolver(type => Domain)
138
- async parent(@Root() domain: Domain): Promise<Domain> {
139
- return domain.parentId && (await getRepository(Domain).findOneBy({ id: domain.parentId }))
100
+ @Directive('@transaction')
101
+ @Directive(
102
+ '@privilege(category: "security", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'
103
+ )
104
+ @Mutation(returns => ScalarObject, { nullable: true, description: 'To update secure IP list for domain' })
105
+ async updateSecureIPList(
106
+ @Arg('iplist', type => ScalarObject) iplist: IPList,
107
+ @Ctx() context: any
108
+ ): Promise<IPList | null> {
109
+ const { domain } = context.state
110
+ const repository = getRepository(Domain)
111
+ // const domain: Domain = await repository.findOneBy({ id })
112
+
113
+ const { iplist: result } = await repository.save({
114
+ ...domain,
115
+ iplist
116
+ } as any)
117
+
118
+ return result
140
119
  }
141
120
  }
@@ -0,0 +1,52 @@
1
+ import { Arg, Args, Ctx, Directive, Mutation, Query, Resolver, FieldResolver, Root } from 'type-graphql'
2
+ import { In, Repository } from 'typeorm'
3
+
4
+ import { getRepository } from '../../initializers/database'
5
+ import { getQueryBuilderFromListParams } from '../../utils/get-query-builder-from-list-params'
6
+
7
+ import { ListParam } from '../common-types/list-param'
8
+ import { Domain, IPList } from './domain'
9
+ import { DomainList } from './domain-types'
10
+ import { ScalarObject } from '../common-types'
11
+
12
+ @Resolver(Domain)
13
+ export class DomainQuery {
14
+ @Directive('@privilege(superUserGranted: true)')
15
+ @Query(returns => Domain, { description: 'To fetch domain' })
16
+ async domain(@Arg('id') id: string, @Ctx() context: any): Promise<Domain> {
17
+ const repository = getRepository(Domain)
18
+
19
+ return await repository.findOneBy({ id })
20
+ }
21
+
22
+ @Directive('@privilege(superUserGranted: true)')
23
+ @Query(returns => DomainList, { description: 'To fetch all domains (Only superuser is granted this privilege.)' })
24
+ async domains(@Args() params: ListParam, @Ctx() context: any): Promise<DomainList> {
25
+ const queryBuilder = await getQueryBuilderFromListParams({
26
+ repository: getRepository(Domain),
27
+ alias: 'ContactPoint',
28
+ params,
29
+ searchables: ['name', 'description', 'subdomain']
30
+ })
31
+
32
+ const [items, total] = await queryBuilder.getManyAndCount()
33
+
34
+ return { items, total }
35
+ }
36
+
37
+ @Directive('@privilege(category: "security", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
38
+ @Query(returns => ScalarObject, { nullable: true, description: 'To fetch domain' })
39
+ async secureIPList(@Ctx() context: any): Promise<IPList | null> {
40
+ const { domain } = context.state
41
+ // const repository = getRepository(Domain)
42
+
43
+ // const { iplist } = await repository.findOneBy({ id })
44
+
45
+ return domain.iplist
46
+ }
47
+
48
+ @FieldResolver(type => Domain)
49
+ async parent(@Root() domain: Domain): Promise<Domain> {
50
+ return domain.parentId && (await getRepository(Domain).findOneBy({ id: domain.parentId }))
51
+ }
52
+ }
@@ -1,5 +1,5 @@
1
1
  import { ObjectType, InputType, Field, Int } from 'type-graphql'
2
- import { Domain } from './domain'
2
+ import { Domain, IPList } from './domain'
3
3
  import { ObjectRef, ScalarObject } from '../common-types'
4
4
 
5
5
  @InputType()
@@ -19,6 +19,16 @@ const domainPrimaryOption = config.get('domainPrimaryOption')
19
19
  const domainPrimaryType = domainPrimaryOption?.type
20
20
  const domainPrimaryStrategy = domainPrimaryOption?.strategy
21
21
 
22
+ export type IPList = {
23
+ whitelist?: string[]
24
+ blacklist?: string[]
25
+ protectedlist?: string[]
26
+ privileges?: {
27
+ category: string
28
+ name: string
29
+ }[]
30
+ }
31
+
22
32
  @Entity()
23
33
  @Index('ix_domain_0', (domain: Domain) => [domain.subdomain, domain.deletedAt], {
24
34
  unique: true,
@@ -115,6 +125,10 @@ export class Domain {
115
125
  @Column({ nullable: true })
116
126
  theme: string
117
127
 
128
+ @Column('simple-json', { nullable: true })
129
+ @Field(type => ScalarObject, { nullable: true })
130
+ iplist?: IPList
131
+
118
132
  @Column('simple-json', { nullable: true })
119
133
  @Field(type => ScalarObject, { nullable: true })
120
134
  attributes?: any
@@ -1,5 +1,6 @@
1
1
  import { Domain } from './domain'
2
- import { DomainResolver } from './domain-resolver'
2
+ import { DomainQuery } from './domain-query'
3
+ import { DomainMutation } from './domain-Mutation'
3
4
 
4
5
  export const entities = [Domain]
5
- export const resolvers = [DomainResolver]
6
+ export const resolvers = [DomainQuery, DomainMutation]
@@ -1 +0,0 @@
1
- {"version":3,"file":"domain-resolver.js","sourceRoot":"","sources":["../../../server/service/domain/domain-resolver.ts"],"names":[],"mappings":";;;;AAAA,+CAAwG;AACxG,qCAAwC;AAExC,iDAA+C;AAE/C,0DAA2D;AAC3D,uGAA8F;AAE9F,2DAAsD;AACtD,qCAAiC;AACjC,iDAAwD;AAGjD,IAAM,cAAc,GAApB,MAAM,cAAc;IAGnB,AAAN,KAAK,CAAC,MAAM,CAAY,EAAU,EAAS,OAAY;QACrD,MAAM,UAAU,GAAG,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAA;QAExC,OAAO,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC3C,CAAC;IAIK,AAAN,KAAK,CAAC,OAAO,CAAS,MAAiB,EAAS,OAAY;QAC1D,MAAM,YAAY,GAAG,MAAM,IAAA,kEAA6B,EAAC;YACvD,UAAU,EAAE,IAAA,wBAAa,EAAC,eAAM,CAAC;YACjC,KAAK,EAAE,cAAc;YACrB,MAAM;YACN,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC;SAClD,CAAC,CAAA;QAEF,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAA;QAE3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAED,mFAAmF;IACnF,uDAAuD;IACvD,uEAAuE;IACvE,kDAAkD;IAElD,uFAAuF;IACvF,qBAAqB;IACrB,8CAA8C;IAC9C,MAAM;IAEN,gBAAgB;IAChB,IAAI;IAKE,AAAN,KAAK,CAAC,YAAY,CAAqB,WAAwB;QAC7D,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,CAAA;QACzC,MAAM,UAAU,GAAuB,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAA;QAC5D,MAAM,SAAS,GAAW,IAAA,eAAO,EAAC,IAAI,CAAC,CAAA;QAEvC,MAAM,MAAM,GAAW,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;QAChE,IAAI,MAAM,EAAE;YACV,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;SACxC;QAED,OAAO,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAA;IAChE,CAAC;IAKK,AAAN,KAAK,CAAC,YAAY,CAAc,IAAY;QAC1C,OAAO,MAAM,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,CAAC;IAOK,AAAN,KAAK,CAAC,aAAa,CAA+B,KAAe;QAC/D,MAAM,OAAO,GAAa,MAAM,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAA,YAAE,EAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAA;QAC1F,MAAM,SAAS,GAAa,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAE5D,MAAM,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IAC3D,CAAC;IAOK,AAAN,KAAK,CAAC,YAAY,CAAc,IAAY,EAAmC,KAAkB;QAC/F,MAAM,UAAU,GAAG,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAA;QACxC,MAAM,MAAM,GAAW,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QAE3D,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,EAAE;YAChD,OAAO,KAAK,CAAC,MAAM,CAAA;SACpB;QAED,OAAO,MAAM,UAAU,CAAC,IAAI,CAAC,gCACxB,MAAM,GACN,KAAK,CACF,CAAC,CAAA;IACX,CAAC;IAOK,AAAN,KAAK,CAAC,aAAa,CAAsC,OAAsB;QAC7E,MAAM,UAAU,GAAuB,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAA;QAE5D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAEzD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;YACvB,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAC,YAAY,EAAC,EAAE;gBACpC,MAAM,MAAM,GAAW,MAAM,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;gBAEnF,IAAI,YAAY,CAAC,IAAI,EAAE;oBACrB,YAAY,CAAC,SAAS,GAAG,IAAA,eAAO,EAAC,YAAY,CAAC,IAAI,CAAC,CAAA;iBACpD;gBAED,IAAI,YAAY,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,EAAE;oBAC9D,OAAO,YAAY,CAAC,MAAM,CAAA;iBAC3B;gBAED,MAAM,UAAU,CAAC,IAAI,CAAC,gCACjB,MAAM,GACN,YAAY,CACT,CAAC,CAAA;YACX,CAAC,CAAC,CAAA;SACH;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAGK,AAAN,KAAK,CAAC,MAAM,CAAS,MAAc;QACjC,OAAO,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAA,wBAAa,EAAC,eAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;IAC5F,CAAC;CACF,CAAA;AA5HO;IAFL,IAAA,wBAAS,EAAC,sGAAsG,CAAC;IACjH,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,eAAM,EAAE,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;IAC/C,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;4CAIzC;AAIK;IAFL,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,yBAAU,EAAE,EAAE,WAAW,EAAE,kEAAkE,EAAE,CAAC;IACnG,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,sBAAS;;6CAWtC;AAkBK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,eAAM,EAAE,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;IACzF,mBAAA,IAAA,kBAAG,EAAC,aAAa,CAAC,CAAA;;6CAAc,0BAAW;;kDAW9D;AAKK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,eAAM,EAAE,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;IACzF,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;;;;kDAE9B;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE;QAC5B,WAAW,EAAE,wEAAwE;KACtF,CAAC;IACmB,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;;;;mDAKhD;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,eAAM,EAAE;QAC3B,WAAW,EAAE,8DAA8D;KAC5E,CAAC;IACkB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,0BAAW,CAAC,CAAA;;qDAAQ,0BAAW;;kDAYhG;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,oCAAoC,CAAC;IAC/C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE;QAC5B,WAAW,EAAE,wEAAwE;KACtF,CAAC;IACmB,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,0BAAW,CAAC,CAAC,CAAA;;;;mDAyBvD;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,eAAM,CAAC;IAChB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAS,eAAM;;4CAElC;AA9HU,cAAc;IAD1B,IAAA,uBAAQ,EAAC,eAAM,CAAC;GACJ,cAAc,CA+H1B;AA/HY,wCAAc","sourcesContent":["import { Arg, Args, Ctx, Directive, Mutation, Query, Resolver, FieldResolver, Root } from 'type-graphql'\nimport { In, Repository } from 'typeorm'\n\nimport { slugger } from '@things-factory/utils'\n\nimport { getRepository } from '../../initializers/database'\nimport { getQueryBuilderFromListParams } from '../../utils/get-query-builder-from-list-params'\n\nimport { ListParam } from '../common-types/list-param'\nimport { Domain } from './domain'\nimport { DomainList, DomainPatch } from './domain-types'\n\n@Resolver(Domain)\nexport class DomainResolver {\n @Directive('@privilege(category: \"system\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => Domain, { description: 'To fetch domain' })\n async domain(@Arg('id') id: string, @Ctx() context: any): Promise<Domain> {\n const repository = getRepository(Domain)\n\n return await repository.findOneBy({ id })\n }\n\n @Directive('@privilege(superUserGranted: true)')\n @Query(returns => DomainList, { description: 'To fetch all domains (Only superuser is granted this privilege.)' })\n async domains(@Args() params: ListParam, @Ctx() context: any): Promise<DomainList> {\n const queryBuilder = await getQueryBuilderFromListParams({\n repository: getRepository(Domain),\n alias: 'ContactPoint',\n params,\n searchables: ['name', 'description', 'subdomain']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n // @Query(returns => Boolean, { description: 'To check if given domain is exist' })\n // async checkExistsDomain(@Arg('name') name: string) {\n // const domainRepository: Repository<Domain> = getRepository(Domain)\n // const targetSubdomain: string = slugger(name)\n\n // const oldDomain = await domainRepository.findOneBy({ subdomain: targetSubdomain })\n // if (oldDomain) {\n // throw new Error('domain is duplicated')\n // }\n\n // return true\n // }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => Domain, { description: 'To create domain (Only superuser is granted this privilege.)' })\n async createDomain(@Arg('domainInput') domainInput: DomainPatch) {\n const { name, description } = domainInput\n const domainRepo: Repository<Domain> = getRepository(Domain)\n const subdomain: string = slugger(name)\n\n const domain: Domain = await domainRepo.findOneBy({ subdomain })\n if (domain) {\n throw new Error('domain is duplicated')\n }\n\n return await domainRepo.save({ name, description, subdomain })\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => Domain, { description: 'To delete domain (Only superuser is granted this privilege.)' })\n async deleteDomain(@Arg('name') name: string) {\n return await getRepository(Domain).delete({ name })\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => Boolean, {\n description: 'To delete multiple domains (Only superuser is granted this privilege.)'\n })\n async deleteDomains(@Arg('names', () => [String]) names: string[]) {\n const domains: Domain[] = await getRepository(Domain).find({ where: { name: In(names) } })\n const domainIds: string[] = domains.map(domain => domain.id)\n\n await getRepository(Domain).delete({ id: In(domainIds) })\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => Domain, {\n description: 'To update domain (Only superuser is granted this privilege.)'\n })\n async updateDomain(@Arg('name') name: string, @Arg('patch', () => DomainPatch) patch: DomainPatch) {\n const repository = getRepository(Domain)\n const domain: Domain = await repository.findOneBy({ name })\n\n if (patch.parent && patch.parent.id == domain.id) {\n delete patch.parent\n }\n\n return await repository.save({\n ...domain,\n ...patch\n } as any)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(superUserGranted: true)')\n @Mutation(returns => Boolean, {\n description: 'To update multiple domains (Only superuser is granted this privilege.)'\n })\n async updateDomains(@Arg('patches', () => [DomainPatch]) patches: DomainPatch[]): Promise<boolean> {\n const domainRepo: Repository<Domain> = getRepository(Domain)\n\n const patchIds = patches.filter((patch: any) => patch.id)\n\n if (patchIds.length > 0) {\n patchIds.forEach(async updateRecord => {\n const domain: Domain = await domainRepo.findOne({ where: { id: updateRecord.id } })\n\n if (updateRecord.name) {\n updateRecord.subdomain = slugger(updateRecord.name)\n }\n\n if (updateRecord.parent && updateRecord.parent.id == domain.id) {\n delete updateRecord.parent\n }\n\n await domainRepo.save({\n ...domain,\n ...updateRecord\n } as any)\n })\n }\n\n return true\n }\n\n @FieldResolver(type => Domain)\n async parent(@Root() domain: Domain): Promise<Domain> {\n return domain.parentId && (await getRepository(Domain).findOneBy({ id: domain.parentId }))\n }\n}\n"]}