@waline/vercel 1.15.2 → 1.17.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.15.2",
3
+ "version": "1.17.0",
4
4
  "description": "vercel server for waline comment system",
5
5
  "keywords": [
6
6
  "waline",
@@ -20,20 +20,21 @@
20
20
  "akismet": "^2.0.7",
21
21
  "deta": "^1.1.0",
22
22
  "dompurify": "^2.3.6",
23
+ "dy-node-ip2region": "^1.0.1",
23
24
  "fast-csv": "^4.3.6",
24
25
  "jsdom": "^19.0.0",
25
26
  "jsonwebtoken": "^8.5.1",
26
27
  "katex": "^0.15.3",
27
28
  "leancloud-storage": "^4.12.2",
28
- "markdown-it": "^12.3.2",
29
- "markdown-it-emoji": "^2.0.0",
29
+ "markdown-it": "^13.0.1",
30
+ "markdown-it-emoji": "^2.0.2",
30
31
  "markdown-it-sub": "^1.0.0",
31
32
  "markdown-it-sup": "^1.0.0",
32
33
  "mathjax-full": "^3.2.0",
33
- "nodemailer": "^6.7.3",
34
+ "nodemailer": "^6.7.4",
34
35
  "nunjucks": "^3.2.3",
35
36
  "phpass": "^0.1.1",
36
- "prismjs": "^1.27.0",
37
+ "prismjs": "^1.28.0",
37
38
  "request": "^2.88.2",
38
39
  "request-promise-native": "^1.0.9",
39
40
  "speakeasy": "^2.0.0",
@@ -14,6 +14,7 @@ const {
14
14
  TCB_KEY,
15
15
  SECURE_DOMAINS,
16
16
  DISABLE_USERAGENT,
17
+ DISABLE_REGION,
17
18
  AVATAR_PROXY,
18
19
  GITHUB_TOKEN,
19
20
  DETA_PROJECT_KEY,
@@ -106,6 +107,7 @@ module.exports = {
106
107
  disallowIPList: [],
107
108
  secureDomains: SECURE_DOMAINS ? SECURE_DOMAINS.split(/\s*,\s*/) : undefined,
108
109
  disableUserAgent: DISABLE_USERAGENT && !isFalse(DISABLE_USERAGENT),
110
+ disableRegion: DISABLE_REGION && !isFalse(DISABLE_REGION),
109
111
  levels:
110
112
  !LEVELS || isFalse(LEVELS)
111
113
  ? false
@@ -5,7 +5,7 @@ const { getMarkdownParser } = require('../service/markdown');
5
5
 
6
6
  const markdownParser = getMarkdownParser();
7
7
  async function formatCmt(
8
- { ua, user_id, ...comment },
8
+ { ua, user_id, ip, ...comment },
9
9
  users = [],
10
10
  { avatarProxy },
11
11
  loginUser
@@ -25,6 +25,7 @@ async function formatCmt(
25
25
  comment.mail = user.email;
26
26
  comment.link = user.url;
27
27
  comment.type = user.type;
28
+ comment.label = user.label;
28
29
  }
29
30
 
30
31
  const avatarUrl =
@@ -41,8 +42,13 @@ async function formatCmt(
41
42
  delete comment.mail;
42
43
  } else {
43
44
  comment.orig = comment.comment;
45
+ comment.ip = ip;
44
46
  }
45
47
 
48
+ // administrator can always show region
49
+ if (isAdmin || !think.config('disableRegion')) {
50
+ comment.addr = await think.ip2region(ip, { depth: isAdmin ? 3 : 1 });
51
+ }
46
52
  comment.comment = markdownParser(comment.comment);
47
53
  return comment;
48
54
  }
@@ -88,6 +94,7 @@ module.exports = class extends BaseRest {
88
94
  'pid',
89
95
  'rid',
90
96
  'ua',
97
+ 'ip',
91
98
  'user_id',
92
99
  'sticky',
93
100
  ],
@@ -106,7 +113,14 @@ module.exports = class extends BaseRest {
106
113
  users = await userModel.select(
107
114
  { objectId: ['IN', user_ids] },
108
115
  {
109
- field: ['display_name', 'email', 'url', 'type', 'avatar'],
116
+ field: [
117
+ 'display_name',
118
+ 'email',
119
+ 'url',
120
+ 'type',
121
+ 'avatar',
122
+ 'label',
123
+ ],
110
124
  }
111
125
  );
112
126
  }
@@ -186,7 +200,14 @@ module.exports = class extends BaseRest {
186
200
  users = await userModel.select(
187
201
  { objectId: ['IN', user_ids] },
188
202
  {
189
- field: ['display_name', 'email', 'url', 'type', 'avatar'],
203
+ field: [
204
+ 'display_name',
205
+ 'email',
206
+ 'url',
207
+ 'type',
208
+ 'avatar',
209
+ 'label',
210
+ ],
190
211
  }
191
212
  );
192
213
  }
@@ -235,6 +256,7 @@ module.exports = class extends BaseRest {
235
256
  'pid',
236
257
  'rid',
237
258
  'ua',
259
+ 'ip',
238
260
  'user_id',
239
261
  'sticky',
240
262
  ],
@@ -307,7 +329,14 @@ module.exports = class extends BaseRest {
307
329
  users = await userModel.select(
308
330
  { objectId: ['IN', user_ids] },
309
331
  {
310
- field: ['display_name', 'email', 'url', 'type', 'avatar'],
332
+ field: [
333
+ 'display_name',
334
+ 'email',
335
+ 'url',
336
+ 'type',
337
+ 'avatar',
338
+ 'label',
339
+ ],
311
340
  }
312
341
  );
313
342
  }
@@ -11,6 +11,26 @@ module.exports = class extends BaseRest {
11
11
  );
12
12
  }
13
13
 
14
+ async getAction() {
15
+ const { page, pageSize } = this.get();
16
+
17
+ const count = await this.modelInstance.count({});
18
+ const users = await this.modelInstance.select(
19
+ {},
20
+ {
21
+ desc: 'insertedAt',
22
+ limit: pageSize,
23
+ offset: Math.max((page - 1) * pageSize, 0),
24
+ }
25
+ );
26
+ return this.success({
27
+ page,
28
+ totalPages: Math.ceil(count / pageSize),
29
+ pageSize,
30
+ data: users,
31
+ });
32
+ }
33
+
14
34
  async postAction() {
15
35
  const data = this.post();
16
36
  const resp = await this.modelInstance.select({
@@ -92,12 +112,20 @@ module.exports = class extends BaseRest {
92
112
  }
93
113
 
94
114
  async putAction() {
95
- const { display_name, url, avatar, password } = this.post();
115
+ const { display_name, url, avatar, password, type, label } = this.post();
96
116
  const { objectId } = this.ctx.state.userInfo;
97
117
  const twoFactorAuth = this.post('2fa');
98
118
 
99
119
  const updateData = {};
100
120
 
121
+ if (this.id && type) {
122
+ updateData.type = type;
123
+ }
124
+
125
+ if (think.isString(label)) {
126
+ updateData.label = label;
127
+ }
128
+
101
129
  if (display_name) {
102
130
  updateData.display_name = display_name;
103
131
  }
@@ -130,7 +158,9 @@ module.exports = class extends BaseRest {
130
158
  return this.success();
131
159
  }
132
160
 
133
- await this.modelInstance.update(updateData, { objectId });
161
+ await this.modelInstance.update(updateData, {
162
+ objectId: this.id || objectId,
163
+ });
134
164
 
135
165
  return this.success();
136
166
  }
@@ -1,5 +1,9 @@
1
+ const ip2region = require('dy-node-ip2region');
2
+ const helper = require('think-helper');
1
3
  const preventMessage = 'PREVENT_NEXT_PROCESS';
2
4
 
5
+ const regionSearch = ip2region.create();
6
+
3
7
  module.exports = {
4
8
  prevent() {
5
9
  throw new Error(preventMessage);
@@ -18,4 +22,46 @@ module.exports = {
18
22
 
19
23
  return -1;
20
24
  },
25
+ promiseAllQueue(promises, taskNum) {
26
+ return new Promise((resolve, reject) => {
27
+ const ret = [];
28
+ let index = 0;
29
+ let count = 0;
30
+
31
+ function runTask() {
32
+ const idx = index;
33
+ index += 1;
34
+ if (index > promises.length) {
35
+ return Promise.resolve();
36
+ }
37
+
38
+ return promises[idx].then((data) => {
39
+ ret[idx] = data;
40
+ count += 1;
41
+ if (count === promises.length) {
42
+ resolve(ret);
43
+ }
44
+ return runTask();
45
+ }, reject);
46
+ }
47
+
48
+ for (let i = 0; i < taskNum; i++) {
49
+ runTask();
50
+ }
51
+ });
52
+ },
53
+ async ip2region(ip, { depth = 1 }) {
54
+ if (!ip) return '';
55
+
56
+ try {
57
+ const search = helper.promisify(regionSearch.btreeSearch, regionSearch);
58
+ const { region } = await search(ip);
59
+ const [, , province, city, isp] = region.split('|');
60
+ const address = Array.from(new Set([province, city, isp]));
61
+ return address.slice(0, depth).join(' ');
62
+ } catch (e) {
63
+ console.log(e);
64
+ return '';
65
+ }
66
+ },
21
67
  };
package/src/logic/base.js CHANGED
@@ -8,6 +8,7 @@ module.exports = class extends think.Logic {
8
8
  `storage/${this.config('storage')}`,
9
9
  'Users'
10
10
  );
11
+ this.id = this.getId();
11
12
  }
12
13
 
13
14
  async __before() {
@@ -89,4 +90,20 @@ module.exports = class extends think.Logic {
89
90
  this.ctx.state.userInfo = userInfo;
90
91
  this.ctx.state.token = token;
91
92
  }
93
+
94
+ getId() {
95
+ const id = this.get('id');
96
+
97
+ if (id && (think.isString(id) || think.isNumber(id))) {
98
+ return id;
99
+ }
100
+
101
+ const last = decodeURIComponent(this.ctx.path.split('/').pop());
102
+
103
+ if (last !== this.resource && /^([a-z0-9]+,?)*$/i.test(last)) {
104
+ return last;
105
+ }
106
+
107
+ return '';
108
+ }
92
109
  };
package/src/logic/user.js CHANGED
@@ -1,6 +1,24 @@
1
1
  const Base = require('./base');
2
2
 
3
3
  module.exports = class extends Base {
4
+ getAction() {
5
+ const { userInfo } = this.ctx.state;
6
+ if (think.isEmpty(userInfo) || userInfo.type !== 'administrator') {
7
+ return this.fail();
8
+ }
9
+
10
+ this.rules = {
11
+ page: {
12
+ int: true,
13
+ default: 1,
14
+ },
15
+ pageSize: {
16
+ int: { max: 100 },
17
+ default: 10,
18
+ },
19
+ };
20
+ }
21
+
4
22
  /**
5
23
  * @api {POST} /user user register
6
24
  * @apiGroup User
@@ -30,9 +48,15 @@ module.exports = class extends Base {
30
48
  * @apiSuccess (200) {String} errmsg return error message if error
31
49
  */
32
50
  putAction() {
51
+ // you need login to update yourself profile
33
52
  const { userInfo } = this.ctx.state;
34
53
  if (think.isEmpty(userInfo)) {
35
54
  return this.fail();
36
55
  }
56
+
57
+ // you should be a administrator to update otherself info
58
+ if (this.id && userInfo.type !== 'administrator') {
59
+ return this.fail();
60
+ }
37
61
  }
38
62
  };
@@ -172,7 +172,7 @@ module.exports = class extends Base {
172
172
  }
173
173
  }
174
174
 
175
- await Promise.all(countsPromise);
175
+ await think.promiseAllQueue(countsPromise, 3);
176
176
  return counts;
177
177
  }
178
178