@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 +1 -1
- package/src/controller/comment.js +43 -39
- package/src/controller/oauth.js +16 -14
- package/src/controller/user.js +1 -2
- package/src/logic/comment.js +58 -16
- package/src/service/storage/mysql.js +3 -3
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ const { getMarkdownParser } = require('../service/markdown');
|
|
|
6
6
|
const markdownParser = getMarkdownParser();
|
|
7
7
|
|
|
8
8
|
async function formatCmt(
|
|
9
|
-
{ ua,
|
|
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
|
-
'
|
|
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
|
-
|
|
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.
|
|
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
|
-
'
|
|
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() {
|
package/src/controller/oauth.js
CHANGED
|
@@ -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?${
|
|
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}?${
|
|
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?${
|
|
43
|
+
const redirectUrl = `${serverURL}/oauth?${new URLSearchParams({
|
|
45
44
|
redirect,
|
|
46
45
|
type,
|
|
47
|
-
})}`;
|
|
46
|
+
}).toString()}`;
|
|
48
47
|
|
|
49
|
-
params.state =
|
|
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(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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);
|
package/src/controller/user.js
CHANGED
|
@@ -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
|
-
|
|
84
|
+
new URLSearchParams({ token, email: data.email }).toString();
|
|
86
85
|
|
|
87
86
|
await notify.transporter.sendMail({
|
|
88
87
|
from:
|
package/src/logic/comment.js
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
const Base = require('./base');
|
|
2
2
|
|
|
3
3
|
module.exports = class extends Base {
|
|
4
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|