@adaptivestone/framework 3.0.22 → 3.1.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/CHANGELOG.md
CHANGED
|
@@ -1,17 +1,51 @@
|
|
|
1
|
+
const fs = require('fs').promises;
|
|
2
|
+
|
|
1
3
|
const AbstractCommand = require('../modules/AbstractCommand');
|
|
2
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Command for generate documentation json file openApi
|
|
7
|
+
*/
|
|
3
8
|
class GetOpenApiJson extends AbstractCommand {
|
|
4
9
|
async run() {
|
|
5
10
|
const { myDomain } = this.app.getConfig('http');
|
|
11
|
+
let jsonFile = process.env.npm_package_json;
|
|
12
|
+
if (!jsonFile) {
|
|
13
|
+
jsonFile = `${process.env.PWD}/package.json`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// eslint-disable-next-line import/no-dynamic-require, global-require
|
|
18
|
+
jsonFile = require(jsonFile);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
this.logger.error(
|
|
21
|
+
'No npm package detected. Please start this command via NPM as it depends on package.json',
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!jsonFile) {
|
|
26
|
+
jsonFile = {
|
|
27
|
+
name: 'UNDETECTD PROJECT',
|
|
28
|
+
description: 'UNDETECTD PROJECT DECCRIPTION',
|
|
29
|
+
version: '0.0.0-undetrcted',
|
|
30
|
+
author: {
|
|
31
|
+
email: 'none@example.com',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!jsonFile.author) {
|
|
37
|
+
jsonFile.author = 'none@example.com';
|
|
38
|
+
}
|
|
39
|
+
|
|
6
40
|
const openApi = {
|
|
7
41
|
openapi: '3.0.0',
|
|
8
42
|
info: {
|
|
9
|
-
title:
|
|
10
|
-
description:
|
|
43
|
+
title: jsonFile.name,
|
|
44
|
+
description: jsonFile.description,
|
|
11
45
|
contact: {
|
|
12
|
-
email:
|
|
46
|
+
email: jsonFile.author.email,
|
|
13
47
|
},
|
|
14
|
-
version:
|
|
48
|
+
version: jsonFile.version,
|
|
15
49
|
},
|
|
16
50
|
servers: [
|
|
17
51
|
{
|
|
@@ -215,7 +249,12 @@ class GetOpenApiJson extends AbstractCommand {
|
|
|
215
249
|
}
|
|
216
250
|
|
|
217
251
|
const result = JSON.stringify(openApi);
|
|
218
|
-
|
|
252
|
+
|
|
253
|
+
if (this.args.output) {
|
|
254
|
+
await fs.writeFile(this.args.output, result);
|
|
255
|
+
this.logger.info(`Output to: ${this.args.output}`);
|
|
256
|
+
}
|
|
257
|
+
|
|
219
258
|
return result;
|
|
220
259
|
}
|
|
221
260
|
}
|
package/controllers/Auth.test.js
CHANGED
|
@@ -31,6 +31,26 @@ describe('auth', () => {
|
|
|
31
31
|
expect(status).toBe(201);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
+
it('can not create user with the same nickname', async () => {
|
|
35
|
+
expect.assertions(1);
|
|
36
|
+
await request(global.server.app.httpServer.express)
|
|
37
|
+
.post('/auth/register')
|
|
38
|
+
.send({
|
|
39
|
+
email: userEmail,
|
|
40
|
+
password: userPassword,
|
|
41
|
+
nickName: 'test',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const { status } = await request(global.server.app.httpServer.express)
|
|
45
|
+
.post('/auth/register')
|
|
46
|
+
.send({
|
|
47
|
+
email: userEmail2,
|
|
48
|
+
password: '123',
|
|
49
|
+
nickName: 'test',
|
|
50
|
+
});
|
|
51
|
+
expect(status).toBe(400);
|
|
52
|
+
});
|
|
53
|
+
|
|
34
54
|
it('can NOT create SAME user', async () => {
|
|
35
55
|
expect.assertions(1);
|
|
36
56
|
const { status } = await request(global.server.app.httpServer.express)
|
|
@@ -90,6 +110,136 @@ describe('auth', () => {
|
|
|
90
110
|
});
|
|
91
111
|
|
|
92
112
|
describe('isAuthWithVefificationFlow auth option', () => {
|
|
113
|
+
it('can verify user', async () => {
|
|
114
|
+
expect.assertions(2);
|
|
115
|
+
const user = await global.server.app.getModel('User').create({
|
|
116
|
+
email: 'Test@gmail.com',
|
|
117
|
+
password: 'userPassword',
|
|
118
|
+
name: {
|
|
119
|
+
nick: 'nickname',
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
user.verificationTokens.push({
|
|
124
|
+
token: 'testToken',
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await user.save();
|
|
128
|
+
|
|
129
|
+
const { status } = await request(
|
|
130
|
+
global.server.app.httpServer.express,
|
|
131
|
+
).post(`/auth/verify?verification_token=testToken`);
|
|
132
|
+
|
|
133
|
+
const { isVerified } = await global.server.app.getModel('User').findOne({
|
|
134
|
+
email: 'Test@gmail.com',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
expect(status).toBe(200);
|
|
138
|
+
expect(isVerified).toBeTruthy();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('can not verify user with wrong token', async () => {
|
|
142
|
+
expect.assertions(2);
|
|
143
|
+
const user = await global.server.app.getModel('User').create({
|
|
144
|
+
email: 'Test423@gmail.com',
|
|
145
|
+
password: 'userPassword',
|
|
146
|
+
name: {
|
|
147
|
+
nick: 'nicknameee',
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
user.verificationTokens.push({
|
|
152
|
+
token: 'testToken',
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
await user.save();
|
|
156
|
+
|
|
157
|
+
const { status } = await request(
|
|
158
|
+
global.server.app.httpServer.express,
|
|
159
|
+
).post(`/auth/verify?verification_token=testToken123wrong`);
|
|
160
|
+
|
|
161
|
+
const { isVerified } = await global.server.app.getModel('User').findOne({
|
|
162
|
+
email: 'Test423@gmail.com',
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
expect(status).toBe(400);
|
|
166
|
+
expect(isVerified).toBeFalsy();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('can NOT send recovery to not exist email', async () => {
|
|
170
|
+
expect.assertions(1);
|
|
171
|
+
const { status } = await request(global.server.app.httpServer.express)
|
|
172
|
+
.post('/auth/send-recovery-email')
|
|
173
|
+
.send({
|
|
174
|
+
email: 'notExists@gmail.com',
|
|
175
|
+
});
|
|
176
|
+
expect(status).toBe(400);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('can send recovery to exist email', async () => {
|
|
180
|
+
expect.assertions(1);
|
|
181
|
+
const { status } = await request(global.server.app.httpServer.express)
|
|
182
|
+
.post('/auth/send-recovery-email')
|
|
183
|
+
.send({
|
|
184
|
+
email: userEmail,
|
|
185
|
+
});
|
|
186
|
+
expect(status).toBe(200);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('can recover password', async () => {
|
|
190
|
+
expect.assertions(1);
|
|
191
|
+
|
|
192
|
+
const user = await global.server.app.getModel('User').create({
|
|
193
|
+
email: 'Test1@gmail.com',
|
|
194
|
+
password: 'userPassword',
|
|
195
|
+
name: {
|
|
196
|
+
nick: 'nickname1',
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
user.passwordRecoveryTokens.push({
|
|
201
|
+
token: 'superPassword',
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
await user.save();
|
|
205
|
+
|
|
206
|
+
const { status } = await request(global.server.app.httpServer.express)
|
|
207
|
+
.post('/auth/recover-password')
|
|
208
|
+
.send({
|
|
209
|
+
password: 'newPass',
|
|
210
|
+
passwordRecoveryToken: 'superPassword',
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
expect(status).toBe(200);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('can not recover password with wrong token', async () => {
|
|
217
|
+
expect.assertions(1);
|
|
218
|
+
|
|
219
|
+
const user = await global.server.app.getModel('User').create({
|
|
220
|
+
email: 'Test2@gmail.com',
|
|
221
|
+
password: 'userPassword',
|
|
222
|
+
name: {
|
|
223
|
+
nick: 'nickname2',
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
user.passwordRecoveryTokens.push({
|
|
228
|
+
token: 'superPassword',
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
await user.save();
|
|
232
|
+
|
|
233
|
+
const { status } = await request(global.server.app.httpServer.express)
|
|
234
|
+
.post('/auth/recover-password')
|
|
235
|
+
.send({
|
|
236
|
+
password: 'newPass',
|
|
237
|
+
passwordRecoveryToken: '13123',
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
expect(status).toBe(400);
|
|
241
|
+
});
|
|
242
|
+
|
|
93
243
|
it('can login with normal creds and NOT verifyed email is option isAuthWithVefificationFlow is set', async () => {
|
|
94
244
|
expect.assertions(4);
|
|
95
245
|
|
|
@@ -129,6 +279,28 @@ describe('auth', () => {
|
|
|
129
279
|
});
|
|
130
280
|
});
|
|
131
281
|
|
|
282
|
+
it('can user send verification', async () => {
|
|
283
|
+
expect.assertions(1);
|
|
284
|
+
|
|
285
|
+
const { status } = await request(global.server.app.httpServer.express)
|
|
286
|
+
.post('/auth/send-verification')
|
|
287
|
+
.send({
|
|
288
|
+
email: userEmail2,
|
|
289
|
+
});
|
|
290
|
+
expect(status).toBe(200);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('can not user send verification to wrong email', async () => {
|
|
294
|
+
expect.assertions(1);
|
|
295
|
+
|
|
296
|
+
const { status } = await request(global.server.app.httpServer.express)
|
|
297
|
+
.post('/auth/send-verification')
|
|
298
|
+
.send({
|
|
299
|
+
email: 'wrong@gmail.com',
|
|
300
|
+
});
|
|
301
|
+
expect(status).toBe(400);
|
|
302
|
+
});
|
|
303
|
+
|
|
132
304
|
describe('rate limiter', () => {
|
|
133
305
|
it('we should receive 429 on rate limit exceeded', async () => {
|
|
134
306
|
expect.assertions(1);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const SomeController = require('../controllers/test/SomeController');
|
|
2
|
+
const AbstractController = require('./AbstractController');
|
|
3
|
+
|
|
4
|
+
describe('abstract controller methods', () => {
|
|
5
|
+
it('can get routes', async () => {
|
|
6
|
+
expect.assertions(2);
|
|
7
|
+
|
|
8
|
+
const controller = new AbstractController(global.server.app);
|
|
9
|
+
const childController = new SomeController(global.server.app);
|
|
10
|
+
|
|
11
|
+
const { routes } = controller;
|
|
12
|
+
const { routes: childRoutes } = childController;
|
|
13
|
+
|
|
14
|
+
expect(routes).toStrictEqual({});
|
|
15
|
+
expect(childRoutes).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaptivestone/framework",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Adaptive stone node js framework",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"dotenv": "^16.0.0",
|
|
41
41
|
"email-templates": "^10.0.0",
|
|
42
42
|
"express": "^4.17.1",
|
|
43
|
-
"i18next": "^
|
|
44
|
-
"i18next-chained-backend": "^
|
|
45
|
-
"i18next-fs-backend": "^
|
|
43
|
+
"i18next": "^22.0.4",
|
|
44
|
+
"i18next-chained-backend": "^4.0.0",
|
|
45
|
+
"i18next-fs-backend": "^2.0.0",
|
|
46
46
|
"i18next-http-middleware": "^3.1.4",
|
|
47
47
|
"minimist": "^1.2.5",
|
|
48
48
|
"mongoose": "^6.0.0",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const RateLimiter = require('./RateLimiter');
|
|
2
|
+
|
|
3
|
+
describe('middlewares methods', () => {
|
|
4
|
+
it('can create redis rateLimiter', async () => {
|
|
5
|
+
expect.assertions(1);
|
|
6
|
+
|
|
7
|
+
const redisRateLimiter = new RateLimiter(global.server.app, {
|
|
8
|
+
driver: 'redis',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
expect(redisRateLimiter.limiter).toBeDefined();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('can not create rateLimiter with unknown driver', async () => {
|
|
15
|
+
expect.assertions(1);
|
|
16
|
+
|
|
17
|
+
const rateLimiter = new RateLimiter(global.server.app, {
|
|
18
|
+
driver: 'unknown',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
expect(rateLimiter.limiter).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('generateConsumeKey works correctly', async () => {
|
|
25
|
+
expect.assertions(1);
|
|
26
|
+
|
|
27
|
+
const redisRateLimiter = new RateLimiter(global.server.app, {
|
|
28
|
+
driver: 'redis',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const res = await redisRateLimiter.gerenateConsumeKey({
|
|
32
|
+
ip: '192.168.0.0',
|
|
33
|
+
appInfo: {
|
|
34
|
+
user: {
|
|
35
|
+
id: 'someId',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(res).toBe('192.168.0.0__someId');
|
|
41
|
+
});
|
|
42
|
+
});
|