@simitgroup/simpleapp-generator 1.0.31 → 1.0.32

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.
@@ -1,67 +1,67 @@
1
- import { Injectable } from '@nestjs/common';
1
+ import { Injectable, Logger } from '@nestjs/common';
2
2
  import { InjectModel } from '@nestjs/mongoose';
3
3
  import { Model } from 'mongoose';
4
4
  import Ajv from 'ajv';
5
5
  import addFormats from 'ajv-formats';
6
6
  import addErrors from 'ajv-errors';
7
7
  import foreignkeys from '../dicts/foreignkeys.json';
8
-
8
+ import { Workflow } from './Workflow';
9
9
  import {
10
10
  NotFoundException,
11
11
  InternalServerErrorException,
12
12
  } from '@nestjs/common/exceptions';
13
- import { User } from './User';
13
+ import { UserProvider } from './UserProvider';
14
14
 
15
15
  export enum IsolationType {
16
+ 'none' = 'none',
16
17
  'org' = 'org',
17
18
  'tenant' = 'tenant',
18
19
  'branch' = 'branch',
19
20
  }
20
21
  export enum HookType {
21
- 'init'='init',
22
- 'beforeSearch'='beforeSearch',
23
- 'afterSearch'='afterSearch',
24
- 'beforeValidation'='beforeValidation',
25
- 'afterValidation'='afterValidation',
26
- 'beforeCreate'='beforeCreate',
27
- 'afterCreate'='afterCreate',
28
- 'beforeUpdate'='beforeUpdate',
29
- 'afterUpdate'='afterUpdate',
30
- 'beforeDelete'='beforeDelete',
31
- 'afterDelete'='afterDelete',
32
- 'beforeFetchRecord'='beforeFetchRecord',
33
- 'afterFetchRecord'='afterFetchRecord',
34
-
35
-
22
+ 'init' = 'init',
23
+ 'beforeSearch' = 'beforeSearch',
24
+ 'afterSearch' = 'afterSearch',
25
+ 'beforeValidation' = 'beforeValidation',
26
+ 'afterValidation' = 'afterValidation',
27
+ 'beforeCreate' = 'beforeCreate',
28
+ 'afterCreate' = 'afterCreate',
29
+ 'beforeUpdate' = 'beforeUpdate',
30
+ 'afterUpdate' = 'afterUpdate',
31
+ 'beforeDelete' = 'beforeDelete',
32
+ 'afterDelete' = 'afterDelete',
33
+ 'beforeFetchRecord' = 'beforeFetchRecord',
34
+ 'afterFetchRecord' = 'afterFetchRecord',
36
35
  }
37
36
  export type MoreProjectionType = {
38
- [key:string]:string
39
- }
37
+ [key: string]: string;
38
+ };
40
39
  @Injectable()
41
40
  export class SimpleAppService<T extends { _id?: string }> {
41
+ protected logger = new Logger();
42
42
  protected jsonschema = { type: 'object', properties: {}, required: [] };
43
43
  protected documentIdentityCode = 'code';
44
44
  protected documentIdentityName = 'label';
45
45
  protected documentName = '-unknowndocname-';
46
46
  protected documentType = '-unknowndoctype-';
47
47
  protected LIMITPERPAGE = 20;
48
- protected moreAutoCompleteField:MoreProjectionType={}
48
+ protected moreAutoCompleteField: MoreProjectionType = {};
49
49
  protected isolationtype: IsolationType = IsolationType.org;
50
50
  protected isolationFilter: any = {};
51
51
  protected data: T = { _id: '' } as T;
52
52
  private doc: Model<T>; //set private to prevent developer break data isolation control
53
53
  protected errorlist = [];
54
54
  constructor(
55
- doctype:string,
56
- docname:string,
55
+ doctype: string,
56
+ docname: string,
57
57
  newdoc: Model<T>,
58
58
  isolationtype: IsolationType = IsolationType.org,
59
59
  ) {
60
- this.documentType=doctype
61
- this.documentName=docname
60
+ this.documentType = doctype;
61
+ this.documentName = docname;
62
62
  this.doc = newdoc;
63
63
  this.isolationtype = isolationtype;
64
- this.hook(HookType.init,this.documentName)
64
+ this.hook(HookType.init, this.documentName);
65
65
  // this.tenantdoc = tenantdoc
66
66
  }
67
67
  getRecordId = (): string => this.data._id;
@@ -79,15 +79,18 @@ export class SimpleAppService<T extends { _id?: string }> {
79
79
  getIsolationFilter = () => {
80
80
  let isolationFilter = {};
81
81
  switch (this.isolationtype) {
82
+ case 'none':
83
+ isolationFilter = {};
84
+ break;
82
85
  case 'branch':
83
- isolationFilter = User.getInstance().getBranchFilter();
86
+ isolationFilter = UserProvider.getInstance().getBranchFilter();
84
87
  break;
85
88
  case 'tenant':
86
- isolationFilter = User.getInstance().getTenantFilter();
89
+ isolationFilter = UserProvider.getInstance().getTenantFilter();
87
90
  break;
88
91
  case 'org':
89
92
  default:
90
- isolationFilter = User.getInstance().getOrgFilter();
93
+ isolationFilter = UserProvider.getInstance().getOrgFilter();
91
94
  break;
92
95
  }
93
96
  return isolationFilter;
@@ -106,21 +109,21 @@ export class SimpleAppService<T extends { _id?: string }> {
106
109
  throw new InternalServerErrorException(err.message);
107
110
  }
108
111
  }
109
- addAutoCompleteField = (morefield:MoreProjectionType)=>{
110
- const props = Object.getOwnPropertyNames(morefield)
111
- console.log('addAutoCompleteField',props)
112
- for(let i=0;i<props.length;i++){
113
- const key = props[i]
114
- this.moreAutoCompleteField[key] = '$'+morefield[key]
112
+ addAutoCompleteField = (morefield: MoreProjectionType) => {
113
+ const props = Object.getOwnPropertyNames(morefield);
114
+ console.log('addAutoCompleteField', props);
115
+ for (let i = 0; i < props.length; i++) {
116
+ const key = props[i];
117
+ this.moreAutoCompleteField[key] = '$' + morefield[key];
115
118
  }
116
- console.log(this.moreAutoCompleteField)
117
- }
119
+ console.log(this.moreAutoCompleteField);
120
+ };
118
121
  async getAutoComplete(keyword: string) {
119
122
  try {
120
123
  const filter1 = {};
121
124
  const filter2 = {};
122
- filter1[this.documentIdentityCode] = { $regex: keyword,$options:'i' };
123
- filter2[this.documentIdentityName] = { $regex: keyword,$options:'i' };
125
+ filter1[this.documentIdentityCode] = { $regex: keyword, $options: 'i' };
126
+ filter2[this.documentIdentityName] = { $regex: keyword, $options: 'i' };
124
127
  const filterobj = { $or: [filter1, filter2] };
125
128
 
126
129
  Object.assign(filterobj, this.getIsolationFilter());
@@ -129,8 +132,8 @@ export class SimpleAppService<T extends { _id?: string }> {
129
132
  label: `\$${this.documentIdentityCode}`,
130
133
  name: `\$${this.documentIdentityName}`,
131
134
  };
132
- if(this.moreAutoCompleteField){
133
- Object.assign(projections,this.moreAutoCompleteField)
135
+ if (this.moreAutoCompleteField) {
136
+ Object.assign(projections, this.moreAutoCompleteField);
134
137
  }
135
138
  const products = await this.doc.find(filterobj, projections, {
136
139
  limit: this.LIMITPERPAGE,
@@ -145,14 +148,13 @@ export class SimpleAppService<T extends { _id?: string }> {
145
148
  }
146
149
  async search(filters: Object) {
147
150
  try {
148
-
149
151
  Object.assign(filters, this.getIsolationFilter());
150
- await this.hook(HookType.beforeSearch,filters)
152
+ await this.hook(HookType.beforeSearch, filters);
151
153
  const products = await this.doc.find(filters);
152
154
  const productlist = products.map((p: T) => {
153
155
  return p;
154
156
  });
155
- await this.hook(HookType.afterSearch,productlist)
157
+ await this.hook(HookType.afterSearch, productlist);
156
158
  // console.log(products);
157
159
  return productlist;
158
160
  } catch (err) {
@@ -161,9 +163,9 @@ export class SimpleAppService<T extends { _id?: string }> {
161
163
  // return this;
162
164
  }
163
165
  async findById(id: string) {
164
- await this.hook(HookType.beforeFetchRecord,id)
166
+ await this.hook(HookType.beforeFetchRecord, id);
165
167
  const data = await this.search({ _id: id });
166
- await this.hook(HookType.afterFetchRecord,data)
168
+ await this.hook(HookType.afterFetchRecord, data);
167
169
  if (data.length == 1) {
168
170
  // console.log('data0', data[0]);
169
171
  return data[0];
@@ -176,13 +178,13 @@ export class SimpleAppService<T extends { _id?: string }> {
176
178
  let result;
177
179
 
178
180
  try {
179
- await this.hook(HookType.beforeCreate,this.data)
180
- Object.assign(this.data, User.getInstance().getCreateFilter());
181
+ await this.hook(HookType.beforeCreate, this.data);
182
+ Object.assign(this.data, UserProvider.getInstance().getCreateFilter());
181
183
  delete this.data._id;
182
184
  await this.validateData(this.data);
183
185
  const newdoc = new this.doc(this.data);
184
186
  result = await newdoc.save();
185
- await this.hook(HookType.afterCreate,result)
187
+ await this.hook(HookType.afterCreate, result);
186
188
  } catch (err) {
187
189
  throw new InternalServerErrorException(err.message);
188
190
  }
@@ -190,7 +192,7 @@ export class SimpleAppService<T extends { _id?: string }> {
190
192
  }
191
193
  async update() {
192
194
  const id: string = this.getRecordId();
193
- Object.assign(this.data, User.getInstance().getUpdateFilter());
195
+ Object.assign(this.data, UserProvider.getInstance().getUpdateFilter());
194
196
  await this.findIdThenUpdate(id, this.data);
195
197
  }
196
198
  async delete() {
@@ -202,44 +204,56 @@ export class SimpleAppService<T extends { _id?: string }> {
202
204
  return dependency;
203
205
  }
204
206
  }
205
- hook = async (type: string, data?: any) =>{
206
- console.log("Default hook",data)
207
+ hook = async (type: string, data?: any) => {
208
+ // console.log('Default hook', data);
207
209
  return true;
208
- }
210
+ };
209
211
  async validateData(data: T) {
210
212
  const ajv = new Ajv({ allErrors: true });
211
213
  addFormats(ajv);
212
214
  addErrors(ajv);
213
215
 
214
216
  ajv.addFormat('x-document-no', /.*$/);
215
- ajv.addFormat('x-document-name', /.*$/);
216
- ajv.addFormat('x-text', /.*$/);
217
+ ajv.addFormat('x-document-label', /.*$/);
217
218
  ajv.addFormat('tel', /^$|^\d{7,15}$/gm);
219
+ ajv.addFormat('x-text', /.*$/);
218
220
  ajv.addFormat('x-html', /.*$/);
219
- ajv.addKeyword({
220
- keyword: 'x-foreignkey',
221
- type: 'string',
222
- });
223
221
 
224
- const issuccess = await this.hook(HookType.beforeValidation, data)
222
+ ajv.addKeyword({ keyword: 'x-document-status', type: 'array' });
223
+ ajv.addKeyword({ keyword: 'x-document-api', type: 'array' });
224
+ ajv.addKeyword({ keyword: 'x-ignore-autocomplete', type: 'boolean' });
225
+ ajv.addKeyword({ keyword: 'x-isolation-type', type: 'string' });
226
+ ajv.addKeyword({ keyword: 'x-document-type', type: 'string' });
227
+ ajv.addKeyword({ keyword: 'x-document-name', type: 'string' });
228
+ ajv.addKeyword({ keyword: 'x-collection-name', type: 'string' });
229
+ ajv.addKeyword({ keyword: 'x-autocomplete-field', type: 'boolean' });
230
+ ajv.addKeyword({ keyword: 'x-foreignkey', type: 'string' });
231
+
232
+ const issuccess = await this.hook(HookType.beforeValidation, data);
225
233
  if (!issuccess) {
226
234
  const erromsg: string[] = [];
227
235
  for (let i = 0; i < this.errorlist.length; i++) {
228
236
  erromsg.push(this.errorlist[i].message);
229
237
  }
230
-
238
+ this.logger.log('run hook during validation');
231
239
  throw new InternalServerErrorException(erromsg.join('\n'));
232
240
  }
233
- const validate = ajv.compile(this.jsonschema);
241
+
242
+ let validate;
243
+ try {
244
+ validate = ajv.compile(this.jsonschema);
245
+ } catch (err) {
246
+ this.logger.error('compile error', err);
247
+ }
248
+
234
249
  const valid = validate(data);
235
- //console.log(validate.errors);
236
250
  if (!valid) {
237
- // console.log(validate.errors);
251
+ this.logger.error(validate.errors);
238
252
  const erromsg: string[] = [];
239
253
  for (let i = 0; i < ajv.errors.length; i++) {
240
254
  erromsg.push(ajv.errors[i].message);
241
255
  }
242
- console.log('ajv erromsg: ', erromsg);
256
+ this.logger.error('ajv erromsg: ', erromsg);
243
257
  throw new InternalServerErrorException(erromsg.join('\n'));
244
258
  }
245
259
  await this.hook(HookType.afterValidation, data);
@@ -248,7 +262,7 @@ export class SimpleAppService<T extends { _id?: string }> {
248
262
  async findIdThenDelete(id: string): Promise<any> {
249
263
  // const data = await this.findById(id);
250
264
  try {
251
- await this.hook(HookType.beforeDelete,id)
265
+ await this.hook(HookType.beforeDelete, id);
252
266
  //console.log('deletedeletedeletedelete');
253
267
  const dependency = await this.getRelatedRecords(id);
254
268
  if (!dependency) {
@@ -256,7 +270,7 @@ export class SimpleAppService<T extends { _id?: string }> {
256
270
  filter['_id'] = id;
257
271
  const deleteresult = await this.doc.deleteOne(filter);
258
272
  // this.doc.findByIdAndDelete(id)
259
- await this.hook(HookType.afterDelete,deleteresult)
273
+ await this.hook(HookType.afterDelete, deleteresult);
260
274
  //this.doc.findByIdAndDelete(id);
261
275
  return deleteresult;
262
276
  } else {
@@ -273,15 +287,15 @@ export class SimpleAppService<T extends { _id?: string }> {
273
287
 
274
288
  findIdThenUpdate = async (id: string, data: T) => {
275
289
  const existingdata = await this.findById(id);
276
- await this.hook(HookType.beforeUpdate,data)
290
+ await this.hook(HookType.beforeUpdate, data);
277
291
  try {
278
- Object.assign(data, User.getInstance().getUpdateFilter());
292
+ Object.assign(data, UserProvider.getInstance().getUpdateFilter());
279
293
  Object.assign(existingdata, data);
280
294
  await this.validateData(data);
281
295
  let filter = this.getIsolationFilter();
282
296
  filter['_id'] = id;
283
297
  const result = await this.doc.findOneAndUpdate(filter, data);
284
- await this.hook(HookType.afterUpdate,data)
298
+ await this.hook(HookType.afterUpdate, data);
285
299
  return result;
286
300
  } catch (err) {
287
301
  throw new InternalServerErrorException(err.message);
@@ -317,4 +331,36 @@ export class SimpleAppService<T extends { _id?: string }> {
317
331
  }
318
332
  return Promise.resolve(null);
319
333
  }
334
+
335
+ /**
336
+ * change property documentStatus for specific document, no workflow execution
337
+ * @param id
338
+ * @param docstatus
339
+ * @returns Promise
340
+ */
341
+ async setDocumentStatus(id: string, docstatus: string) {
342
+ const partialdata: T = {} as T;
343
+ partialdata['documentStatus'] = docstatus;
344
+ return this.findIdThenUpdate(id, partialdata);
345
+ }
346
+
347
+ /**
348
+ * change property documentStatus for specific document, no workflow execution
349
+ * @param id
350
+ * @param docstatus
351
+ * @returns Promise
352
+ */
353
+ async executeWorkFlow(id: string, bpmnname: string, docstatus: string) {
354
+ const data = await this.findById(id);
355
+ return Workflow.getInstance().executeWorkFlow(
356
+ id,
357
+ bpmnname,
358
+ docstatus,
359
+ data,
360
+ );
361
+ }
362
+
363
+ async getMyUserTask() {
364
+ return Workflow.getInstance().getMyUserTask();
365
+ }
320
366
  }
@@ -2,38 +2,33 @@ import { Injectable, NestMiddleware, Scope } from '@nestjs/common';
2
2
  import { Request, Response, NextFunction } from 'express';
3
3
  // import * as jwt from 'nestjs-jwt'
4
4
 
5
-
6
- import { User } from './User';
5
+ import { UserProvider } from './UserProvider';
7
6
  // import {KeycloakConfigService} from "../keycloak/keycloak.service"
8
7
  @Injectable({
9
8
  scope: Scope.REQUEST,
10
9
  })
11
-
12
10
  export class TenantMiddleware implements NestMiddleware {
13
11
  use(req: Request, res: Response, next: NextFunction) {
14
12
  if (req.baseUrl == '/oauth2-redirect.html') {
15
13
  next();
16
- return ;
14
+ return;
17
15
  }
18
- if(!req.headers['authorization']){
16
+ if (!req.headers['authorization']) {
19
17
  return res.status(401).send('Undefine bearer token');
20
18
  }
21
- if (!req.headers['x-org']){
19
+ if (!req.headers['x-org']) {
22
20
  return res.status(401).send('undefine header string x-org');
23
21
  }
24
- const u = User.getInstance();
22
+ const u = UserProvider.getInstance();
25
23
 
26
24
  try {
27
25
  u.setXorg(req.headers['x-org'].toString());
28
- let tokenstr:string = req.headers['authorization']
29
- tokenstr = tokenstr.replace("Bearer ",'')
30
- u.setUserToken(tokenstr);
26
+ let tokenstr: string = req.headers['authorization'];
27
+ tokenstr = tokenstr.replace('Bearer ', '');
28
+ u.setUserToken(tokenstr);
31
29
  next();
32
30
  } catch {
33
31
  return res.status(401).send('Invalid x-org or user info');
34
32
  }
35
-
36
-
37
-
38
33
  }
39
34
  }
@@ -0,0 +1,127 @@
1
+ import { Injectable, Scope } from '@nestjs/common';
2
+ import Base64URL from '@darkwolf/base64url';
3
+ import * as jwt from 'jsonwebtoken';
4
+
5
+ @Injectable({
6
+ scope: Scope.REQUEST,
7
+ })
8
+ export class UserProvider {
9
+ private static instance: UserProvider;
10
+ protected uid: string = '';
11
+ protected uname: string = '';
12
+ protected email: string = '';
13
+ protected fullname: string = '';
14
+ protected xOrg: string = '';
15
+ protected tenantId: number = 0;
16
+ protected orgId: number = 0;
17
+ protected branchId: number = 0;
18
+ protected accessrights: any = {};
19
+ protected token: string = '';
20
+ protected refreshtoken: string = '';
21
+ protected groups: string[] = [];
22
+ constructor() {}
23
+ public static getInstance(): UserProvider {
24
+ if (!UserProvider.instance) {
25
+ UserProvider.instance = new UserProvider();
26
+ }
27
+ return UserProvider.instance;
28
+ }
29
+ getUid = () => this.uid;
30
+ getUname = () => this.uname;
31
+ getFullname = () => this.fullname;
32
+ getTenantId = () => this.tenantId;
33
+ getOrgId = () => this.orgId;
34
+ getBranchId = () => this.branchId;
35
+ getEmail = () => this.email;
36
+ getGroups = () => this.groups;
37
+ setUserToken = (tokenstr: string) => {
38
+ const tokeninfo = jwt.decode(tokenstr);
39
+ // realm_access: {
40
+ // roles: [
41
+ // 'default-roles-simitdeveloper',
42
+ // 'offline_access',
43
+ // 'uma_authorization'
44
+ // ]
45
+ // },
46
+ // resource_access: { account: { roles: [Array] } },
47
+ // scope: 'openid email profile',
48
+ // sid: '53192f53-d4af-413b-b8d7-1e186419fe53',
49
+ // email_verified: false,
50
+ // name: 'kstan kstan',
51
+ // preferred_username: 'kstan',
52
+ // given_name: 'kstan',
53
+ // family_name: 'kstan',
54
+ // email: 'kstan@simitgroup.com'
55
+
56
+ const u = UserProvider.getInstance();
57
+ u.token = tokenstr;
58
+ u.uid = tokeninfo.sub;
59
+ u.email = tokeninfo.email;
60
+ u.uname = tokeninfo.preferred_username;
61
+ u.fullname = tokeninfo.name;
62
+ u.groups = ['superuser', 'accountant', 'directors'];
63
+ u.accessrights = tokeninfo.resource_access;
64
+ };
65
+ getInfo = () => {
66
+ return UserProvider.getInstance();
67
+ };
68
+ getBranchFilter = () => {
69
+ return {
70
+ tenantId: UserProvider.getInstance().tenantId,
71
+ orgId: UserProvider.getInstance().orgId,
72
+ branchId: UserProvider.getInstance().branchId,
73
+ };
74
+ };
75
+ getTenantFilter = () => {
76
+ return { tenantId: UserProvider.getInstance().tenantId };
77
+ };
78
+ getOrgFilter = () => {
79
+ return {
80
+ tenantId: UserProvider.getInstance().tenantId,
81
+ orgId: UserProvider.getInstance().orgId,
82
+ };
83
+ };
84
+ getWorkflowTaskFilter() {
85
+ return {
86
+ 'data.tenantId': UserProvider.getInstance().tenantId,
87
+ 'assignments.assignee': UserProvider.getInstance().getUid(),
88
+ // 'assignments.assignee': User.getInstance().getUid(),
89
+ };
90
+ }
91
+ getCreateFilter = () => {
92
+ const u = UserProvider.getInstance();
93
+ return {
94
+ tenantId: u.tenantId,
95
+ orgId: u.orgId,
96
+ branchId: u.branchId,
97
+ createdby: u.uid,
98
+ updatedby: u.uid,
99
+ created: new Date().getTime().toString(),
100
+ updated: new Date().getTime().toString(),
101
+ };
102
+ };
103
+ getUpdateFilter = () => {
104
+ const u = UserProvider.getInstance();
105
+ return {
106
+ updatedby: u.uid,
107
+ updated: new Date().getTime().toString(),
108
+ };
109
+ };
110
+ setXorg = (xorg) => {
111
+ try {
112
+ const decodedText: string = Base64URL.decodeText(xorg);
113
+ const arrXorg = decodedText.split('-');
114
+
115
+ if (arrXorg.length == 3) {
116
+ const u = UserProvider.getInstance();
117
+ u.tenantId = Number(arrXorg[0]);
118
+ u.orgId = Number(arrXorg[1]);
119
+ u.branchId = Number(arrXorg[2]);
120
+ } else {
121
+ throw 'invalid x-org';
122
+ }
123
+ } catch (err) {
124
+ throw err;
125
+ }
126
+ };
127
+ }
@@ -0,0 +1,75 @@
1
+ import { BPMNClient } from "bpmn-client";
2
+ import { UserProvider } from './UserProvider';
3
+ import { Injectable } from '@nestjs/common';
4
+
5
+ export type UserTaskActorOptions={
6
+ userId:string
7
+ actGroups?:string[]
8
+ actUsers?:string[]
9
+ }
10
+ @Injectable()
11
+ export class Workflow{
12
+ private static instance: Workflow;
13
+ server:BPMNClient
14
+
15
+ constructor(){
16
+ this.server= new BPMNClient(process.env.BPMN_HOST, process.env.BPMN_PORT, process.env.BPMN_API_KEY);
17
+ }
18
+ public static getInstance(): Workflow {
19
+ if (!Workflow.instance) {
20
+ Workflow.instance = new Workflow();
21
+ }
22
+ return Workflow.instance;
23
+ }
24
+
25
+ async executeWorkFlow(id: string, bpmnname: string, docstatus: string,data:any) {
26
+ const workflowactoroptions : UserTaskActorOptions ={
27
+ userId:UserProvider.getInstance().getUid(),
28
+ actGroups:[],
29
+ actUsers:[]
30
+ }
31
+ var instance = await this.server.engine.start(bpmnname, data,null,workflowactoroptions);
32
+ const res = {instanceId:instance.id,data:instance.data,name:instance.name,status:instance.status}
33
+ return Promise.resolve(res);
34
+ }
35
+ async getMyUserTask(){
36
+ const uid = UserProvider.getInstance().getUid()
37
+ const groups = UserProvider.getInstance().getGroups()
38
+ // 'assignments.candidateUsers': User.getInstance().getUid(),
39
+ // 'assignments.candidateGroups': User.getInstance().getGroups
40
+
41
+ let anyof:any = [
42
+ {'items.assignments.assignee':uid},
43
+ ]
44
+ let usersfilter={}
45
+ usersfilter[uid]={$in: 'items.assignments.candidateUsers'}
46
+ anyof.push(usersfilter)
47
+ //{'data.tenantId': 1,'$or':[{
48
+ // 'items.assignments.assignee': 'b2a49a8f-a943-4814-8087-60b1ef2f304f'
49
+ // }]}
50
+ //any of the group
51
+ for(let i=0;i<groups.length;i++){
52
+ const gname = groups[i]
53
+ const tmp = {}
54
+ tmp[gname]={ $in: 'items.assignments.candidateGroups'}
55
+ anyof.push(tmp)
56
+ }
57
+ const filters = {
58
+ 'data.tenantId': UserProvider.getInstance().getTenantId(),
59
+ '$or':anyof
60
+ }
61
+ console.dir(filters)
62
+
63
+
64
+ // 'assignments.assignee': User.getInstance().getUid(),
65
+ const client = new BPMNClient(process.env.BPMN_HOST, process.env.BPMN_PORT, process.env.BPMN_API_KEY);
66
+ const items = await client.datastore.findItems(filters)
67
+ let data=[]
68
+ for(let i=0;i<items.length;i++){
69
+ if(items[i].status=='wait'){
70
+ data.push(items[i])
71
+ }
72
+ }
73
+ return Promise.resolve(data);
74
+ }
75
+ }
@@ -0,0 +1,12 @@
1
+ import { Controller, Get } from '@nestjs/common';
2
+ import { AppService } from './app.service';
3
+
4
+ @Controller()
5
+ export class AppController {
6
+ constructor(private readonly appService: AppService) {}
7
+
8
+ @Get('myworkflowtask')
9
+ async getHello() {
10
+ return await this.appService.getMyTask();
11
+ }
12
+ }
@@ -10,6 +10,8 @@ import { ConfigModule } from '@nestjs/config';
10
10
  import { ServeStaticModule } from '@nestjs/serve-static';
11
11
  import { join } from 'path';
12
12
  import {TenantMiddleware} from './class/TenantMiddleware'
13
+ import {AppController} from './app.controller'
14
+ import {AppService} from './app.service'
13
15
  <% for(let i=0;i<it.length; i++){ %>
14
16
  import {<%= it[i].docname %>Module} from './docs/<%= it[i].doctype %>/<%= it[i].doctype %>.module'
15
17
  <%}%>
@@ -32,8 +34,10 @@ import {<%= it[i].docname %>Module} from './docs/<%= it[i].doctype %>/<%= it[i].
32
34
  tokenValidation: TokenValidation.ONLINE,
33
35
  }),
34
36
  <% for(let i=0;i<it.length; i++){ %><%= it[i].docname %>Module,<%}%>],
35
- controllers: [],
36
- providers: [ {
37
+ controllers: [AppController],
38
+ providers: [
39
+ AppService,
40
+ {
37
41
  provide: APP_GUARD,
38
42
  useClass: AuthGuard,
39
43
  },
@@ -0,0 +1,8 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { Workflow } from './class/Workflow';
3
+ @Injectable()
4
+ export class AppService {
5
+ async getMyTask() {
6
+ return await Workflow.getInstance().getMyUserTask()
7
+ }
8
+ }
@@ -6,6 +6,13 @@ PROJECT_NAME=SimpleApp Demo1
6
6
  PROJECT_DESCRIPTION=Try CRUD
7
7
  PROJECT_Version=1.0.0
8
8
 
9
+ BPMN_HOST=<%=it.bpmnsetting.BPMN_HOST%>
10
+
11
+ BPMN_PORT=<%=it.bpmnsetting.BPMN_PORT%>
12
+
13
+ BPMN_API_KEY=<%=it.bpmnsetting.BPMN_API_KEY%>
14
+
15
+
9
16
  OAUTH2_BASEURL=<%=it.keycloaksetting.OAUTH2_BASEURL%>
10
17
 
11
18
  OAUTH2_REALM=<%=it.keycloaksetting.OAUTH2_REALM%>
@@ -29,6 +29,6 @@ const visible = ref(false)
29
29
  right: 0;
30
30
  background-color: antiquewhite;
31
31
  font-size: large;
32
- top: 0;
32
+ top: 20;
33
33
  }
34
34
  </style>