@simitgroup/simpleapp-generator 2.0.0-i-alpha → 2.0.0-j-alpha
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/ReleaseNote.md +3 -0
- package/package.json +1 -1
- package/templates/basic/nest/service.ts.eta +1 -1
- package/templates/nest/src/simple-app/.core/features/queue/queue-base/queue-base.consumer.ts.eta +1 -1
- package/templates/nest/src/simple-app/.core/features/user-context/user.context.ts.eta +28 -30
- package/templates/nest/src/simple-app/.core/features/webhook/run-webhook.service.ts.eta +39 -33
- package/templates/nest/src/simple-app/.core/framework/schemas/simple-app.schema.ts.eta +3 -3
- package/templates/nuxt/simpleapp/generate/features/miniApp/app/components/MiniAppPageIframe.vue.eta +29 -5
package/ReleaseNote.md
CHANGED
package/package.json
CHANGED
|
@@ -48,7 +48,7 @@ export class <%= it.typename %>Service extends SimpleAppService<schema.<%= it.ty
|
|
|
48
48
|
protected foreignkeys = <%~ JSON.stringify(it.foreignkeys)%>;
|
|
49
49
|
constructor(
|
|
50
50
|
@InjectModel('<%= it.typename %>') mydoc: Model<schema.<%= it.typename %>>,
|
|
51
|
-
|
|
51
|
+
event2:EventEmitter2,
|
|
52
52
|
docNoGen:SimpleAppDocumentNoFormatService,
|
|
53
53
|
logSvc: SimpleAppLogService,
|
|
54
54
|
webhookSvc:RunWebhookService
|
package/templates/nest/src/simple-app/.core/features/queue/queue-base/queue-base.consumer.ts.eta
CHANGED
|
@@ -16,7 +16,7 @@ export abstract class BaseQueueConsumer extends WorkerHost {
|
|
|
16
16
|
protected abstract readonly processor: string;
|
|
17
17
|
|
|
18
18
|
constructor(
|
|
19
|
-
|
|
19
|
+
protected readonly queueUserContext: QueueUserContext,
|
|
20
20
|
@InjectModel('Queuejob') protected queueJobModel: Model<Queuejob>,
|
|
21
21
|
@InjectConnection() private readonly connection: Connection,
|
|
22
22
|
protected eventEmitter: EventEmitter2,
|
|
@@ -212,12 +212,13 @@ export class UserContext extends UserContextInfo {
|
|
|
212
212
|
|
|
213
213
|
setCurrentUserInfo = async (tokenstr: string, xOrg: string, webhookModel: Model<Webhook>) => {
|
|
214
214
|
this.setXOrg(xOrg);
|
|
215
|
-
// console.log('xOrg',xOrg)
|
|
216
215
|
await this.setUserToken(tokenstr);
|
|
217
216
|
this.setUserType('normal');
|
|
218
|
-
//
|
|
219
|
-
|
|
220
|
-
|
|
217
|
+
// branchId: this.getBranchId(), active: true
|
|
218
|
+
const wh = await webhookModel.find({});
|
|
219
|
+
if (Array.isArray(wh) && wh.length > 0) {
|
|
220
|
+
this.webhooks = this.webhooks.concat(wh);
|
|
221
|
+
}
|
|
221
222
|
};
|
|
222
223
|
|
|
223
224
|
// setPackage = (packageName: string) => {
|
|
@@ -276,10 +277,10 @@ export class UserContext extends UserContextInfo {
|
|
|
276
277
|
as: 'tenantInfo',
|
|
277
278
|
localField: 'tenantId',
|
|
278
279
|
foreignField: 'tenantId',
|
|
279
|
-
pipeline: [{ $project:{ created:0,updated:0,createdBy:0,updatedBy:0,__v:0} }],
|
|
280
|
+
pipeline: [{ $project: { created: 0, updated: 0, createdBy: 0, updatedBy: 0, __v: 0 } }],
|
|
280
281
|
},
|
|
281
282
|
},
|
|
282
|
-
{$unwind:{path:'$tenantInfo',preserveNullAndEmptyArrays:true}},
|
|
283
|
+
{ $unwind: { path: '$tenantInfo', preserveNullAndEmptyArrays: true } },
|
|
283
284
|
{
|
|
284
285
|
$lookup: {
|
|
285
286
|
from: 'permission',
|
|
@@ -343,30 +344,30 @@ export class UserContext extends UserContextInfo {
|
|
|
343
344
|
as: 'tenantInfo',
|
|
344
345
|
localField: 'tenantId',
|
|
345
346
|
foreignField: 'tenantId',
|
|
346
|
-
pipeline: [{ $project:{ created:0,updated:0,createdBy:0,updatedBy:0,__v:0} }],
|
|
347
|
+
pipeline: [{ $project: { created: 0, updated: 0, createdBy: 0, updatedBy: 0, __v: 0 } }],
|
|
347
348
|
},
|
|
348
349
|
},
|
|
349
|
-
{$unwind:{path:'$tenantInfo',preserveNullAndEmptyArrays:true}},
|
|
350
|
+
{ $unwind: { path: '$tenantInfo', preserveNullAndEmptyArrays: true } },
|
|
350
351
|
{
|
|
351
352
|
$lookup: {
|
|
352
353
|
from: 'organization',
|
|
353
354
|
as: 'orgInfo',
|
|
354
355
|
localField: 'orgId',
|
|
355
356
|
foreignField: 'orgId',
|
|
356
|
-
pipeline: [{ $project:{ created:0,updated:0,createdBy:0,updatedBy:0,__v:0} }],
|
|
357
|
+
pipeline: [{ $project: { created: 0, updated: 0, createdBy: 0, updatedBy: 0, __v: 0 } }],
|
|
357
358
|
},
|
|
358
359
|
},
|
|
359
|
-
{$unwind:{path:'$orgInfo',preserveNullAndEmptyArrays:true}},
|
|
360
|
+
{ $unwind: { path: '$orgInfo', preserveNullAndEmptyArrays: true } },
|
|
360
361
|
{
|
|
361
362
|
$lookup: {
|
|
362
363
|
from: 'branch',
|
|
363
364
|
as: 'branchInfo',
|
|
364
365
|
localField: 'branchId',
|
|
365
366
|
foreignField: 'branchId',
|
|
366
|
-
pipeline: [{ $project:{ created:0,updated:0,createdBy:0,updatedBy:0,__v:0} }],
|
|
367
|
+
pipeline: [{ $project: { created: 0, updated: 0, createdBy: 0, updatedBy: 0, __v: 0 } }],
|
|
367
368
|
},
|
|
368
369
|
},
|
|
369
|
-
{$unwind:{path:'$branchInfo',preserveNullAndEmptyArrays:true}},
|
|
370
|
+
{ $unwind: { path: '$branchInfo', preserveNullAndEmptyArrays: true } },
|
|
370
371
|
{
|
|
371
372
|
$project: {
|
|
372
373
|
uid: 1,
|
|
@@ -386,9 +387,9 @@ export class UserContext extends UserContextInfo {
|
|
|
386
387
|
timeZone: '$b.o.timeZone',
|
|
387
388
|
currency: '$b.o.currency',
|
|
388
389
|
country: '$b.o.country',
|
|
389
|
-
tenantInfo:1,
|
|
390
|
-
orgInfo:1,
|
|
391
|
-
branchInfo:1,
|
|
390
|
+
tenantInfo: 1,
|
|
391
|
+
orgInfo: 1,
|
|
392
|
+
branchInfo: 1,
|
|
392
393
|
},
|
|
393
394
|
},
|
|
394
395
|
|
|
@@ -461,22 +462,21 @@ export class UserContext extends UserContextInfo {
|
|
|
461
462
|
as: 'tenant',
|
|
462
463
|
},
|
|
463
464
|
},
|
|
464
|
-
{$unwind:'$tenant'},
|
|
465
|
+
{ $unwind: '$tenant' },
|
|
465
466
|
{
|
|
466
|
-
$project:{
|
|
467
|
-
_id:1,
|
|
468
|
-
created:1,
|
|
467
|
+
$project: {
|
|
468
|
+
_id: 1,
|
|
469
|
+
created: 1,
|
|
469
470
|
tenantId: 1,
|
|
470
|
-
tenantName:'$tenant.tenantName'
|
|
471
|
-
}
|
|
472
|
-
}
|
|
471
|
+
tenantName: '$tenant.tenantName',
|
|
472
|
+
},
|
|
473
|
+
},
|
|
473
474
|
],
|
|
474
475
|
},
|
|
475
|
-
}
|
|
476
|
+
},
|
|
476
477
|
];
|
|
477
478
|
|
|
478
479
|
const userProfiles: UserContextInfo[] = await this.userModel.aggregate(pipelines).exec();
|
|
479
|
-
// console.log("userProfiles",userProfiles)
|
|
480
480
|
return userProfiles[0];
|
|
481
481
|
}
|
|
482
482
|
|
|
@@ -492,8 +492,7 @@ export class UserContext extends UserContextInfo {
|
|
|
492
492
|
this.ssoACL = <Record<string, { roles: string[] }>>tokeninfo?.resource_access ?? {};
|
|
493
493
|
this.logger.debug(`User found ${this.uid}`);
|
|
494
494
|
|
|
495
|
-
const userProfile = await this.obtainProfileFromDB();
|
|
496
|
-
// console.log('userProfile', JSON.stringify(userProfile,null,2));
|
|
495
|
+
const userProfile = await this.obtainProfileFromDB();
|
|
497
496
|
if (userProfile) {
|
|
498
497
|
this.logger.debug(`User ${this.uid} exists in tenant (${this.tenantId})`);
|
|
499
498
|
|
|
@@ -535,8 +534,7 @@ export class UserContext extends UserContextInfo {
|
|
|
535
534
|
|
|
536
535
|
if (this.isRealmAdmin() && !this.roles.includes(Role.SuperAdmin)) {
|
|
537
536
|
this.roles.push(Role.SuperAdmin);
|
|
538
|
-
}
|
|
539
|
-
// console.log('this.roles',this.roles)
|
|
537
|
+
}
|
|
540
538
|
// this.logger.verbose(`User ${this.uid} have _id (${this.getId()}), groups (${this.groups.join(',')}) and roles (${this.getRoles().join(',')}).`);
|
|
541
539
|
};
|
|
542
540
|
|
|
@@ -924,7 +922,7 @@ export class UserContext extends UserContextInfo {
|
|
|
924
922
|
// }
|
|
925
923
|
}
|
|
926
924
|
|
|
927
|
-
|
|
925
|
+
|
|
928
926
|
return results;
|
|
929
927
|
}
|
|
930
928
|
|
|
@@ -1007,7 +1005,7 @@ export class UserContext extends UserContextInfo {
|
|
|
1007
1005
|
tenantId: this.tenantId,
|
|
1008
1006
|
orgId: this.orgId,
|
|
1009
1007
|
branchId: this.branchId,
|
|
1010
|
-
});
|
|
1008
|
+
});
|
|
1011
1009
|
return miniAppInstallation.miniApp;
|
|
1012
1010
|
}
|
|
1013
1011
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { BadRequestException, Injectable, Inject, InternalServerErrorException, Logger, NotFoundException } from '@nestjs/common';
|
|
2
2
|
import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
|
|
3
|
+
import { Model } from 'mongoose';
|
|
4
|
+
import { InjectModel } from '@nestjs/mongoose';
|
|
5
|
+
|
|
3
6
|
import { UserContext } from '../user-context/user.context';
|
|
4
7
|
import { Webhook, WebhookLog } from './schemas';
|
|
5
8
|
import { alldocuments } from '../document-no-format/document.dict';
|
|
@@ -8,38 +11,40 @@ import { alldocuments } from '../document-no-format/document.dict';
|
|
|
8
11
|
export class RunWebhookService {
|
|
9
12
|
@Inject(EventEmitter2)
|
|
10
13
|
protected eventEmitter: EventEmitter2;
|
|
11
|
-
protected systemWebhooks
|
|
14
|
+
protected systemWebhooks: Webhook[] = [];
|
|
12
15
|
protected logger = new Logger();
|
|
13
16
|
protected maxRetries = 5;
|
|
14
|
-
public constructor(
|
|
15
|
-
|
|
17
|
+
public constructor(
|
|
18
|
+
@InjectModel('WebhookLog') private webHookLogModel: Model<WebhookLog>
|
|
19
|
+
) {}
|
|
20
|
+
public addWebhook = (wh: Webhook) => this.systemWebhooks.push(wh);
|
|
16
21
|
|
|
17
22
|
/**
|
|
18
23
|
* trigger
|
|
19
24
|
*/
|
|
20
|
-
async run(
|
|
21
|
-
if (process.env.WEBHOOK_ONOFF && process.env.WEBHOOK_ONOFF.toLowerCase() == 'on') {
|
|
22
|
-
return await this.runRealtimeWebhook(
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
+
async run(appUser: UserContext, documentName: string, actionName: string, data: any) {
|
|
26
|
+
if (process.env.WEBHOOK_ONOFF && process.env.WEBHOOK_ONOFF.toLowerCase() == 'on') {
|
|
27
|
+
return await this.runRealtimeWebhook(appUser, documentName, actionName, data);
|
|
28
|
+
} else {
|
|
25
29
|
this.logger.warn(`Webhook off, not run for ${documentName}:${actionName}`);
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
async runRealtimeWebhook(
|
|
33
|
+
async runRealtimeWebhook(appUser: UserContext, documentName: string, actionName: string, data: any) {
|
|
30
34
|
this.logger.debug(`Run webhook ${documentName}, ${actionName}`);
|
|
31
|
-
|
|
32
|
-
const userWebhooks =
|
|
33
|
-
const systemWebhooks = this.systemWebhooks.filter((wh) => wh.resourceName
|
|
34
|
-
|
|
35
|
-
webhooks.concat(userWebhooks)
|
|
36
|
-
|
|
35
|
+
|
|
36
|
+
const userWebhooks = appUser.getWebHooks().filter((wh) => wh.resourceName === documentName && wh.eventType === actionName && wh.active);
|
|
37
|
+
const systemWebhooks = this.systemWebhooks.filter((wh) => wh.resourceName === documentName && wh.eventType === actionName && wh.active);
|
|
38
|
+
let webhooks = [];
|
|
39
|
+
webhooks = webhooks.concat(userWebhooks)
|
|
40
|
+
webhooks = webhooks.concat(systemWebhooks);
|
|
41
|
+
console.log("implement webhooks",webhooks)
|
|
37
42
|
const systemVars = {
|
|
38
|
-
$xOrg:
|
|
39
|
-
$accessToken:
|
|
40
|
-
$fullName:
|
|
41
|
-
$email:
|
|
42
|
-
$uid:
|
|
43
|
+
$xOrg: appUser.getXOrg(),
|
|
44
|
+
$accessToken: appUser.getUserToken(),
|
|
45
|
+
$fullName: appUser.getFullname(),
|
|
46
|
+
$email: appUser.getEmail(),
|
|
47
|
+
$uid: appUser.getUid(),
|
|
43
48
|
$resourceName: documentName,
|
|
44
49
|
$actionName: actionName,
|
|
45
50
|
$url: process.env.APP_URL ?? 'http://localhost:8080',
|
|
@@ -90,7 +95,7 @@ export class RunWebhookService {
|
|
|
90
95
|
// console.log("options",options)
|
|
91
96
|
|
|
92
97
|
if (['POST', 'PUT', 'PATCH'].includes(options.method)) {
|
|
93
|
-
options.body = this.prepareBody(
|
|
98
|
+
options.body = this.prepareBody(appUser, webhook, data, systemVars);
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
while (tries > 0) {
|
|
@@ -107,16 +112,16 @@ export class RunWebhookService {
|
|
|
107
112
|
msg = `Try: ${tryno}/${maxtries} ${documentName}:${actionName}, ${reqMethod} ${webhookUrl}, ${statusCode},${req.statusText}`;
|
|
108
113
|
if (statusCode >= 200 && statusCode <= 300) {
|
|
109
114
|
//success, continue next webhook
|
|
110
|
-
this.addLog(
|
|
115
|
+
await this.addLog(appUser, documentName, webhook, actionName, data, options, 'success', statusCode, msg);
|
|
111
116
|
break;
|
|
112
117
|
} else {
|
|
113
118
|
//common error like 404
|
|
114
|
-
this.addLog(
|
|
119
|
+
await this.addLog(appUser, documentName, webhook, actionName, data, options, 'failed', statusCode, msg);
|
|
115
120
|
}
|
|
116
121
|
} catch (e) {
|
|
117
122
|
// exception, usually server not accessible. use error 500
|
|
118
123
|
msg = `Try: ${tryno}/${maxtries}, error ${documentName}:${actionName} (${webhook._id}) ${e} at ${webhookUrl}`;
|
|
119
|
-
this.addLog(
|
|
124
|
+
await this.addLog(appUser, documentName, webhook, actionName, data, options, 'failed', 500, msg);
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
//finish tries, throw error
|
|
@@ -129,7 +134,7 @@ export class RunWebhookService {
|
|
|
129
134
|
return true;
|
|
130
135
|
}
|
|
131
136
|
|
|
132
|
-
addLog(
|
|
137
|
+
async addLog(appUser: UserContext, documentName: string, webhook: Webhook, actionName: string, data: any, options, status: string, statusCode: number, msg: string) {
|
|
133
138
|
if (status == 'success') {
|
|
134
139
|
this.logger.debug(msg);
|
|
135
140
|
} else {
|
|
@@ -140,14 +145,14 @@ export class RunWebhookService {
|
|
|
140
145
|
|
|
141
146
|
const whlog: WebhookLog = {
|
|
142
147
|
_id: crypto.randomUUID(),
|
|
143
|
-
tenantId:
|
|
144
|
-
orgId:
|
|
145
|
-
branchId:
|
|
148
|
+
tenantId: appUser.getTenantId(),
|
|
149
|
+
orgId: appUser.getOrgId(),
|
|
150
|
+
branchId: appUser.getBranchId(),
|
|
146
151
|
webHookId: webhook._id,
|
|
147
152
|
created: new Date().toISOString(),
|
|
148
|
-
createdBy:
|
|
153
|
+
createdBy: appUser.getUid(),
|
|
149
154
|
updated: new Date().toISOString(),
|
|
150
|
-
updatedBy:
|
|
155
|
+
updatedBy: appUser.getUid(),
|
|
151
156
|
title: `${webhook.requestMethod} ${webhook.url}`,
|
|
152
157
|
dataId: data._id,
|
|
153
158
|
resource: documentName,
|
|
@@ -157,10 +162,11 @@ export class RunWebhookService {
|
|
|
157
162
|
body: body,
|
|
158
163
|
msg: msg,
|
|
159
164
|
};
|
|
160
|
-
|
|
161
|
-
this.
|
|
165
|
+
|
|
166
|
+
const doc = new this.webHookLogModel(whlog)
|
|
167
|
+
await doc.save({ session:appUser.getDBSession() })
|
|
162
168
|
}
|
|
163
|
-
prepareBody(
|
|
169
|
+
prepareBody(appUser: UserContext, webhook: Webhook, data: any, systemVars: any) {
|
|
164
170
|
const cleandata = JSON.parse(JSON.stringify(data));
|
|
165
171
|
|
|
166
172
|
if (webhook.body?.trim() == '*') {
|
|
@@ -121,13 +121,13 @@ export class SchemaConfig {
|
|
|
121
121
|
export class ForeignKey {
|
|
122
122
|
@Field()
|
|
123
123
|
@ApiProperty({ type: () => String })
|
|
124
|
-
_id?:
|
|
124
|
+
_id?: string;
|
|
125
125
|
@Field()
|
|
126
126
|
@ApiProperty({ type: () => String })
|
|
127
|
-
code?:
|
|
127
|
+
code?: string;
|
|
128
128
|
@Field()
|
|
129
129
|
@ApiProperty({ type: () => String })
|
|
130
|
-
label?:
|
|
130
|
+
label?: string;
|
|
131
131
|
[key: string]: any;
|
|
132
132
|
}
|
|
133
133
|
export class MyForeignKey {
|
package/templates/nuxt/simpleapp/generate/features/miniApp/app/components/MiniAppPageIframe.vue.eta
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
v-if="iframeSource !== ''"
|
|
5
5
|
:ref="(el) => (iframeRef = el as HTMLIFrameElement)"
|
|
6
6
|
:src="
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
copyQueryToIframeSource(
|
|
8
|
+
generateIframeSource(iframeSource, {
|
|
9
|
+
miniAppInstallationId: miniAppInstallationId,
|
|
10
|
+
}),
|
|
11
|
+
)
|
|
10
12
|
"
|
|
11
13
|
:title="pageInfo.title || t('miniAppLang.content')"
|
|
12
14
|
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-modals"
|
|
@@ -25,17 +27,19 @@
|
|
|
25
27
|
<script setup lang="ts">
|
|
26
28
|
import {
|
|
27
29
|
MiniAppDetail,
|
|
28
|
-
|
|
30
|
+
MiniAppIntegrationCustomPagePages,
|
|
29
31
|
} from "~/simpleapp/generate/openapi";
|
|
30
32
|
|
|
31
33
|
const props = defineProps<{
|
|
32
34
|
miniApp: MiniAppDetail;
|
|
33
|
-
pageInfo:
|
|
35
|
+
pageInfo: MiniAppIntegrationCustomPagePages;
|
|
34
36
|
miniAppCode: string;
|
|
35
37
|
miniAppInstallationId: string;
|
|
36
38
|
developerPortalAppId: string;
|
|
37
39
|
}>();
|
|
38
40
|
|
|
41
|
+
const route = useRoute();
|
|
42
|
+
|
|
39
43
|
const _xOrg = getPathPara("xorg", "");
|
|
40
44
|
const hasError = ref(false);
|
|
41
45
|
|
|
@@ -53,6 +57,26 @@ function generateIframeSource(template: string, options: Option = {}) {
|
|
|
53
57
|
});
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
function copyQueryToIframeSource(url: string): string {
|
|
61
|
+
const query = route.query;
|
|
62
|
+
const searchParams = new URLSearchParams();
|
|
63
|
+
|
|
64
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
65
|
+
if (Array.isArray(value)) {
|
|
66
|
+
value.forEach((v) => {
|
|
67
|
+
if (v != null) searchParams.append(key, v);
|
|
68
|
+
});
|
|
69
|
+
} else if (value != null) {
|
|
70
|
+
searchParams.append(key, value);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const hasQuery = url.includes("?");
|
|
75
|
+
const queryString = searchParams.toString();
|
|
76
|
+
|
|
77
|
+
return queryString ? url + (hasQuery ? "&" : "?") + queryString : url;
|
|
78
|
+
}
|
|
79
|
+
|
|
56
80
|
const { iframeRef, onIframeLoad } = useMiniAppBridge(
|
|
57
81
|
props.miniAppInstallationId,
|
|
58
82
|
props.pageInfo,
|