@waline/vercel 1.6.1 → 1.7.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.6.1",
3
+ "version": "1.7.0",
4
4
  "description": "vercel server for waline comment system",
5
5
  "repository": "https://github.com/walinejs/waline",
6
6
  "license": "MIT",
@@ -17,7 +17,7 @@
17
17
  "jsonwebtoken": "^8.5.1",
18
18
  "katex": "^0.13.23",
19
19
  "leancloud-storage": "^4.12.0",
20
- "markdown-it": "^12.2.0",
20
+ "markdown-it": "^12.3.2",
21
21
  "markdown-it-emoji": "^2.0.0",
22
22
  "markdown-it-sub": "^1.0.0",
23
23
  "markdown-it-sup": "^1.0.0",
@@ -1,4 +1,3 @@
1
- const helper = require('think-helper');
2
1
  const parser = require('ua-parser-js');
3
2
  const BaseRest = require('./rest');
4
3
  const akismet = require('../service/akismet');
@@ -8,7 +7,8 @@ const markdownParser = getMarkdownParser();
8
7
  async function formatCmt(
9
8
  { ua, user_id, ...comment },
10
9
  users = [],
11
- { avatarProxy }
10
+ { avatarProxy },
11
+ loginUser
12
12
  ) {
13
13
  ua = parser(ua);
14
14
  if (!think.config('disableUserAgent')) {
@@ -36,9 +36,12 @@ async function formatCmt(
36
36
  ? avatarProxy + '?url=' + encodeURIComponent(avatarUrl)
37
37
  : avatarUrl;
38
38
 
39
- comment.mail = helper.md5(
40
- comment.mail ? comment.mail.toLowerCase() : comment.mail
41
- );
39
+ const isAdmin = loginUser && loginUser.type === 'administrator';
40
+ if (!isAdmin) {
41
+ delete comment.mail;
42
+ } else {
43
+ comment.orig = comment.comment;
44
+ }
42
45
 
43
46
  comment.comment = markdownParser(comment.comment);
44
47
  return comment;
@@ -55,30 +58,40 @@ module.exports = class extends BaseRest {
55
58
 
56
59
  async getAction() {
57
60
  const { type } = this.get();
61
+ const { userInfo } = this.ctx.state;
58
62
 
59
63
  switch (type) {
60
64
  case 'recent': {
61
65
  const { count } = this.get();
62
- const comments = await this.modelInstance.select(
63
- { status: ['NOT IN', ['waiting', 'spam']] },
64
- {
65
- desc: 'insertedAt',
66
- limit: count,
67
- field: [
68
- 'comment',
69
- 'insertedAt',
70
- 'link',
71
- 'mail',
72
- 'nick',
73
- 'url',
74
- 'pid',
75
- 'rid',
76
- 'ua',
77
- 'user_id',
78
- 'sticky',
79
- ],
80
- }
81
- );
66
+ const where = {};
67
+ if (think.isEmpty(userInfo) || this.config('storage') === 'deta') {
68
+ where.status = ['NOT IN', ['waiting', 'spam']];
69
+ } else {
70
+ where._complex = {
71
+ _logic: 'or',
72
+ status: ['NOT IN', ['waiting', 'spam']],
73
+ user_id: userInfo.objectId,
74
+ };
75
+ }
76
+
77
+ const comments = await this.modelInstance.select(where, {
78
+ desc: 'insertedAt',
79
+ limit: count,
80
+ field: [
81
+ 'status',
82
+ 'comment',
83
+ 'insertedAt',
84
+ 'link',
85
+ 'mail',
86
+ 'nick',
87
+ 'url',
88
+ 'pid',
89
+ 'rid',
90
+ 'ua',
91
+ 'user_id',
92
+ 'sticky',
93
+ ],
94
+ });
82
95
 
83
96
  const userModel = this.service(
84
97
  `storage/${this.config('storage')}`,
@@ -100,20 +113,26 @@ module.exports = class extends BaseRest {
100
113
 
101
114
  return this.json(
102
115
  await Promise.all(
103
- comments.map((cmt) => formatCmt(cmt, users, this.config()))
116
+ comments.map((cmt) =>
117
+ formatCmt(cmt, users, this.config(), userInfo)
118
+ )
104
119
  )
105
120
  );
106
121
  }
107
122
 
108
123
  case 'count': {
109
124
  const { url } = this.get();
110
- const data = await this.modelInstance.select(
111
- {
112
- url: ['IN', url],
125
+ const where = { url: ['IN', url] };
126
+ if (think.isEmpty(userInfo) || this.config('storage') === 'deta') {
127
+ where.status = ['NOT IN', ['waiting', 'spam']];
128
+ } else {
129
+ where._complex = {
130
+ _logic: 'or',
113
131
  status: ['NOT IN', ['waiting', 'spam']],
114
- },
115
- { field: ['url'] }
116
- );
132
+ user_id: userInfo.objectId,
133
+ };
134
+ }
135
+ const data = await this.modelInstance.select(where, { field: ['url'] });
117
136
  const counts = url.map(
118
137
  (u) => data.filter(({ url }) => url === u).length
119
138
  );
@@ -179,35 +198,42 @@ module.exports = class extends BaseRest {
179
198
  spamCount,
180
199
  waitingCount,
181
200
  data: await Promise.all(
182
- comments.map((cmt) => formatCmt(cmt, users, this.config()))
201
+ comments.map((cmt) =>
202
+ formatCmt(cmt, users, this.config(), userInfo)
203
+ )
183
204
  ),
184
205
  });
185
206
  }
186
207
 
187
208
  default: {
188
209
  const { path: url, page, pageSize } = this.get();
189
-
190
- const comments = await this.modelInstance.select(
191
- {
192
- url,
210
+ const where = { url };
211
+ if (think.isEmpty(userInfo) || this.config('storage') === 'deta') {
212
+ where.status = ['NOT IN', ['waiting', 'spam']];
213
+ } else {
214
+ where._complex = {
215
+ _logic: 'or',
193
216
  status: ['NOT IN', ['waiting', 'spam']],
194
- },
195
- {
196
- desc: 'insertedAt',
197
- field: [
198
- 'comment',
199
- 'insertedAt',
200
- 'link',
201
- 'mail',
202
- 'nick',
203
- 'pid',
204
- 'rid',
205
- 'ua',
206
- 'user_id',
207
- 'sticky',
208
- ],
209
- }
210
- );
217
+ user_id: userInfo.objectId,
218
+ };
219
+ }
220
+
221
+ const comments = await this.modelInstance.select(where, {
222
+ desc: 'insertedAt',
223
+ field: [
224
+ 'status',
225
+ 'comment',
226
+ 'insertedAt',
227
+ 'link',
228
+ 'mail',
229
+ 'nick',
230
+ 'pid',
231
+ 'rid',
232
+ 'ua',
233
+ 'user_id',
234
+ 'sticky',
235
+ ],
236
+ });
211
237
 
212
238
  const userModel = this.service(
213
239
  `storage/${this.config('storage')}`,
@@ -241,11 +267,16 @@ module.exports = class extends BaseRest {
241
267
  count: comments.length,
242
268
  data: await Promise.all(
243
269
  rootComments.map(async (comment) => {
244
- const cmt = await formatCmt(comment, users, this.config());
270
+ const cmt = await formatCmt(
271
+ comment,
272
+ users,
273
+ this.config(),
274
+ userInfo
275
+ );
245
276
  cmt.children = await Promise.all(
246
277
  comments
247
278
  .filter(({ rid }) => rid === cmt.objectId)
248
- .map((cmt) => formatCmt(cmt, users, this.config()))
279
+ .map((cmt) => formatCmt(cmt, users, this.config(), userInfo))
249
280
  .reverse()
250
281
  );
251
282
  return cmt;
@@ -403,7 +434,9 @@ module.exports = class extends BaseRest {
403
434
 
404
435
  think.logger.debug(`Comment post hooks postSave done!`);
405
436
 
406
- return this.success(await formatCmt(resp, [userInfo], this.config()));
437
+ return this.success(
438
+ await formatCmt(resp, [userInfo], this.config(), userInfo)
439
+ );
407
440
  }
408
441
 
409
442
  async putAction() {
package/src/logic/base.js CHANGED
@@ -45,6 +45,7 @@ module.exports = class extends think.Logic {
45
45
  { email: userMail },
46
46
  {
47
47
  field: [
48
+ 'id',
48
49
  'email',
49
50
  'url',
50
51
  'display_name',
@@ -33,14 +33,17 @@ module.exports = class extends Base {
33
33
  }
34
34
  }
35
35
 
36
- where(instance, where) {
36
+ parseWhere(where) {
37
37
  if (think.isEmpty(where)) {
38
- return instance;
38
+ return {};
39
39
  }
40
40
 
41
41
  const filter = {};
42
42
  const parseKey = (k) => (k === 'objectId' ? '_id' : k);
43
43
  for (let k in where) {
44
+ if (k === '_complex') {
45
+ continue;
46
+ }
44
47
  if (think.isString(where[k])) {
45
48
  filter[parseKey(k)] = _.eq(where[k]);
46
49
  continue;
@@ -84,7 +87,26 @@ module.exports = class extends Base {
84
87
  }
85
88
  }
86
89
  }
87
- return instance.where(filter);
90
+ return filter;
91
+ }
92
+
93
+ where(instance, where) {
94
+ const filter = this.parseWhere(where);
95
+ if (!where._complex) {
96
+ return instance.where(filter);
97
+ }
98
+
99
+ const filters = [];
100
+ for (const k in where._complex) {
101
+ if (k === '_logic') {
102
+ continue;
103
+ }
104
+ filters.push({
105
+ ...this.parseWhere({ [k]: where._complex[k] }),
106
+ ...filter,
107
+ });
108
+ }
109
+ return instance.where(_[where._complex._logic](...filters));
88
110
  }
89
111
 
90
112
  async _select(where, { desc, limit, offset, field } = {}) {
@@ -166,13 +166,18 @@ module.exports = class extends Base {
166
166
  return this.git.set(filename, csv, { sha });
167
167
  }
168
168
 
169
- where(data, where) {
169
+ parseWhere(where) {
170
+ const _where = [];
170
171
  if (think.isEmpty(where)) {
171
- return data;
172
+ return _where;
172
173
  }
173
174
 
174
175
  const filters = [];
175
176
  for (let k in where) {
177
+ if (k === '_complex') {
178
+ continue;
179
+ }
180
+
176
181
  if (k === 'objectId') {
177
182
  filters.push((item) => item.id === where[k]);
178
183
  continue;
@@ -219,7 +224,33 @@ module.exports = class extends Base {
219
224
  }
220
225
  }
221
226
 
222
- return filters.reduce((data, fn) => data.filter(fn), data);
227
+ return filters;
228
+ }
229
+
230
+ where(data, where) {
231
+ const filter = this.parseWhere(where);
232
+
233
+ if (!where._complex) {
234
+ return data.filter((item) => filter.every((fn) => fn(item)));
235
+ }
236
+
237
+ const logicMap = {
238
+ and: Array.prototype.every,
239
+ or: Array.prototype.some,
240
+ };
241
+ const filters = [];
242
+ for (const k in where._complex) {
243
+ if (k === '_logic') {
244
+ continue;
245
+ }
246
+
247
+ filters.push([...filter, ...this.parseWhere({ [k]: where._complex[k] })]);
248
+ }
249
+
250
+ const logicFn = logicMap[where._complex._logic];
251
+ return data.filter((item) =>
252
+ logicFn.call(filters, (filter) => filter.every((fn) => fn(item)))
253
+ );
223
254
  }
224
255
 
225
256
  async select(where, { desc, limit, offset, field } = {}) {
@@ -7,14 +7,18 @@ module.exports = class extends Base {
7
7
  this.db = inspirecloud.db;
8
8
  }
9
9
 
10
- where(where) {
10
+ parseWhere(where) {
11
+ const _where = {};
11
12
  if (think.isEmpty(where)) {
12
- return;
13
+ return _where;
13
14
  }
14
15
 
15
- const _where = {};
16
16
  const parseKey = (k) => (k === 'objectId' ? '_id' : k);
17
17
  for (const k in where) {
18
+ if (k === '_complex') {
19
+ continue;
20
+ }
21
+
18
22
  if (think.isString(where[k])) {
19
23
  _where[parseKey(k)] =
20
24
  k === 'objectId' ? this.db.ObjectId(where[k]) : where[k];
@@ -28,18 +32,20 @@ module.exports = class extends Base {
28
32
  const handler = where[k][0].toUpperCase();
29
33
  switch (handler) {
30
34
  case 'IN':
31
- _where[parseKey(k)] = this.db.in(
32
- k === 'objectId'
33
- ? where[k][1].map(this.db.ObjectId)
34
- : where[k][1]
35
- );
35
+ _where[parseKey(k)] = {
36
+ $in:
37
+ k === 'objectId'
38
+ ? where[k][1].map(this.db.ObjectId)
39
+ : where[k][1],
40
+ };
36
41
  break;
37
42
  case 'NOT IN':
38
- _where[parseKey(k)] = this.db.nin(
39
- k === 'objectId'
40
- ? where[k][1].map(this.db.ObjectId)
41
- : where[k][1]
42
- );
43
+ _where[parseKey(k)] = {
44
+ $nin:
45
+ k === 'objectId'
46
+ ? where[k][1].map(this.db.ObjectId)
47
+ : where[k][1],
48
+ };
43
49
  break;
44
50
  case 'LIKE': {
45
51
  const first = where[k][1][0];
@@ -52,14 +58,14 @@ module.exports = class extends Base {
52
58
  } else if (last === '%') {
53
59
  reg = new RegExp('^' + where[k][1].slice(0, -1));
54
60
  }
55
- _where[parseKey(k)] = this.db.regex(reg);
61
+ _where[parseKey(k)] = { $regex: reg };
56
62
  break;
57
63
  }
58
64
  case '!=':
59
- _where[parseKey(k)] = this.db.ne(where[k]);
65
+ _where[parseKey(k)] = { $ne: where[k] };
60
66
  break;
61
67
  case '>':
62
- _where[parseKey(k)] = this.db.gt(where[k]);
68
+ _where[parseKey(k)] = { $gt: where[k] };
63
69
  break;
64
70
  }
65
71
  }
@@ -69,6 +75,27 @@ module.exports = class extends Base {
69
75
  return _where;
70
76
  }
71
77
 
78
+ where(where) {
79
+ const filter = this.parseWhere(where);
80
+ if (!where._complex) {
81
+ return filter;
82
+ }
83
+
84
+ const filters = [];
85
+ for (const k in where._complex) {
86
+ if (k === '_logic') {
87
+ continue;
88
+ }
89
+
90
+ filters.push({
91
+ ...this.parseWhere({ [k]: where._complex[k] }),
92
+ ...filter,
93
+ });
94
+ }
95
+
96
+ return { [`$${where._complex._logic}`]: filters };
97
+ }
98
+
72
99
  async _select(where, { desc, limit, offset, field } = {}) {
73
100
  const instance = this.db.table(this.tableName);
74
101
  const query = instance.where(this.where(where));
@@ -13,19 +13,26 @@ if (LEAN_ID && LEAN_KEY && LEAN_MASTER_KEY) {
13
13
  });
14
14
  }
15
15
  module.exports = class extends Base {
16
- where(instance, where) {
16
+ parseWhere(className, where) {
17
+ const instance = new AV.Query(className);
17
18
  if (think.isEmpty(where)) {
18
- return;
19
+ return instance;
19
20
  }
20
21
 
21
22
  for (const k in where) {
23
+ if (k === '_complex') {
24
+ continue;
25
+ }
26
+
22
27
  if (think.isString(where[k])) {
23
28
  instance.equalTo(k, where[k]);
24
29
  continue;
25
30
  }
31
+
26
32
  if (where[k] === undefined) {
27
33
  instance.doesNotExist(k);
28
34
  }
35
+
29
36
  if (Array.isArray(where[k])) {
30
37
  if (where[k][0]) {
31
38
  const handler = where[k][0].toUpperCase();
@@ -58,11 +65,32 @@ module.exports = class extends Base {
58
65
  }
59
66
  }
60
67
  }
68
+ return instance;
69
+ }
70
+
71
+ where(className, where) {
72
+ if (!where._complex) {
73
+ return this.parseWhere(className, where);
74
+ }
75
+
76
+ const filters = [];
77
+ for (const k in where._complex) {
78
+ if (k === '_logic') {
79
+ continue;
80
+ }
81
+
82
+ const filter = this.parseWhere(className, {
83
+ ...where,
84
+ [k]: where._complex[k],
85
+ });
86
+ filters.push(filter);
87
+ }
88
+
89
+ return AV.Query[where._complex._logic](...filters);
61
90
  }
62
91
 
63
92
  async _select(where, { desc, limit, offset, field } = {}) {
64
- const instance = new AV.Query(this.tableName);
65
- this.where(instance, where);
93
+ const instance = this.where(this.tableName, where);
66
94
  if (desc) {
67
95
  instance.descending(desc);
68
96
  }
@@ -99,8 +127,7 @@ module.exports = class extends Base {
99
127
  }
100
128
 
101
129
  async count(where = {}, options = {}) {
102
- const instance = new AV.Query(this.tableName);
103
- this.where(instance, where);
130
+ const instance = this.where(this.tableName, where);
104
131
  return instance.count(options).catch((e) => {
105
132
  if (e.code === 101) {
106
133
  return 0;
@@ -127,8 +154,7 @@ module.exports = class extends Base {
127
154
  }
128
155
 
129
156
  async update(data, where) {
130
- const instance = new AV.Query(this.tableName);
131
- this.where(instance, where);
157
+ const instance = this.where(this.tableName, where);
132
158
  const ret = await instance.find();
133
159
 
134
160
  return Promise.all(
@@ -146,8 +172,7 @@ module.exports = class extends Base {
146
172
  }
147
173
 
148
174
  async delete(where) {
149
- const instance = new AV.Query(this.tableName);
150
- this.where(instance, where);
175
+ const instance = this.where(this.tableName, where);
151
176
  const data = await instance.find();
152
177
 
153
178
  return AV.Object.destroyAll(data);
@@ -2,25 +2,25 @@ const { ObjectId } = require('mongodb');
2
2
  const Base = require('./base');
3
3
 
4
4
  module.exports = class extends Base {
5
- where(instance, where) {
5
+ parseWhere(where) {
6
6
  if (think.isEmpty(where)) {
7
- return;
7
+ return {};
8
8
  }
9
9
 
10
+ const filter = {};
10
11
  const parseKey = (k) => (k === 'objectId' ? '_id' : k);
11
12
  for (let k in where) {
13
+ if (k === '_complex') {
14
+ continue;
15
+ }
12
16
  if (think.isString(where[k])) {
13
- instance.where({
14
- [parseKey(k)]: {
15
- $eq: k === 'objectId' ? ObjectId(where[k]) : where[k],
16
- },
17
- });
17
+ filter[parseKey(k)] = {
18
+ $eq: k === 'objectId' ? ObjectId(where[k]) : where[k],
19
+ };
18
20
  continue;
19
21
  }
20
22
  if (where[k] === undefined) {
21
- instance.where({
22
- [parseKey(k)]: { $eq: null },
23
- });
23
+ filter[parseKey(k)] = { $eq: null };
24
24
  }
25
25
  if (Array.isArray(where[k])) {
26
26
  if (where[k][0]) {
@@ -28,63 +28,70 @@ module.exports = class extends Base {
28
28
  switch (handler) {
29
29
  case 'IN':
30
30
  if (k === 'objectId') {
31
- instance.where({
32
- [parseKey(k)]: { $in: where[k][1].map(ObjectId) },
33
- });
31
+ filter[parseKey(k)] = { $in: where[k][1].map(ObjectId) };
34
32
  } else {
35
- instance.where({
36
- [parseKey(k)]: {
37
- $regex: new RegExp(`^(${where[k][1].join('|')})$`),
38
- },
39
- });
33
+ filter[parseKey(k)] = {
34
+ $regex: new RegExp(`^(${where[k][1].join('|')})$`),
35
+ };
40
36
  }
41
37
  break;
42
38
  case 'NOT IN':
43
- instance.where({
44
- [parseKey(k)]: {
45
- $nin:
46
- k === 'objectId' ? where[k][1].map(ObjectId) : where[k][1],
47
- },
48
- });
39
+ filter[parseKey(k)] = {
40
+ $nin:
41
+ k === 'objectId' ? where[k][1].map(ObjectId) : where[k][1],
42
+ };
49
43
  break;
50
44
  case 'LIKE': {
51
45
  const first = where[k][1][0];
52
46
  const last = where[k][1].slice(-1);
47
+ let reg;
53
48
  if (first === '%' && last === '%') {
54
- instance.where({
55
- [parseKey(k)]: {
56
- $regex: new RegExp(where[k][1].slice(1, -1)),
57
- },
58
- });
49
+ reg = new RegExp(where[k][1].slice(1, -1));
59
50
  } else if (first === '%') {
60
- instance.where({
61
- [parseKey(k)]: {
62
- $regex: new RegExp(where[k][1].slice(1) + '$'),
63
- },
64
- });
51
+ reg = new RegExp(where[k][1].slice(1) + '$');
65
52
  } else if (last === '%') {
66
- instance.where({
67
- [parseKey(k)]: {
68
- $regex: new RegExp('^' + where[k][1].slice(0, -1)),
69
- },
70
- });
53
+ reg = new RegExp('^' + where[k][1].slice(0, -1));
54
+ }
55
+
56
+ if (reg) {
57
+ filter[parseKey(k)] = { $regex: reg };
71
58
  }
72
59
  break;
73
60
  }
74
61
  case '!=':
75
- instance.where({
76
- [parseKey(k)]: { $ne: where[k][1] },
77
- });
62
+ filter[parseKey(k)] = { $ne: where[k][1] };
78
63
  break;
79
64
  case '>':
80
- instance.where({
81
- [parseKey(k)]: { $gt: where[k][1] },
82
- });
65
+ filter[parseKey(k)] = { $gt: where[k][1] };
83
66
  break;
84
67
  }
85
68
  }
86
69
  }
87
70
  }
71
+ return filter;
72
+ }
73
+
74
+ where(instance, where) {
75
+ const filter = this.parseWhere(where);
76
+ if (!where._complex) {
77
+ return instance.where(filter);
78
+ }
79
+
80
+ const filters = [];
81
+ for (const k in where._complex) {
82
+ if (k === '_logic') {
83
+ continue;
84
+ }
85
+ filters.push({
86
+ ...this.parseWhere({ [k]: where._complex[k] }),
87
+ ...filter,
88
+ });
89
+ }
90
+
91
+ return instance.where({
92
+ // $or, $and, $not, $nor
93
+ [`$${where._complex._logic}`]: filters,
94
+ });
88
95
  }
89
96
 
90
97
  async select(where, { desc, limit, offset, field } = {}) {