@azteam/express 1.2.118 → 1.2.121
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/AdminController.js +67 -83
- package/src/ApiServer.js +40 -28
- package/src/Controller.js +21 -12
- package/src/constant.js +0 -8
- package/src/index.js +3 -1
- package/src/middleware/etagMiddleware.js +1 -2
package/package.json
CHANGED
package/src/AdminController.js
CHANGED
|
@@ -1,194 +1,178 @@
|
|
|
1
|
-
import { NOT_EXISTS
|
|
1
|
+
import { NOT_EXISTS } from '@azteam/error';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { REQUEST_TYPE, USER_LEVEL } from './constant';
|
|
4
|
+
import { paginateMiddleware, roleMiddleware, validateMiddleware } from './middleware';
|
|
5
|
+
import { rulesID } from './validate';
|
|
4
6
|
import Controller from './Controller';
|
|
5
7
|
|
|
6
|
-
import { USER_LEVEL } from './constant';
|
|
7
|
-
|
|
8
8
|
|
|
9
9
|
class AdminController extends Controller {
|
|
10
10
|
constructor(pathName, repository, options = {}) {
|
|
11
|
-
|
|
11
|
+
super(pathName, repository, {
|
|
12
12
|
roles: {
|
|
13
13
|
READ: 1,
|
|
14
14
|
CREATE: 2,
|
|
15
15
|
UPDATE: 3,
|
|
16
16
|
DELETE: 4,
|
|
17
|
-
RESTORE: 5
|
|
17
|
+
RESTORE: 5
|
|
18
18
|
}, // system roles
|
|
19
19
|
|
|
20
|
+
paginateOptions: {},
|
|
20
21
|
rulesCreate: {},
|
|
21
22
|
rulesModify: {},
|
|
22
23
|
|
|
23
24
|
guardResponse: {},
|
|
24
25
|
allowResponse: {},
|
|
25
26
|
|
|
26
|
-
...options
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
super(pathName, repository);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
usePublic(controllers = []){
|
|
34
|
-
return super([
|
|
35
|
-
getPaginate,
|
|
36
|
-
getPaginateTrash,
|
|
37
|
-
getOne,
|
|
38
|
-
getOneTrash,
|
|
39
|
-
postCreate,
|
|
40
|
-
putModify,
|
|
41
|
-
deleteOne,
|
|
42
|
-
postRestore,
|
|
43
|
-
]);
|
|
27
|
+
...options
|
|
28
|
+
});
|
|
44
29
|
}
|
|
45
30
|
|
|
46
|
-
|
|
47
31
|
getPaginate() {
|
|
48
32
|
return {
|
|
49
|
-
path:
|
|
33
|
+
path: '/public',
|
|
50
34
|
method: [
|
|
51
35
|
roleMiddleware([this.options.roles.READ], USER_LEVEL.ADMIN),
|
|
52
|
-
paginateMiddleware(paginateOptions),
|
|
53
|
-
async
|
|
36
|
+
paginateMiddleware(this.options.paginateOptions),
|
|
37
|
+
async (req, res) => {
|
|
54
38
|
const paginateData = await this.repository.find(req.query, req.paginate);
|
|
55
39
|
|
|
56
40
|
return res.success(paginateData, this.options.guardResponse, this.options.allowResponse);
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
};
|
|
61
45
|
|
|
62
46
|
getPaginateTrash() {
|
|
63
47
|
return {
|
|
64
|
-
path:
|
|
48
|
+
path: '/trash',
|
|
65
49
|
method: [
|
|
66
50
|
roleMiddleware([this.options.roles.READ], USER_LEVEL.ADMIN),
|
|
67
|
-
paginateMiddleware(paginateOptions),
|
|
68
|
-
async
|
|
51
|
+
paginateMiddleware(this.options.paginateOptions),
|
|
52
|
+
async (req, res) => {
|
|
69
53
|
const paginateData = await this.repository.findTrash(req.query, req.paginate);
|
|
70
54
|
|
|
71
55
|
return res.success(paginateData, this.options.guardResponse, this.options.allowResponse);
|
|
72
|
-
}
|
|
73
|
-
]
|
|
74
|
-
}
|
|
75
|
-
}
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
};
|
|
59
|
+
};
|
|
76
60
|
|
|
77
61
|
getOne() {
|
|
78
62
|
return {
|
|
79
|
-
path:
|
|
63
|
+
path: '/public/:id',
|
|
80
64
|
method: [
|
|
81
65
|
roleMiddleware([this.options.roles.READ], USER_LEVEL.ADMIN),
|
|
82
66
|
validateMiddleware(REQUEST_TYPE.PARAMS, rulesID),
|
|
83
|
-
async
|
|
67
|
+
async (req, res) => {
|
|
84
68
|
const item = await this.repository.findOneById(req.params.id);
|
|
85
69
|
if (!item) return res.error(NOT_EXISTS);
|
|
86
70
|
return res.success(item, this.options.guardResponse, this.options.allowResponse);
|
|
87
|
-
}
|
|
88
|
-
]
|
|
89
|
-
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
};
|
|
90
74
|
|
|
91
|
-
}
|
|
75
|
+
};
|
|
92
76
|
|
|
93
77
|
getOneTrash() {
|
|
94
78
|
return {
|
|
95
|
-
path:
|
|
79
|
+
path: '/trash/:id',
|
|
96
80
|
method: [
|
|
97
81
|
roleMiddleware([this.options.roles.READ], USER_LEVEL.ADMIN),
|
|
98
82
|
validateMiddleware(REQUEST_TYPE.PARAMS, rulesID),
|
|
99
|
-
async
|
|
83
|
+
async (req, res) => {
|
|
100
84
|
const item = await this.repository.findOneTrashById(req.params.id);
|
|
101
85
|
if (!item) return res.error(NOT_EXISTS);
|
|
102
86
|
return res.success(item, this.options.guardResponse, this.options.allowResponse);
|
|
103
|
-
}
|
|
104
|
-
]
|
|
105
|
-
}
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
};
|
|
106
90
|
|
|
107
|
-
}
|
|
91
|
+
};
|
|
108
92
|
|
|
109
93
|
|
|
110
|
-
|
|
94
|
+
async beforeCreate(data, user) {
|
|
111
95
|
return data;
|
|
112
|
-
}
|
|
96
|
+
};
|
|
113
97
|
|
|
114
98
|
postCreate() {
|
|
115
99
|
return {
|
|
116
|
-
path:
|
|
100
|
+
path: '/public',
|
|
117
101
|
method: [
|
|
118
102
|
roleMiddleware([this.options.roles.CREATE], USER_LEVEL.ADMIN),
|
|
119
103
|
validateMiddleware(REQUEST_TYPE.BODY, this.options.rulesCreate),
|
|
120
|
-
async
|
|
104
|
+
async (req, res) => {
|
|
121
105
|
|
|
122
|
-
const data = this.
|
|
106
|
+
const data = await this.beforeCreate(req.body, req.user);
|
|
123
107
|
|
|
124
108
|
const item = await this.repository.createByUser(req.user.id, data);
|
|
125
109
|
|
|
126
110
|
return res.success(item, this.options.guardResponse, this.options.allowResponse);
|
|
127
|
-
}
|
|
128
|
-
]
|
|
129
|
-
}
|
|
130
|
-
}
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
};
|
|
114
|
+
};
|
|
131
115
|
|
|
132
116
|
|
|
133
|
-
|
|
117
|
+
async beforeModify(item, user) {
|
|
134
118
|
return item;
|
|
135
|
-
}
|
|
119
|
+
};
|
|
136
120
|
|
|
137
121
|
putModify() {
|
|
138
122
|
return {
|
|
139
|
-
path:
|
|
123
|
+
path: '/public/:id',
|
|
140
124
|
method: [
|
|
141
125
|
roleMiddleware([this.options.roles.UPDATE], USER_LEVEL.ADMIN),
|
|
142
126
|
validateMiddleware(REQUEST_TYPE.PARAMS, rulesID),
|
|
143
127
|
validateMiddleware(REQUEST_TYPE.BODY, this.options.rulesModify),
|
|
144
|
-
async
|
|
128
|
+
async (req, res) => {
|
|
145
129
|
|
|
146
130
|
let item = await this.options.roles.findOneById(req.params.id);
|
|
147
131
|
if (!item) return res.error(NOT_EXISTS);
|
|
148
132
|
|
|
149
|
-
item = await this.
|
|
133
|
+
item = await this.beforeModify(item, req.user);
|
|
150
134
|
|
|
151
135
|
item = await this.options.roles.modifyByUser(req.user.id, item, req.body);
|
|
152
136
|
|
|
153
137
|
return res.success(item, this.options.guardResponse, this.options.allowResponse);
|
|
154
|
-
}
|
|
155
|
-
]
|
|
156
|
-
}
|
|
157
|
-
}
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
};
|
|
141
|
+
};
|
|
158
142
|
|
|
159
|
-
|
|
143
|
+
delete() {
|
|
160
144
|
return {
|
|
161
|
-
path:
|
|
145
|
+
path: '/public/:id',
|
|
162
146
|
method: [
|
|
163
147
|
roleMiddleware([this.options.roles.DELETE], USER_LEVEL.ADMIN),
|
|
164
148
|
validateMiddleware(REQUEST_TYPE.PARAMS, rulesID),
|
|
165
|
-
async
|
|
149
|
+
async (req, res) => {
|
|
166
150
|
const item = await this.repository.findOneById(req.params.id);
|
|
167
151
|
if (!item) return res.error(NOT_EXISTS);
|
|
168
152
|
|
|
169
153
|
await this.repository.deleteByUser(req.user.id, item);
|
|
170
154
|
return res.success(true);
|
|
171
|
-
}
|
|
172
|
-
]
|
|
173
|
-
}
|
|
174
|
-
}
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
};
|
|
158
|
+
};
|
|
175
159
|
|
|
176
160
|
postRestore() {
|
|
177
161
|
return {
|
|
178
|
-
path:
|
|
162
|
+
path: '/trash/:id',
|
|
179
163
|
method: [
|
|
180
164
|
roleMiddleware([this.options.roles.RESTORE], USER_LEVEL.ADMIN),
|
|
181
165
|
validateMiddleware(REQUEST_TYPE.PARAMS, rulesID),
|
|
182
|
-
async
|
|
166
|
+
async (req, res) => {
|
|
183
167
|
const item = await this.repository.findOneTrashById(req.params.id);
|
|
184
168
|
if (!item) return res.error(NOT_EXISTS);
|
|
185
169
|
|
|
186
170
|
await this.repository.restoreByUser(req.user.id, item);
|
|
187
171
|
return res.success(true);
|
|
188
|
-
}
|
|
189
|
-
]
|
|
190
|
-
}
|
|
191
|
-
}
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
};
|
|
175
|
+
};
|
|
192
176
|
}
|
|
193
177
|
|
|
194
|
-
export default
|
|
178
|
+
export default AdminController;
|
package/src/ApiServer.js
CHANGED
|
@@ -9,8 +9,7 @@ import morgan from 'morgan';
|
|
|
9
9
|
import cors from 'cors';
|
|
10
10
|
import _ from 'lodash';
|
|
11
11
|
import 'express-async-errors';
|
|
12
|
-
import {
|
|
13
|
-
import { errorCatch, ErrorException, NOT_FOUND, UNKNOWN } from '@azteam/error';
|
|
12
|
+
import {errorCatch, ErrorException, NOT_FOUND, UNKNOWN} from '@azteam/error';
|
|
14
13
|
|
|
15
14
|
function omitItem(item, guard) {
|
|
16
15
|
if (item.toJSON) {
|
|
@@ -33,7 +32,7 @@ class ApiServer {
|
|
|
33
32
|
httpOnly: true,
|
|
34
33
|
signed: true,
|
|
35
34
|
sameSite: 'Lax'
|
|
36
|
-
}
|
|
35
|
+
};
|
|
37
36
|
|
|
38
37
|
this.middlewares = [];
|
|
39
38
|
this.controllers = [];
|
|
@@ -114,8 +113,8 @@ class ApiServer {
|
|
|
114
113
|
}));
|
|
115
114
|
|
|
116
115
|
app.use(methodOverride());
|
|
117
|
-
app.use(bodyParser.urlencoded({
|
|
118
|
-
app.use(bodyParser.json({
|
|
116
|
+
app.use(bodyParser.urlencoded({limit: '5mb', extended: true}));
|
|
117
|
+
app.use(bodyParser.json({limit: '5mb'}));
|
|
119
118
|
|
|
120
119
|
app.set('trust proxy', 1);
|
|
121
120
|
|
|
@@ -128,11 +127,11 @@ class ApiServer {
|
|
|
128
127
|
if (
|
|
129
128
|
!origin || !WHITE_LIST.length ||
|
|
130
129
|
WHITE_LIST.some(re => origin.endsWith(re))) {
|
|
131
|
-
callback(null, true)
|
|
130
|
+
callback(null, true);
|
|
132
131
|
} else {
|
|
133
132
|
callback(new Error(`${origin} Not allowed by CORS`));
|
|
134
133
|
}
|
|
135
|
-
}
|
|
134
|
+
}
|
|
136
135
|
}));
|
|
137
136
|
|
|
138
137
|
if (this.debug) {
|
|
@@ -150,13 +149,13 @@ class ApiServer {
|
|
|
150
149
|
ip: req.ip,
|
|
151
150
|
device: req.get('X-DEVICE') || req.get('User-Agent'),
|
|
152
151
|
device_id: req.get('X-DEVICE-ID') || 'web',
|
|
153
|
-
os: req.get('X-OS') || 'web'
|
|
154
|
-
}
|
|
152
|
+
os: req.get('X-OS') || 'web'
|
|
153
|
+
};
|
|
155
154
|
|
|
156
155
|
|
|
157
156
|
res.error = function(code, errors = []) {
|
|
158
157
|
throw new ErrorException(code, errors);
|
|
159
|
-
}
|
|
158
|
+
};
|
|
160
159
|
|
|
161
160
|
res.success = function(data = {}, guard = [], allows = []) {
|
|
162
161
|
if (data) {
|
|
@@ -176,7 +175,7 @@ class ApiServer {
|
|
|
176
175
|
'metadata_disable',
|
|
177
176
|
'metadata_keywords',
|
|
178
177
|
'metadata_description',
|
|
179
|
-
'metadata_image_url'
|
|
178
|
+
'metadata_image_url'
|
|
180
179
|
];
|
|
181
180
|
}
|
|
182
181
|
|
|
@@ -200,7 +199,7 @@ class ApiServer {
|
|
|
200
199
|
return res.json({
|
|
201
200
|
success: true,
|
|
202
201
|
data,
|
|
203
|
-
options: req.resOptions
|
|
202
|
+
options: req.resOptions
|
|
204
203
|
});
|
|
205
204
|
};
|
|
206
205
|
|
|
@@ -210,7 +209,7 @@ class ApiServer {
|
|
|
210
209
|
domain: COOKIE_OPTIONS.domain
|
|
211
210
|
});
|
|
212
211
|
});
|
|
213
|
-
}
|
|
212
|
+
};
|
|
214
213
|
|
|
215
214
|
res.addCookie = function(data) {
|
|
216
215
|
_.map(data, (value, key) => {
|
|
@@ -221,7 +220,7 @@ class ApiServer {
|
|
|
221
220
|
expires: new Date(Date.now() + maxAge)
|
|
222
221
|
});
|
|
223
222
|
});
|
|
224
|
-
}
|
|
223
|
+
};
|
|
225
224
|
next();
|
|
226
225
|
});
|
|
227
226
|
|
|
@@ -231,19 +230,32 @@ class ApiServer {
|
|
|
231
230
|
|
|
232
231
|
const msg = [];
|
|
233
232
|
_.map(this.controllers, (obj) => {
|
|
234
|
-
const controller = obj.controller;
|
|
235
|
-
_.map(controller, (item, key) => {
|
|
236
|
-
item.path = obj.version.startsWith('v') ? `/${obj.version}${item.path}` : item.path;
|
|
237
|
-
|
|
238
|
-
msg.push({
|
|
239
|
-
controller: obj.name,
|
|
240
|
-
version: obj.version,
|
|
241
|
-
type: item.type,
|
|
242
|
-
method: key,
|
|
243
|
-
path: item.path,
|
|
244
|
-
});
|
|
245
233
|
|
|
246
|
-
|
|
234
|
+
const {name, controller, version} = obj;
|
|
235
|
+
|
|
236
|
+
const listPublicMethod = obj.controller.publicMethod();
|
|
237
|
+
|
|
238
|
+
_.map(listPublicMethod, (methodName) => {
|
|
239
|
+
|
|
240
|
+
const matches = methodName.match(/get|post|put|patch|delete/);
|
|
241
|
+
if (matches) {
|
|
242
|
+
const type = matches[0];
|
|
243
|
+
const item = controller[methodName]();
|
|
244
|
+
|
|
245
|
+
item.path = controller.pathName ? `/${controller.pathName}${item.path}` : item.path;
|
|
246
|
+
|
|
247
|
+
item.path = version.startsWith('v') ? `/${version}${item.path}` : item.path;
|
|
248
|
+
|
|
249
|
+
msg.push({
|
|
250
|
+
controller: name,
|
|
251
|
+
version,
|
|
252
|
+
type,
|
|
253
|
+
method: methodName,
|
|
254
|
+
path: item.path
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
app[type](item.path, ...item.method);
|
|
258
|
+
}
|
|
247
259
|
});
|
|
248
260
|
});
|
|
249
261
|
|
|
@@ -268,7 +280,7 @@ class ApiServer {
|
|
|
268
280
|
this.callbackError(error);
|
|
269
281
|
}
|
|
270
282
|
|
|
271
|
-
return res.status(error.status).json({
|
|
283
|
+
return res.status(error.status).json({success: false, errors: error.errors});
|
|
272
284
|
});
|
|
273
285
|
|
|
274
286
|
const server = http.Server(app);
|
|
@@ -324,4 +336,4 @@ class ApiServer {
|
|
|
324
336
|
}
|
|
325
337
|
}
|
|
326
338
|
|
|
327
|
-
export default ApiServer;
|
|
339
|
+
export default ApiServer;
|
package/src/Controller.js
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import { NOT_EXISTS, PERMISSION } from '@azteam/error';
|
|
2
|
-
|
|
3
|
-
import { HTTP_METHOD, paginateMiddleware, REQUEST_TYPE, roleMiddleware, validateMiddleware, rulesID } from './ApiServer';
|
|
4
|
-
import { USER_LEVEL } from './constant';
|
|
5
|
-
|
|
6
|
-
|
|
7
1
|
class Controller {
|
|
8
|
-
constructor(pathName, repository) {
|
|
2
|
+
constructor(pathName = '', repository = null, options = {}) {
|
|
9
3
|
this.pathName = pathName;
|
|
10
4
|
this.repository = repository;
|
|
5
|
+
|
|
6
|
+
this.options = {
|
|
7
|
+
...options
|
|
8
|
+
};
|
|
11
9
|
}
|
|
12
10
|
|
|
11
|
+
publicMethod() {
|
|
12
|
+
let child = this;
|
|
13
|
+
let result = [];
|
|
14
|
+
|
|
15
|
+
while (Object.getPrototypeOf(child.__proto__)) {
|
|
16
|
+
|
|
17
|
+
const data = Object.getOwnPropertyNames(Object.getPrototypeOf(child));
|
|
18
|
+
|
|
19
|
+
result = [
|
|
20
|
+
...result,
|
|
21
|
+
...data.filter((methodName) => methodName.match(/^get|post|put|patch|delete/))
|
|
22
|
+
]
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
]
|
|
24
|
+
child = child.__proto__;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
18
27
|
}
|
|
19
28
|
}
|
|
20
29
|
|
|
21
|
-
export default Controller;
|
|
30
|
+
export default Controller;
|
package/src/constant.js
CHANGED
package/src/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ApiServer from './ApiServer';
|
|
2
2
|
import SocketServer from './SocketServer';
|
|
3
3
|
|
|
4
|
+
import Controller from './Controller';
|
|
4
5
|
import AdminController from './AdminController';
|
|
5
6
|
|
|
6
7
|
|
|
@@ -12,5 +13,6 @@ export {
|
|
|
12
13
|
ApiServer,
|
|
13
14
|
SocketServer,
|
|
14
15
|
|
|
16
|
+
Controller,
|
|
15
17
|
AdminController,
|
|
16
|
-
}
|
|
18
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import etag from 'etag';
|
|
2
2
|
|
|
3
|
-
import { HTTP_GET } from '../constant';
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
function floorToMinute(time, minutes) {
|
|
@@ -11,7 +10,7 @@ function floorToMinute(time, minutes) {
|
|
|
11
10
|
|
|
12
11
|
export default function(mTimeout = 5) {
|
|
13
12
|
return async function(req, res, next) {
|
|
14
|
-
if (req.method ===
|
|
13
|
+
if (req.method === 'GET') {
|
|
15
14
|
const etag_hash = etag(req.url + floorToMinute(Math.floor(Date.now() / 1000), mTimeout));
|
|
16
15
|
if (req.headers['if-none-match'] === etag_hash) {
|
|
17
16
|
return res.status(304).send();
|