@waline/vercel 1.30.0 → 1.30.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 (60) hide show
  1. package/package.json +9 -6
  2. package/src/controller/db.js +18 -0
  3. package/src/extend/controller.js +1 -1
  4. package/dist/404.html +0 -39
  5. package/dist/500.html +0 -275
  6. package/dist/index.js +0 -58521
  7. package/dist/package.json +0 -55
  8. package/dist/src/config/adapter.js +0 -170
  9. package/dist/src/config/config.js +0 -134
  10. package/dist/src/config/extend.js +0 -38
  11. package/dist/src/config/middleware.js +0 -67
  12. package/dist/src/config/router.js +0 -1
  13. package/dist/src/controller/article.js +0 -88
  14. package/dist/src/controller/comment.js +0 -736
  15. package/dist/src/controller/db.js +0 -71
  16. package/dist/src/controller/index.js +0 -36
  17. package/dist/src/controller/oauth.js +0 -136
  18. package/dist/src/controller/rest.js +0 -60
  19. package/dist/src/controller/token/2fa.js +0 -67
  20. package/dist/src/controller/token.js +0 -76
  21. package/dist/src/controller/user/password.js +0 -53
  22. package/dist/src/controller/user.js +0 -290
  23. package/dist/src/controller/verification.js +0 -35
  24. package/dist/src/extend/controller.js +0 -26
  25. package/dist/src/extend/think.js +0 -104
  26. package/dist/src/locales/en.json +0 -19
  27. package/dist/src/locales/index.js +0 -12
  28. package/dist/src/locales/zh-CN.json +0 -19
  29. package/dist/src/locales/zh-TW.json +0 -19
  30. package/dist/src/logic/article.js +0 -27
  31. package/dist/src/logic/base.js +0 -165
  32. package/dist/src/logic/comment.js +0 -317
  33. package/dist/src/logic/db.js +0 -81
  34. package/dist/src/logic/oauth.js +0 -10
  35. package/dist/src/logic/token/2fa.js +0 -28
  36. package/dist/src/logic/token.js +0 -53
  37. package/dist/src/logic/user/password.js +0 -11
  38. package/dist/src/logic/user.js +0 -117
  39. package/dist/src/middleware/dashboard.js +0 -23
  40. package/dist/src/middleware/version.js +0 -6
  41. package/dist/src/service/akismet.js +0 -42
  42. package/dist/src/service/avatar.js +0 -36
  43. package/dist/src/service/markdown/highlight.js +0 -32
  44. package/dist/src/service/markdown/index.js +0 -64
  45. package/dist/src/service/markdown/katex.js +0 -50
  46. package/dist/src/service/markdown/mathCommon.js +0 -156
  47. package/dist/src/service/markdown/mathjax.js +0 -78
  48. package/dist/src/service/markdown/utils.js +0 -11
  49. package/dist/src/service/markdown/xss.js +0 -44
  50. package/dist/src/service/notify.js +0 -538
  51. package/dist/src/service/storage/base.js +0 -31
  52. package/dist/src/service/storage/cloudbase.js +0 -222
  53. package/dist/src/service/storage/deta.js +0 -309
  54. package/dist/src/service/storage/github.js +0 -379
  55. package/dist/src/service/storage/leancloud.js +0 -432
  56. package/dist/src/service/storage/mongodb.js +0 -180
  57. package/dist/src/service/storage/mysql.js +0 -123
  58. package/dist/src/service/storage/postgresql.js +0 -84
  59. package/dist/src/service/storage/sqlite.js +0 -11
  60. package/dist/src/service/storage/tidb.js +0 -3
@@ -1,736 +0,0 @@
1
- const BaseRest = require('./rest');
2
- const akismet = require('../service/akismet');
3
- const { getMarkdownParser } = require('../service/markdown');
4
-
5
- const markdownParser = getMarkdownParser();
6
-
7
- async function formatCmt(
8
- { ua, ip, ...comment },
9
- users = [],
10
- { avatarProxy },
11
- loginUser
12
- ) {
13
- ua = think.uaParser(ua);
14
- if (!think.config('disableUserAgent')) {
15
- comment.browser = `${ua.browser.name || ''}${(ua.browser.version || '')
16
- .split('.')
17
- .slice(0, 2)
18
- .join('.')}`;
19
- comment.os = [ua.os.name, ua.os.version].filter((v) => v).join(' ');
20
- }
21
-
22
- const user = users.find(({ objectId }) => comment.user_id === objectId);
23
-
24
- if (!think.isEmpty(user)) {
25
- comment.nick = user.display_name;
26
- comment.mail = user.email;
27
- comment.link = user.url;
28
- comment.type = user.type;
29
- comment.label = user.label;
30
- }
31
-
32
- const avatarUrl =
33
- user && user.avatar
34
- ? user.avatar
35
- : await think.service('avatar').stringify(comment);
36
-
37
- comment.avatar =
38
- avatarProxy && !avatarUrl.includes(avatarProxy)
39
- ? avatarProxy + '?url=' + encodeURIComponent(avatarUrl)
40
- : avatarUrl;
41
-
42
- const isAdmin = loginUser && loginUser.type === 'administrator';
43
-
44
- if (loginUser) {
45
- comment.orig = comment.comment;
46
- }
47
- if (!isAdmin) {
48
- delete comment.mail;
49
- } else {
50
- comment.ip = ip;
51
- }
52
-
53
- // administrator can always show region
54
- if (isAdmin || !think.config('disableRegion')) {
55
- comment.addr = await think.ip2region(ip, { depth: isAdmin ? 3 : 1 });
56
- }
57
- comment.comment = markdownParser(comment.comment);
58
- comment.like = Number(comment.like) || 0;
59
-
60
- // compat sql storage return number flag to string
61
- if (typeof comment.sticky === 'string') {
62
- comment.sticky = Boolean(Number(comment.sticky));
63
- }
64
-
65
- return comment;
66
- }
67
-
68
- module.exports = class extends BaseRest {
69
- constructor(ctx) {
70
- super(ctx);
71
- this.modelInstance = this.getModel('Comment');
72
- }
73
-
74
- async getAction() {
75
- const { type } = this.get();
76
- const { userInfo } = this.ctx.state;
77
-
78
- switch (type) {
79
- case 'recent': {
80
- const { count } = this.get();
81
- const where = {};
82
-
83
- if (think.isEmpty(userInfo) || this.config('storage') === 'deta') {
84
- where.status = ['NOT IN', ['waiting', 'spam']];
85
- } else {
86
- where._complex = {
87
- _logic: 'or',
88
- status: ['NOT IN', ['waiting', 'spam']],
89
- user_id: userInfo.objectId,
90
- };
91
- }
92
-
93
- const comments = await this.modelInstance.select(where, {
94
- desc: 'insertedAt',
95
- limit: count,
96
- field: [
97
- 'status',
98
- 'comment',
99
- 'insertedAt',
100
- 'link',
101
- 'mail',
102
- 'nick',
103
- 'url',
104
- 'pid',
105
- 'rid',
106
- 'ua',
107
- 'ip',
108
- 'user_id',
109
- 'sticky',
110
- 'like',
111
- ],
112
- });
113
-
114
- const userModel = this.getModel('Users');
115
- const user_ids = Array.from(
116
- new Set(comments.map(({ user_id }) => user_id).filter((v) => v))
117
- );
118
-
119
- let users = [];
120
-
121
- if (user_ids.length) {
122
- users = await userModel.select(
123
- { objectId: ['IN', user_ids] },
124
- {
125
- field: [
126
- 'display_name',
127
- 'email',
128
- 'url',
129
- 'type',
130
- 'avatar',
131
- 'label',
132
- ],
133
- }
134
- );
135
- }
136
-
137
- return this.json(
138
- await Promise.all(
139
- comments.map((cmt) =>
140
- formatCmt(cmt, users, this.config(), userInfo)
141
- )
142
- )
143
- );
144
- }
145
-
146
- case 'count': {
147
- const { url } = this.get();
148
- const where =
149
- Array.isArray(url) && url.length ? { url: ['IN', url] } : {};
150
-
151
- if (think.isEmpty(userInfo) || this.config('storage') === 'deta') {
152
- where.status = ['NOT IN', ['waiting', 'spam']];
153
- } else {
154
- where._complex = {
155
- _logic: 'or',
156
- status: ['NOT IN', ['waiting', 'spam']],
157
- user_id: userInfo.objectId,
158
- };
159
- }
160
-
161
- if (Array.isArray(url) && url.length > 1) {
162
- const data = await this.modelInstance.select(where, {
163
- field: ['url'],
164
- });
165
-
166
- return this.json(
167
- url.map((u) => data.filter(({ url }) => url === u).length)
168
- );
169
- }
170
- const data = await this.modelInstance.count(where);
171
-
172
- return this.json(data);
173
- }
174
-
175
- case 'list': {
176
- const { page, pageSize, owner, status, keyword } = this.get();
177
- const where = {};
178
-
179
- if (owner === 'mine') {
180
- const { userInfo } = this.ctx.state;
181
-
182
- where.mail = userInfo.email;
183
- }
184
-
185
- if (status) {
186
- where.status = status;
187
-
188
- // compat with valine old data without status property
189
- if (status === 'approved') {
190
- where.status = ['NOT IN', ['waiting', 'spam']];
191
- }
192
- }
193
-
194
- if (keyword) {
195
- where.comment = ['LIKE', `%${keyword}%`];
196
- }
197
-
198
- const count = await this.modelInstance.count(where);
199
- const spamCount = await this.modelInstance.count({ status: 'spam' });
200
- const waitingCount = await this.modelInstance.count({
201
- status: 'waiting',
202
- });
203
- const comments = await this.modelInstance.select(where, {
204
- desc: 'insertedAt',
205
- limit: pageSize,
206
- offset: Math.max((page - 1) * pageSize, 0),
207
- });
208
-
209
- const userModel = this.getModel('Users');
210
- const user_ids = Array.from(
211
- new Set(comments.map(({ user_id }) => user_id).filter((v) => v))
212
- );
213
-
214
- let users = [];
215
-
216
- if (user_ids.length) {
217
- users = await userModel.select(
218
- { objectId: ['IN', user_ids] },
219
- {
220
- field: [
221
- 'display_name',
222
- 'email',
223
- 'url',
224
- 'type',
225
- 'avatar',
226
- 'label',
227
- ],
228
- }
229
- );
230
- }
231
-
232
- return this.success({
233
- page,
234
- totalPages: Math.ceil(count / pageSize),
235
- pageSize,
236
- spamCount,
237
- waitingCount,
238
- data: await Promise.all(
239
- comments.map((cmt) =>
240
- formatCmt(cmt, users, this.config(), userInfo)
241
- )
242
- ),
243
- });
244
- }
245
-
246
- default: {
247
- const { path: url, page, pageSize, sortBy } = this.get();
248
- const where = { url };
249
-
250
- if (think.isEmpty(userInfo) || this.config('storage') === 'deta') {
251
- where.status = ['NOT IN', ['waiting', 'spam']];
252
- } else if (userInfo.type !== 'administrator') {
253
- where._complex = {
254
- _logic: 'or',
255
- status: ['NOT IN', ['waiting', 'spam']],
256
- user_id: userInfo.objectId,
257
- };
258
- }
259
-
260
- const totalCount = await this.modelInstance.count(where);
261
- const pageOffset = Math.max((page - 1) * pageSize, 0);
262
- let comments = [];
263
- let rootComments = [];
264
- let rootCount = 0;
265
- const selectOptions = {
266
- field: [
267
- 'status',
268
- 'comment',
269
- 'insertedAt',
270
- 'link',
271
- 'mail',
272
- 'nick',
273
- 'pid',
274
- 'rid',
275
- 'ua',
276
- 'ip',
277
- 'user_id',
278
- 'sticky',
279
- 'like',
280
- ],
281
- };
282
-
283
- if (sortBy) {
284
- const [field, order] = sortBy.split('_');
285
-
286
- if (order === 'desc') {
287
- selectOptions.desc = field;
288
- } else if (order === 'asc') {
289
- // do nothing because of ascending order is default behavior
290
- }
291
- }
292
-
293
- /**
294
- * most of case we have just little comments
295
- * while if we want get rootComments, rootCount, childComments with pagination
296
- * we have to query three times from storage service
297
- * That's so expensive for user, especially in the serverless.
298
- * so we have a comments length check
299
- * If you have less than 1000 comments, then we'll get all comments one time
300
- * then we'll compute rootComment, rootCount, childComments in program to reduce http request query
301
- *
302
- * Why we have limit and the limit is 1000?
303
- * Many serverless storages have fetch data limit, for example LeanCloud is 100, and CloudBase is 1000
304
- * If we have much comments, We should use more request to fetch all comments
305
- * If we have 3000 comments, We have to use 30 http request to fetch comments, things go athwart.
306
- * And Serverless Service like vercel have execute time limit
307
- * if we have more http requests in a serverless function, it may timeout easily.
308
- * so we use limit to avoid it.
309
- */
310
- if (totalCount < 1000) {
311
- comments = await this.modelInstance.select(where, selectOptions);
312
- rootCount = comments.filter(({ rid }) => !rid).length;
313
- rootComments = [
314
- ...comments.filter(({ rid, sticky }) => !rid && sticky),
315
- ...comments.filter(({ rid, sticky }) => !rid && !sticky),
316
- ].slice(pageOffset, pageOffset + pageSize);
317
- const rootIds = {};
318
-
319
- rootComments.forEach(({ objectId }) => {
320
- rootIds[objectId] = true;
321
- });
322
- comments = comments.filter(
323
- (cmt) => rootIds[cmt.objectId] || rootIds[cmt.rid]
324
- );
325
- } else {
326
- rootComments = await this.modelInstance.select(
327
- { ...where, rid: undefined },
328
- {
329
- ...selectOptions,
330
- offset: pageOffset,
331
- limit: pageSize,
332
- }
333
- );
334
- const children = await this.modelInstance.select(
335
- {
336
- ...where,
337
- rid: ['IN', rootComments.map(({ objectId }) => objectId)],
338
- },
339
- selectOptions
340
- );
341
-
342
- comments = [...rootComments, ...children];
343
- rootCount = await this.modelInstance.count({
344
- ...where,
345
- rid: undefined,
346
- });
347
- }
348
-
349
- const userModel = this.getModel('Users');
350
- const user_ids = Array.from(
351
- new Set(comments.map(({ user_id }) => user_id).filter((v) => v))
352
- );
353
- let users = [];
354
-
355
- if (user_ids.length) {
356
- users = await userModel.select(
357
- { objectId: ['IN', user_ids] },
358
- {
359
- field: [
360
- 'display_name',
361
- 'email',
362
- 'url',
363
- 'type',
364
- 'avatar',
365
- 'label',
366
- ],
367
- }
368
- );
369
- }
370
-
371
- if (think.isArray(this.config('levels'))) {
372
- const countWhere = {
373
- status: ['NOT IN', ['waiting', 'spam']],
374
- _complex: {},
375
- };
376
-
377
- if (user_ids.length) {
378
- countWhere._complex.user_id = ['IN', user_ids];
379
- }
380
- const mails = Array.from(
381
- new Set(comments.map(({ mail }) => mail).filter((v) => v))
382
- );
383
-
384
- if (mails.length) {
385
- countWhere._complex.mail = ['IN', mails];
386
- }
387
- if (!think.isEmpty(countWhere._complex)) {
388
- countWhere._complex._logic = 'or';
389
- } else {
390
- delete countWhere._complex;
391
- }
392
- const counts = await this.modelInstance.count(countWhere, {
393
- group: ['user_id', 'mail'],
394
- });
395
-
396
- comments.forEach((cmt) => {
397
- const countItem = (counts || []).find(({ mail, user_id }) => {
398
- if (cmt.user_id) {
399
- return user_id === cmt.user_id;
400
- }
401
-
402
- return mail === cmt.mail;
403
- });
404
-
405
- let level = 0;
406
-
407
- if (countItem) {
408
- const _level = think.findLastIndex(
409
- this.config('levels'),
410
- (l) => l <= countItem.count
411
- );
412
-
413
- if (_level !== -1) {
414
- level = _level;
415
- }
416
- }
417
- cmt.level = level;
418
- });
419
- }
420
-
421
- return this.json({
422
- page,
423
- totalPages: Math.ceil(rootCount / pageSize),
424
- pageSize,
425
- count: totalCount,
426
- data: await Promise.all(
427
- rootComments.map(async (comment) => {
428
- const cmt = await formatCmt(
429
- comment,
430
- users,
431
- this.config(),
432
- userInfo
433
- );
434
-
435
- cmt.children = await Promise.all(
436
- comments
437
- .filter(({ rid }) => rid === cmt.objectId)
438
- .map((cmt) => formatCmt(cmt, users, this.config(), userInfo))
439
- .reverse()
440
- );
441
-
442
- return cmt;
443
- })
444
- ),
445
- });
446
- }
447
- }
448
- }
449
-
450
- async postAction() {
451
- think.logger.debug('Post Comment Start!');
452
-
453
- const { comment, link, mail, nick, pid, rid, ua, url, at } = this.post();
454
- const data = {
455
- link,
456
- mail,
457
- nick,
458
- pid,
459
- rid,
460
- ua,
461
- url,
462
- comment,
463
- ip: this.ctx.ip,
464
- insertedAt: new Date(),
465
- user_id: this.ctx.state.userInfo.objectId,
466
- };
467
-
468
- if (pid) {
469
- data.comment = `[@${at}](#${pid}): ` + data.comment;
470
- }
471
-
472
- think.logger.debug('Post Comment initial Data:', data);
473
-
474
- const { userInfo } = this.ctx.state;
475
-
476
- if (!userInfo || userInfo.type !== 'administrator') {
477
- /** IP disallowList */
478
- const { disallowIPList } = this.config();
479
-
480
- if (
481
- think.isArray(disallowIPList) &&
482
- disallowIPList.length &&
483
- disallowIPList.includes(data.ip)
484
- ) {
485
- think.logger.debug(`Comment IP ${data.ip} is in disallowIPList`);
486
-
487
- return this.ctx.throw(403);
488
- }
489
-
490
- think.logger.debug(`Comment IP ${data.ip} check OK!`);
491
-
492
- /** Duplicate content detect */
493
- const duplicate = await this.modelInstance.select({
494
- url,
495
- mail: data.mail,
496
- nick: data.nick,
497
- link: data.link,
498
- comment: data.comment,
499
- });
500
-
501
- if (!think.isEmpty(duplicate)) {
502
- think.logger.debug(
503
- 'The comment author had post same comment content before'
504
- );
505
-
506
- return this.fail(this.locale('Duplicate Content'));
507
- }
508
-
509
- think.logger.debug('Comment duplicate check OK!');
510
-
511
- /** IP frequency */
512
- const { IPQPS = 60 } = process.env;
513
-
514
- const recent = await this.modelInstance.select({
515
- ip: this.ctx.ip,
516
- insertedAt: ['>', new Date(Date.now() - IPQPS * 1000)],
517
- });
518
-
519
- if (!think.isEmpty(recent)) {
520
- think.logger.debug(`The author has posted in ${IPQPS} seconds.`);
521
-
522
- return this.fail(this.locale('Comment too fast!'));
523
- }
524
-
525
- think.logger.debug(`Comment post frequency check OK!`);
526
-
527
- /** Akismet */
528
- const { COMMENT_AUDIT } = process.env;
529
-
530
- data.status = COMMENT_AUDIT ? 'waiting' : 'approved';
531
-
532
- think.logger.debug(`Comment initial status is ${data.status}`);
533
-
534
- if (data.status === 'approved') {
535
- const spam = await akismet(data, this.ctx.serverURL).catch((e) =>
536
- console.log(e)
537
- ); // ignore akismet error
538
-
539
- if (spam === true) {
540
- data.status = 'spam';
541
- }
542
- }
543
-
544
- think.logger.debug(`Comment akismet check result: ${data.status}`);
545
-
546
- if (data.status !== 'spam') {
547
- /** KeyWord Filter */
548
- const { forbiddenWords } = this.config();
549
-
550
- if (!think.isEmpty(forbiddenWords)) {
551
- const regexp = new RegExp('(' + forbiddenWords.join('|') + ')', 'ig');
552
-
553
- if (regexp.test(comment)) {
554
- data.status = 'spam';
555
- }
556
- }
557
- }
558
-
559
- think.logger.debug(`Comment keyword check result: ${data.status}`);
560
- } else {
561
- data.status = 'approved';
562
- }
563
-
564
- const preSaveResp = await this.hook('preSave', data);
565
-
566
- if (preSaveResp) {
567
- return this.fail(preSaveResp.errmsg);
568
- }
569
-
570
- think.logger.debug(`Comment post hooks preSave done!`);
571
-
572
- const resp = await this.modelInstance.add(data);
573
-
574
- think.logger.debug(`Comment have been added to storage.`);
575
-
576
- let parentComment;
577
- let parentUser;
578
-
579
- if (pid) {
580
- parentComment = await this.modelInstance.select({ objectId: pid });
581
- parentComment = parentComment[0];
582
- if (parentComment.user_id) {
583
- parentUser = await this.getModel('Users').select({
584
- objectId: parentComment.user_id,
585
- });
586
- parentUser = parentUser[0];
587
- }
588
- }
589
-
590
- await this.ctx.webhook('new_comment', {
591
- comment: { ...resp, rawComment: comment },
592
- reply: parentComment,
593
- });
594
-
595
- const cmtReturn = await formatCmt(
596
- resp,
597
- [userInfo],
598
- this.config(),
599
- userInfo
600
- );
601
- const parentReturn = parentComment
602
- ? await formatCmt(
603
- parentComment,
604
- parentUser ? [parentUser] : [],
605
- this.config(),
606
- userInfo
607
- )
608
- : undefined;
609
-
610
- if (comment.status !== 'spam') {
611
- const notify = this.service('notify', this);
612
-
613
- await notify.run(
614
- { ...cmtReturn, mail: resp.mail, rawComment: comment },
615
- parentReturn ? { ...parentReturn, mail: parentComment.mail } : undefined
616
- );
617
- }
618
-
619
- think.logger.debug(`Comment notify done!`);
620
-
621
- await this.hook('postSave', resp, parentComment);
622
-
623
- think.logger.debug(`Comment post hooks postSave done!`);
624
-
625
- return this.success(
626
- await formatCmt(resp, [userInfo], this.config(), userInfo)
627
- );
628
- }
629
-
630
- async putAction() {
631
- const { userInfo } = this.ctx.state;
632
- const isAdmin = userInfo.type === 'administrator';
633
- let data = isAdmin ? this.post() : this.post('comment,like');
634
- let oldData = await this.modelInstance.select({ objectId: this.id });
635
-
636
- if (think.isEmpty(oldData) || think.isEmpty(data)) {
637
- return this.success();
638
- }
639
-
640
- oldData = oldData[0];
641
- if (think.isBoolean(data.like)) {
642
- const likeIncMax = this.config('LIKE_INC_MAX') || 1;
643
-
644
- data.like =
645
- (Number(oldData.like) || 0) +
646
- (data.like ? Math.ceil(Math.random() * likeIncMax) : -1);
647
- }
648
-
649
- const preUpdateResp = await this.hook('preUpdate', {
650
- ...data,
651
- objectId: this.id,
652
- });
653
-
654
- if (preUpdateResp) {
655
- return this.fail(preUpdateResp);
656
- }
657
-
658
- const newData = await this.modelInstance.update(data, {
659
- objectId: this.id,
660
- });
661
-
662
- let cmtUser;
663
-
664
- if (!think.isEmpty(newData) && newData[0].user_id) {
665
- cmtUser = await this.getModel('Users').select({
666
- objectId: newData[0].user_id,
667
- });
668
- cmtUser = cmtUser[0];
669
- }
670
- const cmtReturn = await formatCmt(
671
- newData[0],
672
- cmtUser ? [cmtUser] : [],
673
- this.config(),
674
- userInfo
675
- );
676
-
677
- if (
678
- oldData.status === 'waiting' &&
679
- data.status === 'approved' &&
680
- oldData.pid
681
- ) {
682
- let pComment = await this.modelInstance.select({
683
- objectId: oldData.pid,
684
- });
685
-
686
- pComment = pComment[0];
687
-
688
- let pUser;
689
-
690
- if (pComment.user_id) {
691
- pUser = await this.getModel('Users').select({
692
- objectId: pComment.user_id,
693
- });
694
- pUser = pUser[0];
695
- }
696
-
697
- const notify = this.service('notify', this);
698
- const pcmtReturn = await formatCmt(
699
- pComment,
700
- pUser ? [pUser] : [],
701
- this.config(),
702
- userInfo
703
- );
704
-
705
- await notify.run(
706
- { ...cmtReturn, mail: newData[0].mail },
707
- { ...pcmtReturn, mail: pComment.mail },
708
- true
709
- );
710
- }
711
-
712
- await this.hook('postUpdate', data);
713
-
714
- return this.success(cmtReturn);
715
- }
716
-
717
- async deleteAction() {
718
- const preDeleteResp = await this.hook('preDelete', this.id);
719
-
720
- if (preDeleteResp) {
721
- return this.fail(preDeleteResp);
722
- }
723
-
724
- await this.modelInstance.delete({
725
- _complex: {
726
- _logic: 'or',
727
- objectId: this.id,
728
- pid: this.id,
729
- rid: this.id,
730
- },
731
- });
732
- await this.hook('postDelete', this.id);
733
-
734
- return this.success();
735
- }
736
- };