@waline/vercel 1.26.3 → 1.26.4
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/dist/404.html +39 -0
- package/dist/500.html +275 -0
- package/dist/index.js +58501 -0
- package/dist/package.json +54 -0
- package/dist/src/config/adapter.js +170 -0
- package/dist/src/config/config.js +134 -0
- package/dist/src/config/extend.js +38 -0
- package/dist/src/config/middleware.js +66 -0
- package/dist/src/config/router.js +1 -0
- package/dist/src/controller/article.js +91 -0
- package/dist/src/controller/comment.js +758 -0
- package/dist/src/controller/db.js +71 -0
- package/dist/src/controller/index.js +36 -0
- package/dist/src/controller/oauth.js +136 -0
- package/dist/src/controller/rest.js +60 -0
- package/dist/src/controller/token/2fa.js +66 -0
- package/dist/src/controller/token.js +75 -0
- package/dist/src/controller/user/password.js +52 -0
- package/dist/src/controller/user.js +289 -0
- package/dist/src/controller/verification.js +35 -0
- package/dist/src/extend/controller.js +25 -0
- package/dist/src/extend/think.js +84 -0
- package/dist/src/locales/en.json +19 -0
- package/dist/src/locales/index.js +12 -0
- package/dist/src/locales/zh-CN.json +19 -0
- package/dist/src/locales/zh-TW.json +19 -0
- package/dist/src/logic/article.js +27 -0
- package/dist/src/logic/base.js +164 -0
- package/dist/src/logic/comment.js +317 -0
- package/dist/src/logic/db.js +81 -0
- package/dist/src/logic/oauth.js +10 -0
- package/dist/src/logic/token/2fa.js +28 -0
- package/dist/src/logic/token.js +53 -0
- package/dist/src/logic/user/password.js +11 -0
- package/dist/src/logic/user.js +117 -0
- package/dist/src/middleware/dashboard.js +23 -0
- package/dist/src/middleware/version.js +6 -0
- package/dist/src/service/akismet.js +41 -0
- package/dist/src/service/avatar.js +35 -0
- package/dist/src/service/markdown/highlight.js +32 -0
- package/dist/src/service/markdown/index.js +63 -0
- package/dist/src/service/markdown/katex.js +49 -0
- package/dist/src/service/markdown/mathCommon.js +156 -0
- package/dist/src/service/markdown/mathjax.js +78 -0
- package/dist/src/service/markdown/utils.js +11 -0
- package/dist/src/service/markdown/xss.js +44 -0
- package/dist/src/service/notify.js +537 -0
- package/dist/src/service/storage/base.js +31 -0
- package/dist/src/service/storage/cloudbase.js +221 -0
- package/dist/src/service/storage/deta.js +307 -0
- package/dist/src/service/storage/github.js +377 -0
- package/dist/src/service/storage/leancloud.js +430 -0
- package/dist/src/service/storage/mongodb.js +179 -0
- package/dist/src/service/storage/mysql.js +123 -0
- package/dist/src/service/storage/postgresql.js +84 -0
- package/dist/src/service/storage/sqlite.js +11 -0
- package/dist/src/service/storage/tidb.js +3 -0
- package/package.json +1 -1
- package/src/controller/comment.js +1 -2
- package/src/extend/think.js +19 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const qs = require('querystring');
|
|
3
|
+
const fetch = require('node-fetch');
|
|
4
|
+
const jwt = require('jsonwebtoken');
|
|
5
|
+
const helper = require('think-helper');
|
|
6
|
+
|
|
7
|
+
module.exports = class extends think.Logic {
|
|
8
|
+
constructor(...args) {
|
|
9
|
+
super(...args);
|
|
10
|
+
this.modelInstance = this.service(
|
|
11
|
+
`storage/${this.config('storage')}`,
|
|
12
|
+
'Users'
|
|
13
|
+
);
|
|
14
|
+
this.resource = this.getResource();
|
|
15
|
+
this.id = this.getId();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async __before() {
|
|
19
|
+
const referrer = this.ctx.referrer(true);
|
|
20
|
+
let { secureDomains } = this.config();
|
|
21
|
+
|
|
22
|
+
if (secureDomains && referrer && this.ctx.host.indexOf(referrer) !== 0) {
|
|
23
|
+
secureDomains = think.isArray(secureDomains)
|
|
24
|
+
? secureDomains
|
|
25
|
+
: [secureDomains];
|
|
26
|
+
secureDomains.push(
|
|
27
|
+
'localhost',
|
|
28
|
+
'127.0.0.1',
|
|
29
|
+
'github.com',
|
|
30
|
+
'api.twitter.com',
|
|
31
|
+
'www.facebook.com'
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const match = secureDomains.some((domain) =>
|
|
35
|
+
think.isFunction(domain.test)
|
|
36
|
+
? domain.test(referrer)
|
|
37
|
+
: domain === referrer
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (!match) {
|
|
41
|
+
return this.ctx.throw(403);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.ctx.state.userInfo = {};
|
|
46
|
+
const { authorization } = this.ctx.req.headers;
|
|
47
|
+
const { state } = this.get();
|
|
48
|
+
|
|
49
|
+
if (!authorization && !state) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const token = state || authorization.replace(/^Bearer /, '');
|
|
53
|
+
let userMail = '';
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
userMail = jwt.verify(token, think.config('jwtKey'));
|
|
57
|
+
} catch (e) {
|
|
58
|
+
think.logger.debug(e);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (think.isEmpty(userMail) || !think.isString(userMail)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const user = await this.modelInstance.select(
|
|
66
|
+
{ email: userMail },
|
|
67
|
+
{
|
|
68
|
+
field: [
|
|
69
|
+
'id',
|
|
70
|
+
'email',
|
|
71
|
+
'url',
|
|
72
|
+
'display_name',
|
|
73
|
+
'type',
|
|
74
|
+
'github',
|
|
75
|
+
'twitter',
|
|
76
|
+
'facebook',
|
|
77
|
+
'google',
|
|
78
|
+
'weibo',
|
|
79
|
+
'qq',
|
|
80
|
+
'avatar',
|
|
81
|
+
'2fa',
|
|
82
|
+
'label',
|
|
83
|
+
],
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
if (think.isEmpty(user)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const userInfo = user[0];
|
|
92
|
+
|
|
93
|
+
let avatarUrl = userInfo.avatar
|
|
94
|
+
? userInfo.avatar
|
|
95
|
+
: await think.service('avatar').stringify({
|
|
96
|
+
mail: userInfo.email,
|
|
97
|
+
nick: userInfo.display_name,
|
|
98
|
+
link: userInfo.url,
|
|
99
|
+
});
|
|
100
|
+
const { avatarProxy } = think.config();
|
|
101
|
+
|
|
102
|
+
if (avatarProxy) {
|
|
103
|
+
avatarUrl = avatarProxy + '?url=' + encodeURIComponent(avatarUrl);
|
|
104
|
+
}
|
|
105
|
+
userInfo.avatar = avatarUrl;
|
|
106
|
+
userInfo.mailMd5 = helper.md5(userInfo.email);
|
|
107
|
+
this.ctx.state.userInfo = userInfo;
|
|
108
|
+
this.ctx.state.token = token;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getResource() {
|
|
112
|
+
const filename = this.__filename || __filename;
|
|
113
|
+
const last = filename.lastIndexOf(path.sep);
|
|
114
|
+
|
|
115
|
+
return filename.substr(last + 1, filename.length - last - 4);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
getId() {
|
|
119
|
+
const id = this.get('id');
|
|
120
|
+
|
|
121
|
+
if (id && (think.isString(id) || think.isNumber(id))) {
|
|
122
|
+
return id;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const last = decodeURIComponent(this.ctx.path.split('/').pop());
|
|
126
|
+
|
|
127
|
+
if (last !== this.resource && /^([a-z0-9]+,?)*$/i.test(last)) {
|
|
128
|
+
return last;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return '';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async useCaptchaCheck() {
|
|
135
|
+
const { RECAPTCHA_V3_SECRET } = process.env;
|
|
136
|
+
|
|
137
|
+
if (!RECAPTCHA_V3_SECRET) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const { recaptchaV3 } = this.post();
|
|
141
|
+
|
|
142
|
+
if (!recaptchaV3) {
|
|
143
|
+
return this.ctx.throw(403);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const query = qs.stringify({
|
|
147
|
+
secret: RECAPTCHA_V3_SECRET,
|
|
148
|
+
response: recaptchaV3,
|
|
149
|
+
remoteip: this.ctx.ip,
|
|
150
|
+
});
|
|
151
|
+
const recaptchaV3Result = await fetch(
|
|
152
|
+
`https://recaptcha.net/recaptcha/api/siteverify?${query}`
|
|
153
|
+
).then((resp) => resp.json());
|
|
154
|
+
|
|
155
|
+
if (!recaptchaV3Result.success) {
|
|
156
|
+
think.logger.debug(
|
|
157
|
+
'RecaptchaV3 Result:',
|
|
158
|
+
JSON.stringify(recaptchaV3Result, null, '\t')
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
return this.ctx.throw(403);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
const Base = require('./base');
|
|
2
|
+
|
|
3
|
+
module.exports = class extends Base {
|
|
4
|
+
checkAdmin() {
|
|
5
|
+
const { userInfo } = this.ctx.state;
|
|
6
|
+
|
|
7
|
+
if (think.isEmpty(userInfo)) {
|
|
8
|
+
return this.ctx.throw(401);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (userInfo.type !== 'administrator') {
|
|
12
|
+
return this.ctx.throw(403);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @api {GET} /comment Get comment list for client
|
|
18
|
+
* @apiGroup Comment
|
|
19
|
+
* @apiVersion 0.0.1
|
|
20
|
+
*
|
|
21
|
+
* @apiParam {String} path comment url path
|
|
22
|
+
* @apiParam {String} page page
|
|
23
|
+
* @apiParam {String} pageSize page size
|
|
24
|
+
* @apiParam {String} sortBy comment sort type, one of 'insertedAt_desc', 'insertedAt_asc', 'like_desc'
|
|
25
|
+
* @apiParam {String} lang language
|
|
26
|
+
*
|
|
27
|
+
* @apiSuccess (200) {Number} page return current comments list page
|
|
28
|
+
* @apiSuccess (200) {Number} pageSize to return error message if error
|
|
29
|
+
* @apiSuccess (200) {Object[]} data comments list
|
|
30
|
+
* @apiSuccess (200) {String} data.nick comment user nick name
|
|
31
|
+
* @apiSuccess (200) {String} data.mail comment user mail md5
|
|
32
|
+
* @apiSuccess (200) {String} data.link comment user link
|
|
33
|
+
* @apiSuccess (200) {String} data.objectId comment id
|
|
34
|
+
* @apiSuccess (200) {String} data.browser comment user browser
|
|
35
|
+
* @apiSuccess (200) {String} data.os comment user os
|
|
36
|
+
* @apiSuccess (200) {String} data.insertedAt comment created time
|
|
37
|
+
* @apiSuccess (200) {String} data.avatar comment user avatar
|
|
38
|
+
* @apiSuccess (200) {String} data.type comment login user type
|
|
39
|
+
* @apiSuccess (200) {Object[]} data.children children comments list
|
|
40
|
+
* @apiSuccess (200) {String} data.children.nick comment user nick name
|
|
41
|
+
* @apiSuccess (200) {String} data.children.mail comment user mail md5
|
|
42
|
+
* @apiSuccess (200) {String} data.children.link comment user link
|
|
43
|
+
* @apiSuccess (200) {String} data.children.objectId comment id
|
|
44
|
+
* @apiSuccess (200) {String} data.children.browser comment user browser
|
|
45
|
+
* @apiSuccess (200) {String} data.children.os comment user os
|
|
46
|
+
* @apiSuccess (200) {String} data.children.insertedAt comment created time
|
|
47
|
+
* @apiSuccess (200) {String} data.children.avatar comment user avatar
|
|
48
|
+
* @apiSuccess (200) {String} data.children.type comment login user type
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* @api {GET} /comment?type=list Get comment list for admin
|
|
52
|
+
* @apiGroup Comment
|
|
53
|
+
* @apiVersion 0.0.1
|
|
54
|
+
*
|
|
55
|
+
* @apiParam {String} page page
|
|
56
|
+
* @apiParam {String} pageSize page size
|
|
57
|
+
* @apiParam {String} lang language
|
|
58
|
+
*
|
|
59
|
+
* @apiSuccess (200) {Number} errno 0
|
|
60
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
61
|
+
* @apiSuccess (200) {Object} data
|
|
62
|
+
* @apiSuccess (200) {Number} data.page comments list current page
|
|
63
|
+
* @apiSuccess (200) {Number} data.pageSize comments list page size
|
|
64
|
+
* @apiSuccess (200) {Number} data.totalPages comments list total pages
|
|
65
|
+
* @apiSuccess (200) {Number} data.spamCount spam comments count
|
|
66
|
+
* @apiSuccess (200) {Number} data.waitingCount waiting comments count
|
|
67
|
+
* @apiSuccess (200) {Object[]} data.data comments list data
|
|
68
|
+
* @apiSuccess (200) {String} data.data.ip comment user ip address
|
|
69
|
+
* @apiSuccess (200) {String} data.data.nick comment user nick name
|
|
70
|
+
* @apiSuccess (200) {String} data.data.mail comment user mail md5
|
|
71
|
+
* @apiSuccess (200) {String} data.data.link comment user link
|
|
72
|
+
* @apiSuccess (200) {String} data.data.objectId comment id
|
|
73
|
+
* @apiSuccess (200) {String} data.data.status comment status, approved, waiting or spam
|
|
74
|
+
* @apiSuccess (200) {String} data.data.ua comment user agent
|
|
75
|
+
* @apiSuccess (200) {String} data.data.insertedAt comment created time
|
|
76
|
+
* @apiSuccess (200) {String} data.data.avatar comment user avatar
|
|
77
|
+
* @apiSuccess (200) {String} data.data.url comment article link
|
|
78
|
+
*/
|
|
79
|
+
/**
|
|
80
|
+
* @api {GET} /comment?type=count Get comment count for articles
|
|
81
|
+
* @apiGroup Comment
|
|
82
|
+
* @apiVersion 0.0.1
|
|
83
|
+
*
|
|
84
|
+
* @apiParam {String} url a array string join by comma just like `a` or `a,b`, return site comment count if url empty
|
|
85
|
+
* @apiParam {String} lang language
|
|
86
|
+
*
|
|
87
|
+
* @apiSuccessExample {Number} Single Path Response:
|
|
88
|
+
* 300
|
|
89
|
+
* @apiSuccessExample {Number} Multiple Path Response:
|
|
90
|
+
* [300, 100]
|
|
91
|
+
*/
|
|
92
|
+
/**
|
|
93
|
+
* @api {GET} /comment?type=recent Get recent comments
|
|
94
|
+
* @apiGroup Comment
|
|
95
|
+
* @apiVersion 0.0.1
|
|
96
|
+
*
|
|
97
|
+
* @apiParam {String} count return comments number, default value is 10
|
|
98
|
+
* @apiParam {String} lang language
|
|
99
|
+
*
|
|
100
|
+
* @apiSuccess (200) {Object[]} response
|
|
101
|
+
* @apiSuccess (200) {String} response.nick comment user nick name
|
|
102
|
+
* @apiSuccess (200) {String} response.mail comment user mail md5
|
|
103
|
+
* @apiSuccess (200) {String} response.link comment user link
|
|
104
|
+
* @apiSuccess (200) {String} response.objectId comment id
|
|
105
|
+
* @apiSuccess (200) {String} response.browser comment user browser
|
|
106
|
+
* @apiSuccess (200) {String} response.os comment user os
|
|
107
|
+
* @apiSuccess (200) {String} response.insertedAt comment created time
|
|
108
|
+
* @apiSuccess (200) {String} response.avatar comment user avatar
|
|
109
|
+
* @apiSuccess (200) {String} response.type comment login user type
|
|
110
|
+
*/
|
|
111
|
+
getAction() {
|
|
112
|
+
const { type, path } = this.get();
|
|
113
|
+
const isAllowedGet = type !== 'list' || path;
|
|
114
|
+
|
|
115
|
+
if (!isAllowedGet) {
|
|
116
|
+
this.checkAdmin();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
switch (type) {
|
|
120
|
+
case 'recent':
|
|
121
|
+
this.rules = {
|
|
122
|
+
count: {
|
|
123
|
+
int: { max: 50 },
|
|
124
|
+
default: 10,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
break;
|
|
128
|
+
|
|
129
|
+
case 'count':
|
|
130
|
+
this.rules = {
|
|
131
|
+
url: {
|
|
132
|
+
array: true,
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
break;
|
|
136
|
+
|
|
137
|
+
case 'list': {
|
|
138
|
+
const { userInfo } = this.ctx.state;
|
|
139
|
+
|
|
140
|
+
if (userInfo.type !== 'administrator') {
|
|
141
|
+
return this.fail();
|
|
142
|
+
}
|
|
143
|
+
this.rules = {
|
|
144
|
+
page: {
|
|
145
|
+
int: true,
|
|
146
|
+
default: 1,
|
|
147
|
+
},
|
|
148
|
+
pageSize: {
|
|
149
|
+
int: { max: 100 },
|
|
150
|
+
default: 10,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
default:
|
|
157
|
+
this.rules = {
|
|
158
|
+
path: {
|
|
159
|
+
string: true,
|
|
160
|
+
required: true,
|
|
161
|
+
},
|
|
162
|
+
page: {
|
|
163
|
+
int: true,
|
|
164
|
+
default: 1,
|
|
165
|
+
},
|
|
166
|
+
pageSize: {
|
|
167
|
+
int: { max: 100 },
|
|
168
|
+
default: 10,
|
|
169
|
+
},
|
|
170
|
+
sortBy: {
|
|
171
|
+
in: ['insertedAt_desc', 'insertedAt_asc', 'like_desc'],
|
|
172
|
+
default: 'insertedAt_desc',
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @api {POST} /comment post comment
|
|
181
|
+
* @apiGroup Comment
|
|
182
|
+
* @apiVersion 0.0.1
|
|
183
|
+
*
|
|
184
|
+
* @apiParam {String} nick post comment user nick name
|
|
185
|
+
* @apiParam {String} mail post comment user mail address
|
|
186
|
+
* @apiParam {String} link post comment user link
|
|
187
|
+
* @apiParam {String} comment post comment text
|
|
188
|
+
* @apiParam {String} url the article url path of comment
|
|
189
|
+
* @apiParam {String} ua browser user agent
|
|
190
|
+
* @apiParam {String} pid parent comment id
|
|
191
|
+
* @apiParam {String} rid root comment id
|
|
192
|
+
* @apiParam {String} at parent comment user nick name
|
|
193
|
+
* @apiParam {String} lang language
|
|
194
|
+
*
|
|
195
|
+
* @apiSuccess (200) {Number} errno 0
|
|
196
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
197
|
+
* @apiSuccess (200) {Object} data return comment data
|
|
198
|
+
* @apiSuccess (200) {String} data.nick comment user nick name
|
|
199
|
+
* @apiSuccess (200) {String} data.mail comment user mail md5
|
|
200
|
+
* @apiSuccess (200) {String} data.link comment user link
|
|
201
|
+
* @apiSuccess (200) {String} data.objectId comment id
|
|
202
|
+
* @apiSuccess (200) {String} data.browser comment user browser
|
|
203
|
+
* @apiSuccess (200) {String} data.os comment user os
|
|
204
|
+
* @apiSuccess (200) {String} data.insertedAt comment created time
|
|
205
|
+
* @apiSuccess (200) {String} data.avatar comment user avatar
|
|
206
|
+
* @apiSuccess (200) {String} data.type comment login user type
|
|
207
|
+
*/
|
|
208
|
+
async postAction() {
|
|
209
|
+
const { LOGIN } = process.env;
|
|
210
|
+
const { userInfo } = this.ctx.state;
|
|
211
|
+
|
|
212
|
+
if (!think.isEmpty(userInfo)) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (LOGIN === 'force') {
|
|
217
|
+
return this.ctx.throw(401);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return this.useCaptchaCheck();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @api {PUT} /comment/:id update comment data
|
|
225
|
+
* @apiGroup Comment
|
|
226
|
+
* @apiVersion 0.0.1
|
|
227
|
+
*
|
|
228
|
+
* @apiParam {String} [nick] post comment user nick name
|
|
229
|
+
* @apiParam {String} [mail] post comment user mail address
|
|
230
|
+
* @apiParam {String} [link] post comment user link
|
|
231
|
+
* @apiParam {String} [comment] post comment text
|
|
232
|
+
* @apiParam {String} [url] the article url path of comment
|
|
233
|
+
* @apiParam {Boolean} [like] like comment
|
|
234
|
+
* @apiParam {String} lang language
|
|
235
|
+
*
|
|
236
|
+
* @apiSuccess (200) {Number} errno 0
|
|
237
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
238
|
+
*/
|
|
239
|
+
async putAction() {
|
|
240
|
+
const { userInfo } = this.ctx.state;
|
|
241
|
+
const { like } = this.post();
|
|
242
|
+
|
|
243
|
+
// 1. like
|
|
244
|
+
if (think.isEmpty(userInfo) && think.isBoolean(like)) {
|
|
245
|
+
this.rules = {
|
|
246
|
+
like: {
|
|
247
|
+
required: true,
|
|
248
|
+
boolean: true,
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (think.isEmpty(userInfo)) {
|
|
256
|
+
return this.ctx.throw(401);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 2. administrator
|
|
260
|
+
if (userInfo.type === 'administrator') {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// 3. comment author modify comment content
|
|
265
|
+
const modelInstance = this.service(
|
|
266
|
+
`storage/${this.config('storage')}`,
|
|
267
|
+
'Comment'
|
|
268
|
+
);
|
|
269
|
+
const commentData = await modelInstance.select({
|
|
270
|
+
user_id: userInfo.objectId,
|
|
271
|
+
objectId: this.id,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
if (!think.isEmpty(commentData)) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return this.ctx.throw(403);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* @api {DELETE} /comment/:id delete comment
|
|
283
|
+
* @apiGroup Comment
|
|
284
|
+
* @apiVersion 0.0.1
|
|
285
|
+
*
|
|
286
|
+
* @apiParam {String} lang language
|
|
287
|
+
*
|
|
288
|
+
* @apiSuccess (200) {Number} errno 0
|
|
289
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
290
|
+
*/
|
|
291
|
+
async deleteAction() {
|
|
292
|
+
const { userInfo } = this.ctx.state;
|
|
293
|
+
|
|
294
|
+
if (think.isEmpty(userInfo)) {
|
|
295
|
+
return this.ctx.throw(401);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (userInfo.type === 'administrator') {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const modelInstance = this.service(
|
|
303
|
+
`storage/${this.config('storage')}`,
|
|
304
|
+
'Comment'
|
|
305
|
+
);
|
|
306
|
+
const commentData = await modelInstance.select({
|
|
307
|
+
user_id: userInfo.objectId,
|
|
308
|
+
objectId: this.id,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
if (!think.isEmpty(commentData)) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return this.ctx.throw(403);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const Base = require('./base');
|
|
2
|
+
|
|
3
|
+
module.exports = class extends Base {
|
|
4
|
+
async __before(...args) {
|
|
5
|
+
await super.__before(...args);
|
|
6
|
+
|
|
7
|
+
const { userInfo } = this.ctx.state;
|
|
8
|
+
|
|
9
|
+
if (think.isEmpty(userInfo)) {
|
|
10
|
+
return this.fail(401);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (userInfo.type !== 'administrator') {
|
|
14
|
+
return this.fail(403);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @api {GET} /db export site data
|
|
20
|
+
* @apiGroup Site
|
|
21
|
+
* @apiVersion 0.0.1
|
|
22
|
+
*
|
|
23
|
+
* @apiParam {String} lang language
|
|
24
|
+
*/
|
|
25
|
+
async getAction() {}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @api {POST} /db import site data
|
|
29
|
+
* @apiGroup Site
|
|
30
|
+
* @apiVersion 0.0.1
|
|
31
|
+
*
|
|
32
|
+
* @apiParam {String} lang language
|
|
33
|
+
*/
|
|
34
|
+
async postAction() {
|
|
35
|
+
this.rules = {
|
|
36
|
+
table: {
|
|
37
|
+
string: true,
|
|
38
|
+
required: true,
|
|
39
|
+
method: 'GET',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @api {PUT} /db update site table data
|
|
46
|
+
* @apiGroup Site
|
|
47
|
+
* @apiVersion 0.0.1
|
|
48
|
+
*
|
|
49
|
+
* @apiParam {String} lang language
|
|
50
|
+
*/
|
|
51
|
+
async putAction() {
|
|
52
|
+
this.rules = {
|
|
53
|
+
table: {
|
|
54
|
+
string: true,
|
|
55
|
+
required: true,
|
|
56
|
+
method: 'GET',
|
|
57
|
+
},
|
|
58
|
+
objectId: {
|
|
59
|
+
required: true,
|
|
60
|
+
method: 'GET',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @api {DELETE} /db clean site data
|
|
67
|
+
* @apiGroup Site
|
|
68
|
+
* @apiVersion 0.0.1
|
|
69
|
+
*
|
|
70
|
+
* @apiParam {String} lang language
|
|
71
|
+
*/
|
|
72
|
+
async deleteAction() {
|
|
73
|
+
this.rules = {
|
|
74
|
+
table: {
|
|
75
|
+
string: true,
|
|
76
|
+
required: true,
|
|
77
|
+
method: 'GET',
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const Base = require('../base');
|
|
2
|
+
|
|
3
|
+
module.exports = class extends Base {
|
|
4
|
+
async getAction() {
|
|
5
|
+
const { email } = this.get();
|
|
6
|
+
const { userInfo } = this.ctx.state;
|
|
7
|
+
|
|
8
|
+
if (think.isEmpty(userInfo) && !email) {
|
|
9
|
+
return this.fail(401);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async postAction() {
|
|
14
|
+
const { userInfo } = this.ctx.state;
|
|
15
|
+
|
|
16
|
+
if (think.isEmpty(userInfo)) {
|
|
17
|
+
return this.fail(401);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
this.rules = {
|
|
21
|
+
code: {
|
|
22
|
+
required: true,
|
|
23
|
+
string: true,
|
|
24
|
+
length: 6,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const Base = require('./base');
|
|
2
|
+
|
|
3
|
+
module.exports = class extends Base {
|
|
4
|
+
/**
|
|
5
|
+
* @api {GET} /token get login user info
|
|
6
|
+
* @apiGroup User
|
|
7
|
+
* @apiVersion 0.0.1
|
|
8
|
+
*
|
|
9
|
+
* @apiParam {String} lang language
|
|
10
|
+
*
|
|
11
|
+
* @apiSuccess (200) {Number} errno 0
|
|
12
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
13
|
+
* @apiSuccess (200) {Object} data user info
|
|
14
|
+
* @apiSuccess (200) {String} data.avatar user avatar
|
|
15
|
+
* @apiSuccess (200) {String} data.createdAt user register time
|
|
16
|
+
* @apiSuccess (200) {String} data.display_name user nick name
|
|
17
|
+
* @apiSuccess (200) {String} data.email user email address
|
|
18
|
+
* @apiSuccess (200) {String} data.github user github account name
|
|
19
|
+
* @apiSuccess (200) {String} data.mailMd5 user mail md5
|
|
20
|
+
* @apiSuccess (200) {String} data.objectId user id
|
|
21
|
+
* @apiSuccess (200) {String} data.type user type, administrator or guest
|
|
22
|
+
* @apiSuccess (200) {String} data.url user link
|
|
23
|
+
*/
|
|
24
|
+
getAction() {}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @api {POST} /token user login
|
|
28
|
+
* @apiGroup User
|
|
29
|
+
* @apiVersion 0.0.1
|
|
30
|
+
*
|
|
31
|
+
* @apiParam {String} email login user email
|
|
32
|
+
* @apiParam {String} password login user password
|
|
33
|
+
* @apiParam {String} lang language
|
|
34
|
+
*
|
|
35
|
+
* @apiSuccess (200) {Number} errno 0
|
|
36
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
37
|
+
*/
|
|
38
|
+
postAction() {
|
|
39
|
+
return this.useCaptchaCheck();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @api {DELETE} /token user logout
|
|
44
|
+
* @apiGroup User
|
|
45
|
+
* @apiVersion 0.0.1
|
|
46
|
+
*
|
|
47
|
+
* @apiParam {String} lang language
|
|
48
|
+
*
|
|
49
|
+
* @apiSuccess (200) {Number} errno 0
|
|
50
|
+
* @apiSuccess (200) {String} errmsg return error message if error
|
|
51
|
+
*/
|
|
52
|
+
deleteAction() {}
|
|
53
|
+
};
|