@waline/vercel 1.36.4 → 1.36.5
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/__tests__/xss.spec.js +8 -19
- package/package.json +16 -17
- package/src/config/adapter.js +2 -7
- package/src/config/config.js +2 -10
- package/src/config/extend.js +0 -6
- package/src/config/middleware.js +2 -5
- package/src/controller/article.js +3 -10
- package/src/controller/comment.js +14 -37
- package/src/controller/db.js +3 -9
- package/src/controller/oauth.js +2 -5
- package/src/controller/user/password.js +3 -12
- package/src/controller/user.js +10 -38
- package/src/extend/think.js +2 -6
- package/src/logic/base.js +7 -25
- package/src/service/avatar.js +1 -3
- package/src/service/markdown/mathCommon.js +2 -8
- package/src/service/markdown/mathjax.js +1 -2
- package/src/service/notify.js +66 -92
- package/src/service/storage/base.js +1 -6
- package/src/service/storage/github.js +15 -24
- package/src/service/storage/leancloud.js +13 -33
- package/src/service/storage/mongodb.js +1 -2
- package/src/service/storage/mysql.js +3 -9
- package/src/service/storage/postgresql.js +2 -6
- package/src/service/storage/deta.js +0 -310
package/__tests__/xss.spec.js
CHANGED
|
@@ -3,8 +3,7 @@ import { describe, expect, it } from 'vitest';
|
|
|
3
3
|
|
|
4
4
|
import { sanitize } from '../src/service/markdown/xss';
|
|
5
5
|
|
|
6
|
-
const parser = (content) =>
|
|
7
|
-
sanitize(new MarkdownIt({ html: true }).render(content));
|
|
6
|
+
const parser = (content) => sanitize(new MarkdownIt({ html: true }).render(content));
|
|
8
7
|
|
|
9
8
|
describe('XSS test', () => {
|
|
10
9
|
it('Should render', () => {
|
|
@@ -36,20 +35,16 @@ Waline is a good framework. :money:
|
|
|
36
35
|
});
|
|
37
36
|
|
|
38
37
|
it('Should protect', () => {
|
|
39
|
-
expect(parser(`<img src="x" onerror="alert('img')">`)).toEqual(
|
|
40
|
-
'<img src="x">',
|
|
41
|
-
);
|
|
38
|
+
expect(parser(`<img src="x" onerror="alert('img')">`)).toEqual('<img src="x">');
|
|
42
39
|
expect(parser('<script>alert("hello world")</script>')).toEqual('');
|
|
43
40
|
|
|
44
41
|
expect(
|
|
45
|
-
parser(
|
|
46
|
-
'<p>Waline is <iframe//src=jaVa	script:alert(3)></iframe>awesome</p>',
|
|
47
|
-
),
|
|
42
|
+
parser('<p>Waline is <iframe//src=jaVa	script:alert(3)></iframe>awesome</p>'),
|
|
48
43
|
).toEqual('<p>Waline is awesome</p>');
|
|
49
44
|
|
|
50
|
-
expect(
|
|
51
|
-
|
|
52
|
-
)
|
|
45
|
+
expect(parser('<p>Waline is <iframe//src=jaVa	script:alert(3)>awesome</p>')).toEqual(
|
|
46
|
+
'<p>Waline is </p>',
|
|
47
|
+
);
|
|
53
48
|
});
|
|
54
49
|
|
|
55
50
|
it('Should resolve unmatching html tags', () => {
|
|
@@ -78,11 +73,7 @@ Waline is a good framework. :money:
|
|
|
78
73
|
expect(parser('[link](https://example.com)')).toEqual(
|
|
79
74
|
'<p><a href="https://example.com" target="_blank" rel="nofollow noreferrer noopener">link</a></p>\n',
|
|
80
75
|
);
|
|
81
|
-
expect(
|
|
82
|
-
parser(
|
|
83
|
-
'<p><a href="https://example.com" rel="opener prefetch">link</a></p>',
|
|
84
|
-
),
|
|
85
|
-
).toEqual(
|
|
76
|
+
expect(parser('<p><a href="https://example.com" rel="opener prefetch">link</a></p>')).toEqual(
|
|
86
77
|
'<p><a href="https://example.com" rel="nofollow noreferrer noopener" target="_blank">link</a></p>',
|
|
87
78
|
);
|
|
88
79
|
});
|
|
@@ -94,9 +85,7 @@ Waline is a good framework. :money:
|
|
|
94
85
|
|
|
95
86
|
it('Should forbid style', () => {
|
|
96
87
|
expect(
|
|
97
|
-
parser(
|
|
98
|
-
'<div style="position:fixed;top:0;left:0;width:100vh;height:100vh;">广告文字</div>',
|
|
99
|
-
),
|
|
88
|
+
parser('<div style="position:fixed;top:0;left:0;width:100vh;height:100vh;">广告文字</div>'),
|
|
100
89
|
).toEqual('<div>广告文字</div>');
|
|
101
90
|
expect(
|
|
102
91
|
parser(
|
package/package.json
CHANGED
|
@@ -1,43 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waline/vercel",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.5",
|
|
4
4
|
"description": "vercel server for waline comment system",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"vercel",
|
|
6
|
+
"blog",
|
|
8
7
|
"comment",
|
|
9
|
-
"
|
|
8
|
+
"vercel",
|
|
9
|
+
"waline"
|
|
10
10
|
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "lizheming <i@imnerd.org>",
|
|
11
13
|
"repository": {
|
|
12
14
|
"url": "https://github.com/walinejs/waline",
|
|
13
15
|
"directory": "packages/server"
|
|
14
16
|
},
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"provenance": true
|
|
19
|
+
},
|
|
17
20
|
"scripts": {
|
|
18
21
|
"dev": "node development.js 9090"
|
|
19
22
|
},
|
|
20
23
|
"dependencies": {
|
|
21
|
-
"@cloudbase/node-sdk": "^3.
|
|
24
|
+
"@cloudbase/node-sdk": "^3.18.0",
|
|
22
25
|
"@koa/cors": "^5.0.0",
|
|
23
26
|
"@mdit/plugin-katex": "0.23.4-cjs.0",
|
|
24
27
|
"@mdit/plugin-mathjax": "0.23.4-cjs.0",
|
|
25
28
|
"@mdit/plugin-sub": "0.22.5-cjs.0",
|
|
26
29
|
"@mdit/plugin-sup": "0.22.5-cjs.0",
|
|
27
30
|
"akismet": "^2.0.7",
|
|
28
|
-
"
|
|
29
|
-
"dompurify": "^3.3.0",
|
|
31
|
+
"dompurify": "^3.3.1",
|
|
30
32
|
"dy-node-ip2region": "^1.0.1",
|
|
31
33
|
"fast-csv": "^5.0.5",
|
|
32
34
|
"form-data": "^4.0.5",
|
|
33
35
|
"jsdom": "^19.0.0",
|
|
34
|
-
"jsonwebtoken": "^9.0.
|
|
36
|
+
"jsonwebtoken": "^9.0.3",
|
|
35
37
|
"koa-compose": "^4.1.0",
|
|
36
38
|
"leancloud-storage": "^4.15.2",
|
|
37
|
-
"markdown-it": "^14.1.
|
|
39
|
+
"markdown-it": "^14.1.1",
|
|
38
40
|
"markdown-it-emoji": "^3.0.0",
|
|
39
41
|
"mathjax-full": "^3.2.2",
|
|
40
|
-
"nodemailer": "^
|
|
42
|
+
"nodemailer": "^8.0.1",
|
|
41
43
|
"nunjucks": "^3.2.4",
|
|
42
44
|
"phpass": "^0.1.1",
|
|
43
45
|
"prismjs": "^1.30.0",
|
|
@@ -52,16 +54,13 @@
|
|
|
52
54
|
"think-mongo": "^2.2.1",
|
|
53
55
|
"think-router-rest": "^1.0.5",
|
|
54
56
|
"thinkjs": "4.0.0-alpha.0",
|
|
55
|
-
"ua-parser-js": "^2.0.
|
|
57
|
+
"ua-parser-js": "^2.0.9"
|
|
56
58
|
},
|
|
57
59
|
"devDependencies": {
|
|
58
|
-
"dotenv": "17.2.
|
|
60
|
+
"dotenv": "17.2.4",
|
|
59
61
|
"think-watcher": "3.0.4"
|
|
60
62
|
},
|
|
61
63
|
"engines": {
|
|
62
64
|
"node": ">=20"
|
|
63
|
-
},
|
|
64
|
-
"publishConfig": {
|
|
65
|
-
"provenance": true
|
|
66
65
|
}
|
|
67
66
|
}
|
package/src/config/adapter.js
CHANGED
|
@@ -97,11 +97,7 @@ exports.model = {
|
|
|
97
97
|
? JSON.parse(MONGO_HOST)
|
|
98
98
|
: MONGO_HOST
|
|
99
99
|
: '127.0.0.1',
|
|
100
|
-
port: MONGO_PORT
|
|
101
|
-
? MONGO_PORT.startsWith('[')
|
|
102
|
-
? JSON.parse(MONGO_PORT)
|
|
103
|
-
: MONGO_PORT
|
|
104
|
-
: 27017,
|
|
100
|
+
port: MONGO_PORT ? (MONGO_PORT.startsWith('[') ? JSON.parse(MONGO_PORT) : MONGO_PORT) : 27017,
|
|
105
101
|
user: MONGO_USER,
|
|
106
102
|
password: MONGO_PASSWORD,
|
|
107
103
|
database: MONGO_DB,
|
|
@@ -118,8 +114,7 @@ exports.model = {
|
|
|
118
114
|
connectionLimit: 1,
|
|
119
115
|
prefix: PG_PREFIX || POSTGRES_PREFIX || 'wl_',
|
|
120
116
|
ssl:
|
|
121
|
-
(PG_SSL || POSTGRES_SSL) == 'true' ||
|
|
122
|
-
POSTGRES_URL?.includes('sslmode=require')
|
|
117
|
+
(PG_SSL || POSTGRES_SSL) == 'true' || POSTGRES_URL?.includes('sslmode=require')
|
|
123
118
|
? {
|
|
124
119
|
rejectUnauthorized: false,
|
|
125
120
|
}
|
package/src/config/config.js
CHANGED
|
@@ -21,7 +21,6 @@ const {
|
|
|
21
21
|
DISABLE_REGION,
|
|
22
22
|
AVATAR_PROXY,
|
|
23
23
|
GITHUB_TOKEN,
|
|
24
|
-
DETA_PROJECT_KEY,
|
|
25
24
|
OAUTH_URL,
|
|
26
25
|
|
|
27
26
|
MARKDOWN_CONFIG = '{}',
|
|
@@ -74,9 +73,6 @@ if (LEAN_KEY) {
|
|
|
74
73
|
} else if (think.env === 'cloudbase' || TCB_ENV) {
|
|
75
74
|
storage = 'cloudbase';
|
|
76
75
|
jwtKey = jwtKey || TENCENTCLOUD_SECRETKEY || TCB_KEY || TCB_ENV;
|
|
77
|
-
} else if (DETA_PROJECT_KEY) {
|
|
78
|
-
storage = 'deta';
|
|
79
|
-
jwtKey = jwtKey || DETA_PROJECT_KEY;
|
|
80
76
|
}
|
|
81
77
|
|
|
82
78
|
if (think.env === 'cloudbase' && storage === 'sqlite') {
|
|
@@ -85,8 +81,7 @@ if (think.env === 'cloudbase' && storage === 'sqlite') {
|
|
|
85
81
|
|
|
86
82
|
const forbiddenWords = FORBIDDEN_WORDS ? FORBIDDEN_WORDS.split(/\s*,\s*/) : [];
|
|
87
83
|
|
|
88
|
-
const isFalse = (content) =>
|
|
89
|
-
content && ['0', 'false'].includes(content.toLowerCase());
|
|
84
|
+
const isFalse = (content) => content && ['0', 'false'].includes(content.toLowerCase());
|
|
90
85
|
|
|
91
86
|
const markdown = {
|
|
92
87
|
config: JSON.parse(MARKDOWN_CONFIG),
|
|
@@ -119,10 +114,7 @@ module.exports = {
|
|
|
119
114
|
secureDomains: SECURE_DOMAINS ? SECURE_DOMAINS.split(/\s*,\s*/) : undefined,
|
|
120
115
|
disableUserAgent: DISABLE_USERAGENT && !isFalse(DISABLE_USERAGENT),
|
|
121
116
|
disableRegion: DISABLE_REGION && !isFalse(DISABLE_REGION),
|
|
122
|
-
levels:
|
|
123
|
-
!LEVELS || isFalse(LEVELS)
|
|
124
|
-
? false
|
|
125
|
-
: LEVELS.split(/\s*,\s*/).map((v) => Number(v)),
|
|
117
|
+
levels: !LEVELS || isFalse(LEVELS) ? false : LEVELS.split(/\s*,\s*/).map((v) => Number(v)),
|
|
126
118
|
|
|
127
119
|
audit: COMMENT_AUDIT && !isFalse(COMMENT_AUDIT),
|
|
128
120
|
avatarProxy,
|
package/src/config/extend.js
CHANGED
|
@@ -3,8 +3,6 @@ const Mongo = require('think-mongo');
|
|
|
3
3
|
|
|
4
4
|
const { isNetlify, netlifyFunctionPrefix } = require('./netlify');
|
|
5
5
|
|
|
6
|
-
const isDeta = think.env === 'deta' || process.env.DETA_RUNTIME === 'true';
|
|
7
|
-
|
|
8
6
|
module.exports = [
|
|
9
7
|
Model(think.app),
|
|
10
8
|
Mongo(think.app),
|
|
@@ -23,10 +21,6 @@ module.exports = [
|
|
|
23
21
|
return `${protocol}://${host}${netlifyFunctionPrefix}`;
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
if (isDeta) {
|
|
27
|
-
return `https://${host}`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
24
|
return `${protocol}://${host}`;
|
|
31
25
|
},
|
|
32
26
|
async webhook(type, data) {
|
package/src/config/middleware.js
CHANGED
|
@@ -5,9 +5,7 @@ const { isNetlify, netlifyFunctionPrefix } = require('./netlify.js');
|
|
|
5
5
|
|
|
6
6
|
const isDev = think.env === 'development';
|
|
7
7
|
const isTcb = think.env === 'cloudbase';
|
|
8
|
-
const
|
|
9
|
-
const isAliyunFC =
|
|
10
|
-
think.env === 'aliyun-fc' || Boolean(process.env.FC_RUNTIME_VERSION);
|
|
8
|
+
const isAliyunFC = think.env === 'aliyun-fc' || Boolean(process.env.FC_RUNTIME_VERSION);
|
|
11
9
|
|
|
12
10
|
module.exports = [
|
|
13
11
|
{
|
|
@@ -26,8 +24,7 @@ module.exports = [
|
|
|
26
24
|
options: {
|
|
27
25
|
logRequest: isDev,
|
|
28
26
|
sendResponseTime: isDev,
|
|
29
|
-
requestTimeoutCallback:
|
|
30
|
-
isTcb || isDeta || isAliyunFC || isNetlify ? false : () => {},
|
|
27
|
+
requestTimeoutCallback: isTcb || isAliyunFC || isNetlify ? false : () => {},
|
|
31
28
|
},
|
|
32
29
|
},
|
|
33
30
|
|
|
@@ -38,9 +38,7 @@ module.exports = class extends BaseRest {
|
|
|
38
38
|
// - single path and multiple type: [{[type]: 0}]
|
|
39
39
|
// - multiple path and single type: [{[type]: 0}]
|
|
40
40
|
// - multiple path and multiple type: [{[type]: 0}]
|
|
41
|
-
return this.jsonOrSuccess(
|
|
42
|
-
path.length === 1 && deprecated ? counters[0] : counters,
|
|
43
|
-
);
|
|
41
|
+
return this.jsonOrSuccess(path.length === 1 && deprecated ? counters[0] : counters);
|
|
44
42
|
}
|
|
45
43
|
|
|
46
44
|
const respObj = resp.reduce((o, n) => {
|
|
@@ -89,17 +87,12 @@ module.exports = class extends BaseRest {
|
|
|
89
87
|
|
|
90
88
|
const ret = await this.modelInstance.update(
|
|
91
89
|
(counter) => ({
|
|
92
|
-
[type]:
|
|
93
|
-
action === 'desc'
|
|
94
|
-
? (counter[type] || 1) - 1
|
|
95
|
-
: (counter[type] || 0) + 1,
|
|
90
|
+
[type]: action === 'desc' ? (counter[type] || 1) - 1 : (counter[type] || 0) + 1,
|
|
96
91
|
updatedAt: new Date(),
|
|
97
92
|
}),
|
|
98
93
|
{ objectId: ['IN', resp.map(({ objectId }) => objectId)] },
|
|
99
94
|
);
|
|
100
95
|
|
|
101
|
-
return this.jsonOrSuccess(
|
|
102
|
-
deprecated ? ret[0][type] : [{ [type]: ret[0][type] }],
|
|
103
|
-
);
|
|
96
|
+
return this.jsonOrSuccess(deprecated ? ret[0][type] : [{ [type]: ret[0][type] }]);
|
|
104
97
|
}
|
|
105
98
|
};
|
|
@@ -29,9 +29,7 @@ async function formatCmt(
|
|
|
29
29
|
comment.label = user.label;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const avatarUrl = user?.avatar
|
|
33
|
-
? user.avatar
|
|
34
|
-
: await think.service('avatar').stringify(comment);
|
|
32
|
+
const avatarUrl = user?.avatar ? user.avatar : await think.service('avatar').stringify(comment);
|
|
35
33
|
|
|
36
34
|
comment.avatar =
|
|
37
35
|
avatarProxy && !avatarUrl.includes(avatarProxy)
|
|
@@ -144,9 +142,7 @@ module.exports = class extends BaseRest {
|
|
|
144
142
|
});
|
|
145
143
|
|
|
146
144
|
if (!think.isEmpty(duplicate)) {
|
|
147
|
-
think.logger.debug(
|
|
148
|
-
'The comment author had post same comment content before',
|
|
149
|
-
);
|
|
145
|
+
think.logger.debug('The comment author had post same comment content before');
|
|
150
146
|
|
|
151
147
|
return this.fail(this.locale('Duplicate Content'));
|
|
152
148
|
}
|
|
@@ -175,9 +171,7 @@ module.exports = class extends BaseRest {
|
|
|
175
171
|
think.logger.debug(`Comment initial status is ${data.status}`);
|
|
176
172
|
|
|
177
173
|
if (data.status === 'approved') {
|
|
178
|
-
const spam = await akismet(data, this.ctx.serverURL).catch((err) =>
|
|
179
|
-
console.log(err),
|
|
180
|
-
); // ignore akismet error
|
|
174
|
+
const spam = await akismet(data, this.ctx.serverURL).catch((err) => console.log(err)); // ignore akismet error
|
|
181
175
|
|
|
182
176
|
if (spam === true) {
|
|
183
177
|
data.status = 'spam';
|
|
@@ -255,9 +249,7 @@ module.exports = class extends BaseRest {
|
|
|
255
249
|
|
|
256
250
|
await notify.run(
|
|
257
251
|
{ ...cmtReturn, mail: resp.mail, rawComment: comment },
|
|
258
|
-
parentReturn
|
|
259
|
-
? { ...parentReturn, mail: parentComment.mail }
|
|
260
|
-
: undefined,
|
|
252
|
+
parentReturn ? { ...parentReturn, mail: parentComment.mail } : undefined,
|
|
261
253
|
);
|
|
262
254
|
}
|
|
263
255
|
|
|
@@ -292,8 +284,7 @@ module.exports = class extends BaseRest {
|
|
|
292
284
|
const likeIncMax = this.config('LIKE_INC_MAX') || 1;
|
|
293
285
|
|
|
294
286
|
data.like =
|
|
295
|
-
(Number(oldData.like) || 0) +
|
|
296
|
-
(data.like ? Math.ceil(Math.random() * likeIncMax) : -1);
|
|
287
|
+
(Number(oldData.like) || 0) + (data.like ? Math.ceil(Math.random() * likeIncMax) : -1);
|
|
297
288
|
data.like = Math.max(data.like, 0);
|
|
298
289
|
}
|
|
299
290
|
|
|
@@ -325,11 +316,7 @@ module.exports = class extends BaseRest {
|
|
|
325
316
|
userInfo,
|
|
326
317
|
);
|
|
327
318
|
|
|
328
|
-
if (
|
|
329
|
-
oldData.status === 'waiting' &&
|
|
330
|
-
data.status === 'approved' &&
|
|
331
|
-
oldData.pid
|
|
332
|
-
) {
|
|
319
|
+
if (oldData.status === 'waiting' && data.status === 'approved' && oldData.pid) {
|
|
333
320
|
let pComment = await this.modelInstance.select({
|
|
334
321
|
objectId: oldData.pid,
|
|
335
322
|
});
|
|
@@ -390,7 +377,7 @@ module.exports = class extends BaseRest {
|
|
|
390
377
|
const { path: url, page, pageSize, sortBy } = this.get();
|
|
391
378
|
const where = { url };
|
|
392
379
|
|
|
393
|
-
if (think.isEmpty(userInfo)
|
|
380
|
+
if (think.isEmpty(userInfo)) {
|
|
394
381
|
where.status = ['NOT IN', ['waiting', 'spam']];
|
|
395
382
|
} else if (userInfo.type !== 'administrator') {
|
|
396
383
|
where._complex = {
|
|
@@ -462,9 +449,7 @@ module.exports = class extends BaseRest {
|
|
|
462
449
|
rootComments.forEach(({ objectId }) => {
|
|
463
450
|
rootIds[objectId] = true;
|
|
464
451
|
});
|
|
465
|
-
comments = comments.filter(
|
|
466
|
-
(cmt) => rootIds[cmt.objectId] || rootIds[cmt.rid],
|
|
467
|
-
);
|
|
452
|
+
comments = comments.filter((cmt) => rootIds[cmt.objectId] || rootIds[cmt.rid]);
|
|
468
453
|
} else {
|
|
469
454
|
comments = await this.modelInstance.select(
|
|
470
455
|
{ ...where, rid: undefined },
|
|
@@ -488,9 +473,7 @@ module.exports = class extends BaseRest {
|
|
|
488
473
|
}
|
|
489
474
|
|
|
490
475
|
const userModel = this.getModel('Users');
|
|
491
|
-
const user_ids = Array.from(
|
|
492
|
-
new Set(comments.map(({ user_id }) => user_id).filter((v) => v)),
|
|
493
|
-
);
|
|
476
|
+
const user_ids = Array.from(new Set(comments.map(({ user_id }) => user_id).filter((v) => v)));
|
|
494
477
|
let users = [];
|
|
495
478
|
|
|
496
479
|
if (user_ids.length) {
|
|
@@ -511,9 +494,7 @@ module.exports = class extends BaseRest {
|
|
|
511
494
|
if (user_ids.length) {
|
|
512
495
|
countWhere._complex.user_id = ['IN', user_ids];
|
|
513
496
|
}
|
|
514
|
-
const mails = Array.from(
|
|
515
|
-
new Set(comments.map(({ mail }) => mail).filter((v) => v)),
|
|
516
|
-
);
|
|
497
|
+
const mails = Array.from(new Set(comments.map(({ mail }) => mail).filter((v) => v)));
|
|
517
498
|
|
|
518
499
|
if (mails.length) {
|
|
519
500
|
countWhere._complex.mail = ['IN', mails];
|
|
@@ -629,9 +610,7 @@ module.exports = class extends BaseRest {
|
|
|
629
610
|
});
|
|
630
611
|
|
|
631
612
|
const userModel = this.getModel('Users');
|
|
632
|
-
const user_ids = Array.from(
|
|
633
|
-
new Set(comments.map(({ user_id }) => user_id).filter((v) => v)),
|
|
634
|
-
);
|
|
613
|
+
const user_ids = Array.from(new Set(comments.map(({ user_id }) => user_id).filter((v) => v)));
|
|
635
614
|
|
|
636
615
|
let users = [];
|
|
637
616
|
|
|
@@ -668,7 +647,7 @@ module.exports = class extends BaseRest {
|
|
|
668
647
|
const { userInfo } = this.ctx.state;
|
|
669
648
|
const where = {};
|
|
670
649
|
|
|
671
|
-
if (think.isEmpty(userInfo)
|
|
650
|
+
if (think.isEmpty(userInfo)) {
|
|
672
651
|
where.status = ['NOT IN', ['waiting', 'spam']];
|
|
673
652
|
} else {
|
|
674
653
|
where._complex = {
|
|
@@ -700,9 +679,7 @@ module.exports = class extends BaseRest {
|
|
|
700
679
|
});
|
|
701
680
|
|
|
702
681
|
const userModel = this.getModel('Users');
|
|
703
|
-
const user_ids = Array.from(
|
|
704
|
-
new Set(comments.map(({ user_id }) => user_id).filter((v) => v)),
|
|
705
|
-
);
|
|
682
|
+
const user_ids = Array.from(new Set(comments.map(({ user_id }) => user_id).filter((v) => v)));
|
|
706
683
|
|
|
707
684
|
let users = [];
|
|
708
685
|
|
|
@@ -732,7 +709,7 @@ module.exports = class extends BaseRest {
|
|
|
732
709
|
const { userInfo } = this.ctx.state;
|
|
733
710
|
const where = Array.isArray(url) && url.length ? { url: ['IN', url] } : {};
|
|
734
711
|
|
|
735
|
-
if (think.isEmpty(userInfo)
|
|
712
|
+
if (think.isEmpty(userInfo)) {
|
|
736
713
|
where.status = ['NOT IN', ['waiting', 'spam']];
|
|
737
714
|
} else {
|
|
738
715
|
where._complex = {
|
package/src/controller/db.js
CHANGED
|
@@ -38,15 +38,9 @@ module.exports = class extends BaseRest {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
if (storage === 'mysql') {
|
|
41
|
-
if (item.insertedAt)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'YYYY-MM-DD HH:mm:ss',
|
|
45
|
-
);
|
|
46
|
-
if (item.createdAt)
|
|
47
|
-
item.createdAt = think.datetime(item.createdAt, 'YYYY-MM-DD HH:mm:ss');
|
|
48
|
-
if (item.updatedAt)
|
|
49
|
-
item.updatedAt = think.datetime(item.updatedAt, 'YYYY-MM-DD HH:mm:ss');
|
|
41
|
+
if (item.insertedAt) item.insertedAt = think.datetime(item.insertedAt, 'YYYY-MM-DD HH:mm:ss');
|
|
42
|
+
if (item.createdAt) item.createdAt = think.datetime(item.createdAt, 'YYYY-MM-DD HH:mm:ss');
|
|
43
|
+
if (item.updatedAt) item.updatedAt = think.datetime(item.updatedAt, 'YYYY-MM-DD HH:mm:ss');
|
|
50
44
|
}
|
|
51
45
|
|
|
52
46
|
delete item.objectId;
|
package/src/controller/oauth.js
CHANGED
|
@@ -10,8 +10,7 @@ module.exports = class extends think.Controller {
|
|
|
10
10
|
const { code, oauth_verifier, oauth_token, type, redirect } = this.get();
|
|
11
11
|
const { oauthUrl } = this.config();
|
|
12
12
|
|
|
13
|
-
const hasCode =
|
|
14
|
-
type === 'twitter' ? oauth_token && oauth_verifier : Boolean(code);
|
|
13
|
+
const hasCode = type === 'twitter' ? oauth_token && oauth_verifier : Boolean(code);
|
|
15
14
|
|
|
16
15
|
if (!hasCode) {
|
|
17
16
|
const { serverURL } = this.ctx;
|
|
@@ -109,8 +108,6 @@ module.exports = class extends think.Controller {
|
|
|
109
108
|
// and then generate token!
|
|
110
109
|
const token = jwt.sign(user.objectId, this.config('jwtKey'));
|
|
111
110
|
|
|
112
|
-
return this.redirect(
|
|
113
|
-
redirect + (redirect.includes('?') ? '&' : '?') + 'token=' + token,
|
|
114
|
-
);
|
|
111
|
+
return this.redirect(redirect + (redirect.includes('?') ? '&' : '?') + 'token=' + token);
|
|
115
112
|
}
|
|
116
113
|
};
|
|
@@ -4,14 +4,8 @@ const BaseRest = require('../rest.js');
|
|
|
4
4
|
|
|
5
5
|
module.exports = class extends BaseRest {
|
|
6
6
|
async putAction() {
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
-
SMTP_SERVICE,
|
|
10
|
-
SENDER_EMAIL,
|
|
11
|
-
SENDER_NAME,
|
|
12
|
-
SMTP_USER,
|
|
13
|
-
SITE_NAME,
|
|
14
|
-
} = process.env;
|
|
7
|
+
const { SMTP_HOST, SMTP_SERVICE, SENDER_EMAIL, SENDER_NAME, SMTP_USER, SITE_NAME } =
|
|
8
|
+
process.env;
|
|
15
9
|
const hasMailService = SMTP_HOST || SMTP_SERVICE;
|
|
16
10
|
|
|
17
11
|
if (!hasMailService) {
|
|
@@ -31,10 +25,7 @@ module.exports = class extends BaseRest {
|
|
|
31
25
|
const profileUrl = `${this.ctx.serverURL}/ui/profile?token=${token}`;
|
|
32
26
|
|
|
33
27
|
await notify.transporter.sendMail({
|
|
34
|
-
from:
|
|
35
|
-
SENDER_EMAIL && SENDER_NAME
|
|
36
|
-
? `"${SENDER_NAME}" <${SENDER_EMAIL}>`
|
|
37
|
-
: SMTP_USER,
|
|
28
|
+
from: SENDER_EMAIL && SENDER_NAME ? `"${SENDER_NAME}" <${SENDER_EMAIL}>` : SMTP_USER,
|
|
38
29
|
to: user[0].email,
|
|
39
30
|
subject: this.locale('[{{name | safe}}] Reset Password', {
|
|
40
31
|
name: SITE_NAME || 'Waline',
|
package/src/controller/user.js
CHANGED
|
@@ -50,28 +50,17 @@ module.exports = class extends BaseRest {
|
|
|
50
50
|
email: data.email,
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
if (
|
|
54
|
-
!think.isEmpty(resp) &&
|
|
55
|
-
['administrator', 'guest'].includes(resp[0].type)
|
|
56
|
-
) {
|
|
53
|
+
if (!think.isEmpty(resp) && ['administrator', 'guest'].includes(resp[0].type)) {
|
|
57
54
|
return this.fail(this.locale('USER_EXIST'));
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
const count = await this.modelInstance.count();
|
|
61
58
|
|
|
62
|
-
const {
|
|
63
|
-
|
|
64
|
-
SMTP_SERVICE,
|
|
65
|
-
SENDER_EMAIL,
|
|
66
|
-
SENDER_NAME,
|
|
67
|
-
SMTP_USER,
|
|
68
|
-
SITE_NAME,
|
|
69
|
-
} = process.env;
|
|
59
|
+
const { SMTP_HOST, SMTP_SERVICE, SENDER_EMAIL, SENDER_NAME, SMTP_USER, SITE_NAME } =
|
|
60
|
+
process.env;
|
|
70
61
|
const hasMailService = SMTP_HOST || SMTP_SERVICE;
|
|
71
62
|
|
|
72
|
-
const token = Array.from({ length: 4 }, () =>
|
|
73
|
-
Math.round(Math.random() * 9),
|
|
74
|
-
).join('');
|
|
63
|
+
const token = Array.from({ length: 4 }, () => Math.round(Math.random() * 9)).join('');
|
|
75
64
|
const normalType = hasMailService
|
|
76
65
|
? `verify:${token}:${Date.now() + 1 * 60 * 60 * 1000}`
|
|
77
66
|
: 'guest';
|
|
@@ -97,10 +86,7 @@ module.exports = class extends BaseRest {
|
|
|
97
86
|
});
|
|
98
87
|
|
|
99
88
|
await notify.transporter.sendMail({
|
|
100
|
-
from:
|
|
101
|
-
SENDER_EMAIL && SENDER_NAME
|
|
102
|
-
? `"${SENDER_NAME}" <${SENDER_EMAIL}>`
|
|
103
|
-
: SMTP_USER,
|
|
89
|
+
from: SENDER_EMAIL && SENDER_NAME ? `"${SENDER_NAME}" <${SENDER_EMAIL}>` : SMTP_USER,
|
|
104
90
|
to: data.email,
|
|
105
91
|
subject: this.locale('[{{name | safe}}] Registration Confirm Mail', {
|
|
106
92
|
name: SITE_NAME || 'Waline',
|
|
@@ -125,8 +111,7 @@ module.exports = class extends BaseRest {
|
|
|
125
111
|
}
|
|
126
112
|
|
|
127
113
|
async putAction() {
|
|
128
|
-
const { display_name, url, avatar, password, type, label, email } =
|
|
129
|
-
this.post();
|
|
114
|
+
const { display_name, url, avatar, password, type, label, email } = this.post();
|
|
130
115
|
const { objectId } = this.ctx.state.userInfo;
|
|
131
116
|
const twoFactorAuth = this.post('2fa');
|
|
132
117
|
|
|
@@ -209,9 +194,7 @@ module.exports = class extends BaseRest {
|
|
|
209
194
|
counts.sort((a, b) => b.count - a.count);
|
|
210
195
|
counts.length = Math.min(pageSize, counts.length);
|
|
211
196
|
|
|
212
|
-
const userIds = counts
|
|
213
|
-
.filter(({ user_id }) => user_id)
|
|
214
|
-
.map(({ user_id }) => user_id);
|
|
197
|
+
const userIds = counts.filter(({ user_id }) => user_id).map(({ user_id }) => user_id);
|
|
215
198
|
|
|
216
199
|
let usersMap = {};
|
|
217
200
|
|
|
@@ -237,10 +220,7 @@ module.exports = class extends BaseRest {
|
|
|
237
220
|
let level = 0;
|
|
238
221
|
|
|
239
222
|
if (user.count) {
|
|
240
|
-
const _level = think.findLastIndex(
|
|
241
|
-
this.config('levels'),
|
|
242
|
-
(l) => l <= user.count,
|
|
243
|
-
);
|
|
223
|
+
const _level = think.findLastIndex(this.config('levels'), (l) => l <= user.count);
|
|
244
224
|
|
|
245
225
|
if (_level !== -1) {
|
|
246
226
|
level = _level;
|
|
@@ -250,12 +230,7 @@ module.exports = class extends BaseRest {
|
|
|
250
230
|
}
|
|
251
231
|
|
|
252
232
|
if (count.user_id && users[count.user_id]) {
|
|
253
|
-
const {
|
|
254
|
-
display_name: nick,
|
|
255
|
-
url: link,
|
|
256
|
-
avatar: avatarUrl,
|
|
257
|
-
label,
|
|
258
|
-
} = users[count.user_id];
|
|
233
|
+
const { display_name: nick, url: link, avatar: avatarUrl, label } = users[count.user_id];
|
|
259
234
|
const avatar =
|
|
260
235
|
avatarProxy && !avatarUrl.includes(avatarProxy)
|
|
261
236
|
? avatarProxy + '?url=' + encodeURIComponent(avatarUrl)
|
|
@@ -266,10 +241,7 @@ module.exports = class extends BaseRest {
|
|
|
266
241
|
continue;
|
|
267
242
|
}
|
|
268
243
|
|
|
269
|
-
const comments = await commentModel.select(
|
|
270
|
-
{ mail: count.mail },
|
|
271
|
-
{ limit: 1 },
|
|
272
|
-
);
|
|
244
|
+
const comments = await commentModel.select({ mail: count.mail }, { limit: 1 });
|
|
273
245
|
|
|
274
246
|
if (think.isEmpty(comments)) {
|
|
275
247
|
continue;
|
package/src/extend/think.js
CHANGED
|
@@ -78,9 +78,7 @@ module.exports = {
|
|
|
78
78
|
}
|
|
79
79
|
const { region } = result;
|
|
80
80
|
const [, , province, city, isp] = region.split('|');
|
|
81
|
-
const address = Array.from(
|
|
82
|
-
new Set([province, city, isp].filter((v) => v)),
|
|
83
|
-
);
|
|
81
|
+
const address = Array.from(new Set([province, city, isp].filter((v) => v)));
|
|
84
82
|
|
|
85
83
|
return address.slice(0, depth).join(' ');
|
|
86
84
|
} catch (err) {
|
|
@@ -149,9 +147,7 @@ module.exports = {
|
|
|
149
147
|
},
|
|
150
148
|
getPluginHook(hookName) {
|
|
151
149
|
return think
|
|
152
|
-
.pluginMap('hooks', (hook) =>
|
|
153
|
-
think.isFunction(hook[hookName]) ? hook[hookName] : undefined,
|
|
154
|
-
)
|
|
150
|
+
.pluginMap('hooks', (hook) => (think.isFunction(hook[hookName]) ? hook[hookName] : undefined))
|
|
155
151
|
.filter((v) => v);
|
|
156
152
|
},
|
|
157
153
|
buildUrl(path, query = {}) {
|