@things-factory/integration-base 6.2.15 → 6.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/integration-base",
3
- "version": "6.2.15",
3
+ "version": "6.2.24",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -26,12 +26,12 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@apollo/client": "^3.6.9",
29
- "@things-factory/api": "^6.2.15",
30
- "@things-factory/auth-base": "^6.2.15",
29
+ "@things-factory/api": "^6.2.24",
30
+ "@things-factory/auth-base": "^6.2.24",
31
31
  "@things-factory/env": "^6.2.0",
32
- "@things-factory/oauth2-client": "^6.2.15",
33
- "@things-factory/scheduler-client": "^6.2.15",
34
- "@things-factory/shell": "^6.2.15",
32
+ "@things-factory/oauth2-client": "^6.2.24",
33
+ "@things-factory/scheduler-client": "^6.2.24",
34
+ "@things-factory/shell": "^6.2.24",
35
35
  "async-mqtt": "^2.5.0",
36
36
  "chance": "^1.1.11",
37
37
  "cross-fetch": "^3.0.4",
@@ -46,5 +46,5 @@
46
46
  "devDependencies": {
47
47
  "@types/cron": "^2.0.1"
48
48
  },
49
- "gitHead": "262fa72c069ac8745dd16acd695d0e87331fbc14"
49
+ "gitHead": "f407983563cca529ba87ea8febb5be751ad3229e"
50
50
  }
@@ -11,50 +11,65 @@ import {
11
11
  UpdateDateColumn
12
12
  } from 'typeorm'
13
13
 
14
- import { User } from '@things-factory/auth-base'
14
+ import { Privilege, User } from '@things-factory/auth-base'
15
15
  import { Domain } from '@things-factory/shell'
16
16
 
17
17
  import { ScenarioEngine } from '../../engine'
18
18
  import { Step, StepPatch } from '../step/step-type'
19
19
 
20
+ @ObjectType()
21
+ export class PrivilegeObject {
22
+ @Field({ nullable: true })
23
+ privilege?: string
24
+
25
+ @Field({ nullable: true })
26
+ category?: string
27
+
28
+ @Field({ nullable: true })
29
+ owner?: boolean
30
+
31
+ @Field({ nullable: true })
32
+ super?: boolean
33
+ }
34
+
20
35
  @Entity()
21
36
  @Index('ix_scenario_0', (scenario: Scenario) => [scenario.domain, scenario.name], { unique: true })
22
37
  @ObjectType()
23
38
  export class Scenario {
24
39
  @PrimaryGeneratedColumn('uuid')
25
40
  @Field(type => ID)
26
- id: string
41
+ id?: string
27
42
 
28
43
  @ManyToOne(type => Domain)
29
44
  @Field({ nullable: true })
30
- domain: Domain
45
+ domain?: Domain
31
46
 
32
47
  @RelationId((scenario: Scenario) => scenario.domain)
33
- domainId: string
48
+ domainId?: string
34
49
 
35
50
  @Column()
36
51
  @Field()
37
- name: string
52
+ name?: string
38
53
 
39
54
  @Column({ nullable: true })
40
55
  @Field({ nullable: true })
41
- description: string
56
+ description?: string
42
57
 
43
58
  @Column({ nullable: true })
44
59
  @Field({ nullable: true })
45
- type: string
60
+ type?: string
46
61
 
47
62
  @Column({ nullable: true })
48
63
  @Field({ nullable: true, description: 'accessible and executable system-wide' })
49
- public: boolean
64
+ public?: boolean
50
65
 
51
66
  @Column({ nullable: true })
52
67
  @Field({ nullable: true, description: '[will be deprecated] automatically be started when this server start' })
53
- active: boolean
68
+ active?: boolean
54
69
 
55
70
  @Column({ nullable: true })
56
71
  @Field({ nullable: true })
57
- schedule: string
72
+ schedule?: string
58
73
 
59
74
  @Column({ nullable: true })
60
75
  @Field({ nullable: true })
@@ -62,33 +77,37 @@ export class Scenario {
62
77
 
63
78
  @Column({ nullable: true })
64
79
  @Field({ nullable: true })
65
- timezone: string
80
+ timezone?: string
66
81
 
67
82
  @OneToMany(type => Step, step => step.scenario)
68
83
  @Field(type => [Step], { nullable: true })
69
- steps: Step[]
84
+ steps?: Step[]
85
+
86
+ @Column({ type: 'simple-json', nullable: true })
87
+ @Field(type => PrivilegeObject, { nullable: true })
88
+ privilege?: PrivilegeObject
70
89
 
71
90
  @CreateDateColumn()
72
91
  @Field({ nullable: true })
73
- createdAt: Date
92
+ createdAt?: Date
74
93
 
75
94
  @UpdateDateColumn()
76
95
  @Field({ nullable: true })
77
- updatedAt: Date
96
+ updatedAt?: Date
78
97
 
79
98
  @ManyToOne(type => User, { nullable: true })
80
99
  @Field({ nullable: true })
81
- creator: User
100
+ creator?: User
82
101
 
83
102
  @RelationId((scenario: Scenario) => scenario.creator)
84
- creatorId: string
103
+ creatorId?: string
85
104
 
86
105
  @ManyToOne(type => User, { nullable: true })
87
106
  @Field({ nullable: true })
88
- updater: User
107
+ updater?: User
89
108
 
90
109
  @RelationId((scenario: Scenario) => scenario.updater)
91
- updaterId: string
110
+ updaterId?: string
92
111
 
93
112
  async start(instanceName, variables?: any) {
94
113
  try {
@@ -104,6 +123,21 @@ export class Scenario {
104
123
  }
105
124
  }
106
125
 
126
+ @InputType()
127
+ export class PrivilegeInput {
128
+ @Field({ nullable: true })
129
+ privilege?: string
130
+
131
+ @Field({ nullable: true })
132
+ category?: string
133
+
134
+ @Field({ nullable: true })
135
+ owner?: boolean
136
+
137
+ @Field({ nullable: true })
138
+ super?: boolean
139
+ }
140
+
107
141
  @InputType()
108
142
  export class NewScenario {
109
143
  @Field()
@@ -123,6 +157,9 @@ export class NewScenario {
123
157
 
124
158
  @Field({ nullable: true })
125
159
  active?: boolean
160
+
161
+ @Field({ nullable: true })
162
+ privilege?: PrivilegeInput
126
163
  }
127
164
 
128
165
  @InputType()
@@ -151,6 +188,9 @@ export class ScenarioPatch {
151
188
  @Field(type => [StepPatch], { nullable: true })
152
189
  steps?: StepPatch[]
153
190
 
191
+ @Field({ nullable: true })
192
+ privilege?: PrivilegeInput
193
+
154
194
  @Field({ nullable: true })
155
195
  cuFlag?: string
156
196
  }
@@ -3,12 +3,17 @@ import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'
3
3
  import { getRepository, Domain, GraphqlLocalClient, ScalarObject } from '@things-factory/shell'
4
4
 
5
5
  import { ScenarioEngine } from '../../engine'
6
- import { Scenario } from '../scenario/scenario-type'
6
+ import { PrivilegeObject, Scenario } from '../scenario/scenario-type'
7
7
  import { ScenarioInstance } from './scenario-instance-type'
8
+ import { User } from '@things-factory/auth-base'
9
+ import { Step } from '../step/step-type'
8
10
 
9
11
  const debug = require('debug')('things-factory:integration-base:scenario-instance-mutation')
10
12
 
11
- async function findScenario(scenarioName: string, domain: Domain) {
13
+ async function findScenario(
14
+ scenarioName: string,
15
+ domain: Domain
16
+ ): Promise<{ name: string; steps: Step[]; domain: Domain; privilege?: PrivilegeObject }> {
12
17
  var repository = getRepository(Scenario)
13
18
 
14
19
  var scenario = await repository.findOne({
@@ -23,7 +28,21 @@ async function findScenario(scenarioName: string, domain: Domain) {
23
28
  })
24
29
  }
25
30
 
26
- return scenario
31
+ return scenario as any
32
+ }
33
+
34
+ async function checkPermission(privilegeObject: PrivilegeObject, user: User, domain: Domain): Promise<boolean> {
35
+ if (!privilegeObject || !privilegeObject.privilege || !privilegeObject.category) {
36
+ return true
37
+ }
38
+
39
+ const { owner: domainOwnerGranted, super: superUserGranted, category, privilege } = privilegeObject
40
+
41
+ return (
42
+ (domainOwnerGranted && (await process.domainOwnerGranted(domain, user))) ||
43
+ (superUserGranted && (await process.superUserGranted(domain, user))) ||
44
+ (category && privilege && (await User.hasPrivilege(privilege, category, domain, user)))
45
+ )
27
46
  }
28
47
 
29
48
  @Resolver(ScenarioInstance)
@@ -37,7 +56,7 @@ export class ScenarioInstanceMutation {
37
56
  @Arg('variables', type => ScalarObject, { nullable: true }) variables: any,
38
57
  @Ctx() context: ResolverContext
39
58
  ): Promise<ScenarioInstance> {
40
- const { domain } = context.state
59
+ const { domain, user } = context.state
41
60
 
42
61
  debug('runScenario', scenarioName, instanceName, variables)
43
62
 
@@ -51,6 +70,10 @@ export class ScenarioInstanceMutation {
51
70
  )
52
71
  }
53
72
 
73
+ if (!(await checkPermission(scenario.privilege, user, domain))) {
74
+ throw new Error(`Unauthorized!`)
75
+ }
76
+
54
77
  /* 시나리오 인스턴스를 생성한다. */
55
78
  instanceName = instanceName || scenarioName + '-' + String(Date.now())
56
79
  var instance = new ScenarioInstance(instanceName, scenario, {
@@ -85,6 +108,10 @@ export class ScenarioInstanceMutation {
85
108
  )
86
109
  }
87
110
 
111
+ if (!(await checkPermission(scenario.privilege, user, domain))) {
112
+ throw new Error(`Unauthorized!`)
113
+ }
114
+
88
115
  instanceName = instanceName || scenarioName
89
116
  return await ScenarioEngine.load(instanceName, scenario, { domain, user, lng, variables })
90
117
  }
@@ -94,7 +121,7 @@ export class ScenarioInstanceMutation {
94
121
  @Arg('instanceName', { nullable: true }) instanceName: string,
95
122
  @Ctx() context: ResolverContext
96
123
  ): Promise<ScenarioInstance | undefined> {
97
- const { domain } = context.state
124
+ const { domain, user } = context.state
98
125
 
99
126
  debug('stopScenario', instanceName)
100
127
 
@@ -107,7 +134,12 @@ export class ScenarioInstanceMutation {
107
134
  instance: instanceName
108
135
  })
109
136
  )
110
- return
137
+ }
138
+
139
+ var scenario = await findScenario(scenarioInstance.scenarioName, domain)
140
+
141
+ if (!(await checkPermission(scenario.privilege, user, domain))) {
142
+ throw new Error(`Unauthorized!`)
111
143
  }
112
144
 
113
145
  await ScenarioEngine.unload(domain, instanceName)
@@ -1,6 +1,6 @@
1
1
  {
2
- "error.scenario not found": "[ms] scenario '{scenario}' not found.",
3
- "error.schedule is not set": "schedule should be set for the scenario '{scenario}' in order to register as a schedule",
4
- "error.timezone is not set": "timezone should be set for the scenario '{scenario}' in order to register as a schedule",
5
- "error.scenario instance not found": "[ms] scenario instance '{instance}' not found."
2
+ "error.scenario not found": "Tidak dapat mencari senario '{scenario}'.",
3
+ "error.schedule is not set": "Untuk mendaftarkan sebagai jadual, maklumat jadual mesti diset dalam senario '{scenario}'.",
4
+ "error.timezone is not set": "Untuk mendaftarkan sebagai jadual, maklumat zon masa mesti diset dalam senario '{scenario}'.",
5
+ "error.scenario instance not found": "Tidak dapat mencari instans senario '{instance}'. Mungkin telah berakhir."
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
- "error.scenario not found": "未找到场景'{scenario}'",
3
- "error.schedule is not set": "schedule should be set for the scenario '{scenario}' in order to register as a schedule",
4
- "error.timezone is not set": "timezone should be set for the scenario '{scenario}' in order to register as a schedule",
5
- "error.scenario instance not found": "[zh] scenario instance '{instance}' not found."
2
+ "error.scenario not found": "无法找到场景 '{scenario}'",
3
+ "error.schedule is not set": "要注册为计划,场景 '{scenario}' 需要设置计划信息。",
4
+ "error.timezone is not set": "要注册为计划,场景 '{scenario}' 需要设置时区信息。",
5
+ "error.scenario instance not found": "无法找到场景实例 '{instance}'。它可能已经结束。"
6
6
  }