@waline/vercel 1.19.4 → 1.21.0

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": "@waline/vercel",
3
- "version": "1.19.4",
3
+ "version": "1.21.0",
4
4
  "description": "vercel server for waline comment system",
5
5
  "keywords": [
6
6
  "waline",
@@ -6,7 +6,7 @@ const { getMarkdownParser } = require('../service/markdown');
6
6
  const markdownParser = getMarkdownParser();
7
7
 
8
8
  async function formatCmt(
9
- { ua, user_id, ip, ...comment },
9
+ { ua, ip, ...comment },
10
10
  users = [],
11
11
  { avatarProxy },
12
12
  loginUser
@@ -20,7 +20,7 @@ async function formatCmt(
20
20
  comment.os = [ua.os.name, ua.os.version].filter((v) => v).join(' ');
21
21
  }
22
22
 
23
- const user = users.find(({ objectId }) => user_id === objectId);
23
+ const user = users.find(({ objectId }) => comment.user_id === objectId);
24
24
 
25
25
  if (!think.isEmpty(user)) {
26
26
  comment.nick = user.display_name;
@@ -42,10 +42,12 @@ async function formatCmt(
42
42
 
43
43
  const isAdmin = loginUser && loginUser.type === 'administrator';
44
44
 
45
+ if (loginUser) {
46
+ comment.orig = comment.comment;
47
+ }
45
48
  if (!isAdmin) {
46
49
  delete comment.mail;
47
50
  } else {
48
- comment.orig = comment.comment;
49
51
  comment.ip = ip;
50
52
  }
51
53
 
@@ -247,7 +249,7 @@ module.exports = class extends BaseRest {
247
249
  }
248
250
 
249
251
  default: {
250
- const { path: url, page, pageSize } = this.get();
252
+ const { path: url, page, pageSize, sortBy } = this.get();
251
253
  const where = { url };
252
254
 
253
255
  if (think.isEmpty(userInfo) || this.config('storage') === 'deta') {
@@ -266,7 +268,6 @@ module.exports = class extends BaseRest {
266
268
  let rootComments = [];
267
269
  let rootCount = 0;
268
270
  const selectOptions = {
269
- desc: 'insertedAt',
270
271
  field: [
271
272
  'status',
272
273
  'comment',
@@ -284,6 +285,16 @@ module.exports = class extends BaseRest {
284
285
  ],
285
286
  };
286
287
 
288
+ if (sortBy) {
289
+ const [field, order] = sortBy.split('_');
290
+
291
+ if (order === 'desc') {
292
+ selectOptions.desc = field;
293
+ } else if (order === 'asc') {
294
+ // do nothing because of ascending order is default behaviour
295
+ }
296
+ }
297
+
287
298
  /**
288
299
  * most of case we have just little comments
289
300
  * while if we want get rootComments, rootCount, childComments with pagination
@@ -583,7 +594,7 @@ module.exports = class extends BaseRest {
583
594
  if (parentComment.user_id) {
584
595
  parentUser = await this.service(
585
596
  `storage/${this.config('storage')}`,
586
- 'User'
597
+ 'Users'
587
598
  ).select({
588
599
  objectId: parentComment.user_id,
589
600
  });
@@ -633,26 +644,19 @@ module.exports = class extends BaseRest {
633
644
 
634
645
  async putAction() {
635
646
  const { userInfo } = this.ctx.state;
636
- let data = this.post();
647
+ const isAdmin = userInfo.type === 'administrator';
648
+ let data = isAdmin ? this.post() : this.post('comment,like');
637
649
  let oldData = await this.modelInstance.select({ objectId: this.id });
638
650
 
639
- if (think.isEmpty(oldData)) {
651
+ if (think.isEmpty(oldData) || think.isEmpty(data)) {
640
652
  return this.success();
641
653
  }
642
654
 
643
655
  oldData = oldData[0];
644
- if (think.isEmpty(userInfo) || userInfo.type !== 'administrator') {
645
- if (!think.isBoolean(data.like)) {
646
- return this.success();
647
- }
648
-
656
+ if (think.isBoolean(data.like)) {
649
657
  const likeIncMax = this.config('LIKE_INC_MAX') || 1;
650
-
651
- data = {
652
- like:
653
- (Number(oldData.like) || 0) +
654
- (data.like ? Math.ceil(Math.random() * likeIncMax) : -1),
655
- };
658
+ data.like = (Number(oldData.like) || 0) +
659
+ (data.like ? Math.ceil(Math.random() * likeIncMax) : -1);
656
660
  }
657
661
 
658
662
  const preUpdateResp = await this.hook('preUpdate', {
@@ -668,22 +672,28 @@ module.exports = class extends BaseRest {
668
672
  objectId: this.id,
669
673
  });
670
674
 
675
+ let cmtUser;
676
+ if (!think.isEmpty(newData) && newData[0].user_id) {
677
+ cmtUser = await this.service(
678
+ `storage/${this.config('storage')}`,
679
+ 'Users'
680
+ ).select({
681
+ objectId: newData[0].user_id,
682
+ });
683
+ cmtUser = cmtUser[0];
684
+ }
685
+ const cmtReturn = await formatCmt(
686
+ newData[0],
687
+ cmtUser ? [cmtUser] : [],
688
+ this.config(),
689
+ userInfo
690
+ );
691
+
671
692
  if (
672
693
  oldData.status === 'waiting' &&
673
694
  data.status === 'approved' &&
674
695
  oldData.pid
675
696
  ) {
676
- let cmtUser;
677
-
678
- if (newData.user_id) {
679
- cmtUser = await this.service(
680
- `storage/${this.config('storage')}`,
681
- 'User'
682
- ).select({
683
- objectId: newData.user_id,
684
- });
685
- cmtUser = cmtUser[0];
686
- }
687
697
 
688
698
  let pComment = await this.modelInstance.select({
689
699
  objectId: oldData.pid,
@@ -696,7 +706,7 @@ module.exports = class extends BaseRest {
696
706
  if (pComment.user_id) {
697
707
  pUser = await this.service(
698
708
  `storage/${this.config('storage')}`,
699
- 'User'
709
+ 'Users'
700
710
  ).select({
701
711
  objectId: pComment.user_id,
702
712
  });
@@ -704,12 +714,6 @@ module.exports = class extends BaseRest {
704
714
  }
705
715
 
706
716
  const notify = this.service('notify');
707
- const cmtReturn = await formatCmt(
708
- newData,
709
- cmtUser ? [cmtUser] : [],
710
- this.config(),
711
- userInfo
712
- );
713
717
  const pcmtReturn = await formatCmt(
714
718
  pComment,
715
719
  pUser ? [pUser] : [],
@@ -718,7 +722,7 @@ module.exports = class extends BaseRest {
718
722
  );
719
723
 
720
724
  await notify.run(
721
- { ...cmtReturn, mail: newData.mail },
725
+ { ...cmtReturn, mail: newData[0].mail },
722
726
  { ...pcmtReturn, mail: pComment.mail },
723
727
  true
724
728
  );
@@ -726,7 +730,7 @@ module.exports = class extends BaseRest {
726
730
 
727
731
  await this.hook('postUpdate', data);
728
732
 
729
- return this.success();
733
+ return this.success(cmtReturn);
730
734
  }
731
735
 
732
736
  async deleteAction() {
@@ -1,7 +1,6 @@
1
1
  const jwt = require('jsonwebtoken');
2
2
  const fetch = require('node-fetch');
3
3
  const { PasswordHash } = require('phpass');
4
- const qs = require('querystring');
5
4
 
6
5
  module.exports = class extends think.Controller {
7
6
  constructor(ctx) {
@@ -21,16 +20,16 @@ module.exports = class extends think.Controller {
21
20
 
22
21
  if (!hasCode) {
23
22
  const { serverURL } = this.ctx;
24
- const redirectUrl = `${serverURL}/oauth?${qs.stringify({
23
+ const redirectUrl = `${serverURL}/oauth?${new URLSearchParams({
25
24
  redirect,
26
25
  type,
27
- })}`;
26
+ }).toString()}`;
28
27
 
29
28
  return this.redirect(
30
- `${oauthUrl}/${type}?${qs.stringify({
29
+ `${oauthUrl}/${type}?${new URLSearchParams({
31
30
  redirect: redirectUrl,
32
31
  state: this.ctx.state.token,
33
- })}`
32
+ }).toString()}`
34
33
  );
35
34
  }
36
35
 
@@ -41,23 +40,26 @@ module.exports = class extends think.Controller {
41
40
 
42
41
  if (type === 'facebook') {
43
42
  const { serverURL } = this.ctx;
44
- const redirectUrl = `${serverURL}/oauth?${qs.stringify({
43
+ const redirectUrl = `${serverURL}/oauth?${new URLSearchParams({
45
44
  redirect,
46
45
  type,
47
- })}`;
46
+ }).toString()}`;
48
47
 
49
- params.state = qs.stringify({
48
+ params.state = new URLSearchParams({
50
49
  redirect: redirectUrl,
51
50
  state: this.ctx.state.token || '',
52
51
  });
53
52
  }
54
53
 
55
- const user = await fetch(`${oauthUrl}/${type}?${qs.stringify(params)}`, {
56
- method: 'GET',
57
- headers: {
58
- 'user-agent': '@waline',
59
- },
60
- }).then((resp) => resp.json());
54
+ const user = await fetch(
55
+ `${oauthUrl}/${type}?${new URLSearchParams(params).toString()}`,
56
+ {
57
+ method: 'GET',
58
+ headers: {
59
+ 'user-agent': '@waline',
60
+ },
61
+ }
62
+ ).then((resp) => resp.json());
61
63
 
62
64
  if (!user || !user.id) {
63
65
  return this.fail(user);
@@ -1,4 +1,3 @@
1
- const qs = require('querystring');
2
1
  const { PasswordHash } = require('phpass');
3
2
  const BaseRest = require('./rest');
4
3
 
@@ -82,7 +81,7 @@ module.exports = class extends BaseRest {
82
81
  const apiUrl =
83
82
  this.ctx.serverURL +
84
83
  '/verification?' +
85
- qs.stringify({ token, email: data.email });
84
+ new URLSearchParams({ token, email: data.email }).toString();
86
85
 
87
86
  await notify.transporter.sendMail({
88
87
  from:
@@ -1,18 +1,7 @@
1
1
  const Base = require('./base');
2
2
 
3
3
  module.exports = class extends Base {
4
- async __before() {
5
- await super.__before();
6
-
7
- const { type, path } = this.get();
8
- const { like } = this.post();
9
- const isAllowedGet = this.isGet && (type !== 'list' || path);
10
- const isAllowedPut = this.ctx.isMethod('PUT') && think.isBoolean(like);
11
-
12
- if (this.isPost || isAllowedGet || isAllowedPut) {
13
- return;
14
- }
15
-
4
+ checkAdmin() {
16
5
  const { userInfo } = this.ctx.state;
17
6
 
18
7
  if (think.isEmpty(userInfo)) {
@@ -32,6 +21,7 @@ module.exports = class extends Base {
32
21
  * @apiParam {String} path comment url path
33
22
  * @apiParam {String} page page
34
23
  * @apiParam {String} pagesize page size
24
+ * @apiParam {String} sortBy comment sort type, one of 'insertedAt_desc', 'insertedAt_asc', 'like_desc'
35
25
  *
36
26
  * @apiSuccess (200) {Number} page return current comments list page
37
27
  * @apiSuccess (200) {Number} pageSize to return error message if error
@@ -115,7 +105,11 @@ module.exports = class extends Base {
115
105
  * @apiSuccess (200) {String} response.type comment login user type
116
106
  */
117
107
  getAction() {
118
- const { type } = this.get();
108
+ const { type, path } = this.get();
109
+ const isAllowedGet = type !== 'list' || path;
110
+ if (!isAllowedGet) {
111
+ this.checkAdmin();
112
+ }
119
113
 
120
114
  switch (type) {
121
115
  case 'recent':
@@ -168,6 +162,10 @@ module.exports = class extends Base {
168
162
  int: { max: 100 },
169
163
  default: 10,
170
164
  },
165
+ sortBy: {
166
+ in: ['insertedAt_desc', 'insertedAt_asc', 'like_desc'],
167
+ default: 'insertedAt_desc',
168
+ },
171
169
  };
172
170
  break;
173
171
  }
@@ -225,17 +223,41 @@ module.exports = class extends Base {
225
223
  * @apiSuccess (200) {Number} errno 0
226
224
  * @apiSuccess (200) {String} errmsg return error message if error
227
225
  */
228
- putAction() {
226
+ async putAction() {
229
227
  const { userInfo } = this.ctx.state;
228
+ const { like } = this.post();
230
229
 
231
- if (think.isEmpty(userInfo) || userInfo.type !== 'administrator') {
230
+ // 1. like
231
+ if (think.isEmpty(userInfo) && think.isBoolean(like)) {
232
232
  this.rules = {
233
233
  like: {
234
234
  required: true,
235
235
  boolean: true,
236
236
  },
237
237
  };
238
+ return;
239
+ }
240
+
241
+ if (think.isEmpty(userInfo)) {
242
+ return this.ctx.throw(401);
243
+ }
244
+
245
+ // 2. administrator
246
+ if (userInfo.type === 'administrator') {
247
+ return;
248
+ }
249
+
250
+ // 3. comment author modify comment content
251
+ const modelInstance = this.service(
252
+ `storage/${this.config('storage')}`,
253
+ 'Comment'
254
+ );
255
+ const commentData = await modelInstance.select({ user_id: userInfo.objectId, objectId: this.id });
256
+ if (!think.isEmpty(commentData)) {
257
+ return;
238
258
  }
259
+
260
+ return this.ctx.throw(403);
239
261
  }
240
262
 
241
263
  /**
@@ -246,5 +268,25 @@ module.exports = class extends Base {
246
268
  * @apiSuccess (200) {Number} errno 0
247
269
  * @apiSuccess (200) {String} errmsg return error message if error
248
270
  */
249
- deleteAction() {}
271
+ async deleteAction() {
272
+ const { userInfo } = this.ctx.state;
273
+
274
+ if (think.isEmpty(userInfo)) {
275
+ return this.ctx.throw(401);
276
+ }
277
+
278
+ if (userInfo.type === 'administrator') {
279
+ return;
280
+ }
281
+
282
+ const modelInstance = this.service(
283
+ `storage/${this.config('storage')}`,
284
+ 'Comment'
285
+ );
286
+ const commentData = await modelInstance.select({ user_id: userInfo.objectId, objectId: this.id });
287
+ if (!think.isEmpty(commentData)) {
288
+ return;
289
+ }
290
+ return this.ctx.throw(403);
291
+ }
250
292
  };
@@ -44,7 +44,7 @@ module.exports = class extends Base {
44
44
 
45
45
  instance.where(this.parseWhere(where));
46
46
  if (desc) {
47
- instance.order(`${desc} DESC`);
47
+ instance.order(`"${desc}" DESC`);
48
48
  }
49
49
  if (limit || offset) {
50
50
  instance.limit(offset || 0, limit);
@@ -67,9 +67,9 @@ module.exports = class extends Base {
67
67
  return instance.count();
68
68
  }
69
69
 
70
- instance.field([...group, 'COUNT(*) as count']);
70
+ instance.field([...group, 'COUNT(*) as count'].join(','));
71
71
  instance.group(group);
72
-
72
+
73
73
  return instance.select();
74
74
  }
75
75