5htp-core 0.2.1 → 0.2.2
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 +10 -3
- package/src/client/app/index.ts +2 -2
- package/src/client/assets/css/components/card.less +0 -3
- package/src/client/assets/css/components/other.less +2 -4
- package/src/client/assets/css/components/table.less +1 -2
- package/src/client/assets/css/components.less +4 -0
- package/src/client/assets/css/core.less +0 -1
- package/src/client/assets/css/theme.less +2 -2
- package/src/client/assets/css/utils/medias.less +21 -0
- package/src/client/components/Card/index.tsx +8 -5
- package/src/client/components/Dialog/index.less +3 -3
- package/src/client/components/Row/index.less +2 -0
- package/src/client/components/Row/index.tsx +44 -10
- package/src/client/components/Video/index.less +39 -0
- package/src/client/components/Video/index.tsx +69 -0
- package/src/client/components/containers/Popover/index.tsx +2 -2
- package/src/client/components/data/Time.tsx +1 -1
- package/src/client/components/data/progressbar/circular/index.tsx +1 -1
- package/src/client/components/index.ts +24 -8
- package/src/client/components/input/BaseV2/index.tsx +0 -1
- package/src/client/components/{input/BaseV2/index.less → inputv3/base.less} +1 -1
- package/src/client/components/inputv3/base.tsx +73 -0
- package/src/client/components/{input/UploadImage → inputv3/file}/Bouton.tsx +0 -0
- package/src/client/components/inputv3/file/FileToUpload.ts +34 -0
- package/src/client/components/inputv3/file/index.less +59 -0
- package/src/client/components/inputv3/file/index.tsx +157 -0
- package/src/client/components/{input → inputv3/string}/index.tsx +41 -27
- package/src/client/pages/bug.tsx +3 -4
- package/src/client/services/router/index.tsx +0 -1
- package/src/client/services/router/request/api.ts +20 -12
- package/src/client/services/router/request/multipart.ts +27 -0
- package/src/common/data/chaines/greetings.ts +1 -1
- package/src/common/data/dates.ts +1 -1
- package/src/common/data/input/validate.ts +0 -9
- package/src/common/data/markdown.ts +1 -1
- package/src/common/errors/index.ts +16 -12
- package/src/common/router/request/api.ts +11 -3
- package/src/common/validation/schema.ts +21 -20
- package/src/common/validation/validators.ts +3 -6
- package/src/server/app/commands.ts +149 -0
- package/src/server/app/index.ts +23 -4
- package/src/server/app/service.ts +4 -0
- package/src/server/services/cache/commands.ts +41 -0
- package/src/server/services/cache/index.ts +102 -34
- package/src/server/services/console/index.ts +1 -1
- package/src/server/services/database/connection.ts +38 -22
- package/src/server/services/database/datatypes.ts +51 -12
- package/src/server/services/database/index.ts +133 -40
- package/src/server/services/database/metas.ts +63 -37
- package/src/server/services/database/repository.ts +26 -0
- package/src/server/services/email/index.ts +102 -42
- package/src/server/services/fetch/index.ts +110 -0
- package/src/server/services/router/http/multipart.ts +70 -41
- package/src/server/services/router/index.ts +35 -4
- package/src/server/services/router/request/index.ts +8 -6
- package/src/server/services/schema/index.ts +4 -11
- package/src/server/services/schema/request.ts +16 -7
- package/src/server/services/schema/router.ts +6 -2
- package/src/server/{services_old → services/security/encrypt}/aes.ts +33 -14
- package/src/server/services/users/index.ts +3 -3
- package/src/server/services/users/router/index.ts +0 -2
- package/src/types/global/utils.d.ts +11 -1
- package/tsconfig.common.json +3 -0
- package/src/client/components/input/Textarea.tsx +0 -57
- package/src/client/components/input/Upload.tsx +0 -5
- package/src/client/components/input/UploadImage/index.less +0 -93
- package/src/client/components/input/UploadImage/index.tsx +0 -220
- package/src/common/data/file.ts +0 -25
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
- DEPENDANCES
|
|
3
3
|
----------------------------------*/
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// Npm
|
|
6
|
+
import mime from 'mime-types';
|
|
7
|
+
|
|
8
|
+
// Core
|
|
9
|
+
import FileToUpload from '@client/components/inputv3/file/FileToUpload';
|
|
10
|
+
import { InputError } from '@common/errors';
|
|
6
11
|
|
|
7
12
|
/*----------------------------------
|
|
8
13
|
- TYPES
|
|
@@ -11,6 +16,34 @@ import NormalizedFile from '@common/data/file';
|
|
|
11
16
|
import type { Request, Response, NextFunction } from 'express';
|
|
12
17
|
import type { FileArray, UploadedFile } from 'express-fileupload';
|
|
13
18
|
|
|
19
|
+
/*----------------------------------
|
|
20
|
+
- CONFIG
|
|
21
|
+
----------------------------------*/
|
|
22
|
+
const reMultipart = /^multipart\/(?:form-data|related)(?:;|$)/i;
|
|
23
|
+
|
|
24
|
+
/*----------------------------------
|
|
25
|
+
- MIDDLEWARE
|
|
26
|
+
----------------------------------*/
|
|
27
|
+
export const MiddlewareFormData = (req: Request, res: Response, next: NextFunction) => {
|
|
28
|
+
|
|
29
|
+
// Verif si multipart
|
|
30
|
+
if (!isMutipart( req ))
|
|
31
|
+
return next();
|
|
32
|
+
|
|
33
|
+
// Données body + fichiers
|
|
34
|
+
// NOTE: Les données devant obligatoirement passer par le validateur de schema,
|
|
35
|
+
// On peut mélanger le body et les files sans risque de sécurité
|
|
36
|
+
req.body = traiterMultipart(req.body, req['files']);
|
|
37
|
+
//req.files = traiterMultipart(req.files);
|
|
38
|
+
|
|
39
|
+
next();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/*----------------------------------
|
|
43
|
+
- FUNCTIONS
|
|
44
|
+
----------------------------------*/
|
|
45
|
+
export const isMutipart = (req: Request) => req.headers['content-type'] && reMultipart.exec( req.headers['content-type'] );
|
|
46
|
+
|
|
14
47
|
export const traiterMultipart = (...canaux: any[]) => {
|
|
15
48
|
|
|
16
49
|
let sortie: {[nom: string]: any} = {};
|
|
@@ -20,38 +53,39 @@ export const traiterMultipart = (...canaux: any[]) => {
|
|
|
20
53
|
if (!donnees)
|
|
21
54
|
continue;
|
|
22
55
|
|
|
23
|
-
for (const
|
|
24
|
-
let donnee = donnees[
|
|
56
|
+
for (const fieldPath in donnees) {
|
|
57
|
+
let donnee = donnees[fieldPath];
|
|
25
58
|
|
|
26
59
|
let brancheA = sortie;
|
|
27
|
-
const
|
|
28
|
-
for (let iCle = 0; iCle <
|
|
60
|
+
const results = [...fieldPath.matchAll(/[^\[\]]+/g)];
|
|
61
|
+
for (let iCle = 0; iCle < results.length; iCle++) {
|
|
29
62
|
|
|
30
|
-
const [cle] =
|
|
63
|
+
const [cle] = results[ iCle ];
|
|
31
64
|
|
|
32
|
-
//
|
|
33
|
-
if (iCle !==
|
|
65
|
+
// Need to go deeper to find data
|
|
66
|
+
if (iCle !== results.length - 1) {
|
|
34
67
|
|
|
35
68
|
if (brancheA[ cle ] === undefined) {
|
|
36
|
-
const tableau = !isNaN(
|
|
69
|
+
const tableau = !isNaN( results[ iCle + 1 ][0] as any )
|
|
37
70
|
brancheA[ cle ] = tableau ? [] : {};
|
|
38
71
|
}
|
|
39
72
|
|
|
40
73
|
brancheA = brancheA[ cle ];
|
|
41
|
-
|
|
42
|
-
// Donnée atteinte
|
|
43
|
-
} else {
|
|
44
|
-
|
|
45
|
-
// Fichier
|
|
46
|
-
if (typeof donnee === 'object' && donnee.data !== undefined && donnee.data instanceof Buffer){
|
|
47
|
-
donnee = normaliserFichier(donnee);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
brancheA[ cle ] = donnee;
|
|
51
|
-
|
|
52
|
-
|
|
74
|
+
continue;
|
|
53
75
|
}
|
|
54
76
|
|
|
77
|
+
// Data reached
|
|
78
|
+
if (
|
|
79
|
+
typeof donnee === 'object'
|
|
80
|
+
&&
|
|
81
|
+
donnee.data !== undefined
|
|
82
|
+
&&
|
|
83
|
+
donnee.data instanceof Buffer
|
|
84
|
+
){
|
|
85
|
+
donnee = normalizeFile(donnee);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
brancheA[ cle ] = donnee;
|
|
55
89
|
}
|
|
56
90
|
}
|
|
57
91
|
}
|
|
@@ -59,27 +93,22 @@ export const traiterMultipart = (...canaux: any[]) => {
|
|
|
59
93
|
return sortie;
|
|
60
94
|
}
|
|
61
95
|
|
|
62
|
-
const
|
|
63
|
-
export const requeteMultipart = (req: Request) => reMultipart.exec( req.headers['content-type'] );
|
|
96
|
+
const normalizeFile = (file: UploadedFile) => {
|
|
64
97
|
|
|
65
|
-
const
|
|
66
|
-
name: file.name,
|
|
67
|
-
type: file.mimetype,
|
|
68
|
-
size: file.size,
|
|
69
|
-
data: file.data,
|
|
70
|
-
})
|
|
98
|
+
const ext = mime.extension(file.mimetype);
|
|
71
99
|
|
|
72
|
-
|
|
100
|
+
if (ext === false)
|
|
101
|
+
throw new InputError(`We couldn't determine the type of the CV file you sent. Please encure it's not corrupted and try again.`);
|
|
73
102
|
|
|
74
|
-
|
|
75
|
-
if (!requeteMultipart( req ))
|
|
76
|
-
return next();
|
|
77
|
-
|
|
78
|
-
// Données body + fichiers
|
|
79
|
-
// NOTE: Les données devant obligatoirement passer par le validateur de schema,
|
|
80
|
-
// On peut mélanger le body et les files sans risque de sécurité
|
|
81
|
-
req.body = traiterMultipart(req.body, req.files);
|
|
82
|
-
//req.files = traiterMultipart(req.files);
|
|
103
|
+
return new FileToUpload({
|
|
83
104
|
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
name: file.name,
|
|
106
|
+
type: file.mimetype,
|
|
107
|
+
size: file.size,
|
|
108
|
+
|
|
109
|
+
data: file.data,
|
|
110
|
+
|
|
111
|
+
md5: file.md5,
|
|
112
|
+
ext: ext
|
|
113
|
+
})
|
|
114
|
+
}
|
|
@@ -9,15 +9,19 @@
|
|
|
9
9
|
- DEPENDANCES
|
|
10
10
|
----------------------------------*/
|
|
11
11
|
|
|
12
|
+
// Node
|
|
13
|
+
import path from 'path';
|
|
14
|
+
|
|
12
15
|
// Npm
|
|
13
16
|
import type express from 'express';
|
|
14
17
|
import { v4 as uuid } from 'uuid';
|
|
18
|
+
import fs from 'fs-extra';
|
|
15
19
|
import type { GlobImportedWithMetas } from 'babel-plugin-glob-import';
|
|
16
20
|
|
|
17
21
|
// Core
|
|
18
22
|
import Application, { Service } from '@server/app';
|
|
19
23
|
import context from '@server/context';
|
|
20
|
-
import {
|
|
24
|
+
import { CoreError, NotFound } from '@common/errors';
|
|
21
25
|
import BaseRouter, {
|
|
22
26
|
TRoute, TErrorRoute, TRouteModule,
|
|
23
27
|
TRouteOptions, defaultOptions
|
|
@@ -42,7 +46,7 @@ import DocumentRenderer from './response/page/document';
|
|
|
42
46
|
|
|
43
47
|
export { default as RouterService } from './service';
|
|
44
48
|
export { default as RequestService } from './request/service';
|
|
45
|
-
export type { default as Request } from "./request";
|
|
49
|
+
export type { default as Request, UploadedFile } from "./request";
|
|
46
50
|
export type { default as Response, TRouterContext } from "./response";
|
|
47
51
|
export type { TRoute } from '@common/router';
|
|
48
52
|
|
|
@@ -168,6 +172,7 @@ export default class ServerRouter<
|
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
private registerRoutes(defModules: GlobImportedWithMetas<TRouteModule>) {
|
|
175
|
+
|
|
171
176
|
for (const routeModule of defModules) {
|
|
172
177
|
|
|
173
178
|
const register = routeModule.exports.__register;
|
|
@@ -181,6 +186,14 @@ export default class ServerRouter<
|
|
|
181
186
|
this.afterRegister();
|
|
182
187
|
}
|
|
183
188
|
|
|
189
|
+
// TODO: Generate TS type of the routes list
|
|
190
|
+
public url<TRoutePath extends keyof Routes = keyof Routes>(
|
|
191
|
+
path: TRoutePath,
|
|
192
|
+
params: Routes[TRoutePath]["params"]
|
|
193
|
+
) {
|
|
194
|
+
return this.http.publicUrl + path;
|
|
195
|
+
}
|
|
196
|
+
|
|
184
197
|
/*----------------------------------
|
|
185
198
|
- REGISTER
|
|
186
199
|
----------------------------------*/
|
|
@@ -265,9 +278,12 @@ export default class ServerRouter<
|
|
|
265
278
|
console.info("Pre-Loading request services");
|
|
266
279
|
//await TrackingService.LoadCache();
|
|
267
280
|
|
|
268
|
-
|
|
281
|
+
// Generate typescript typings
|
|
282
|
+
if (this.app.env.profile = 'dev')
|
|
283
|
+
this.genTypings();
|
|
269
284
|
|
|
270
285
|
// Ordonne par ordre de priorité
|
|
286
|
+
console.info("Loading routes ...");
|
|
271
287
|
this.routes.sort((r1, r2) => {
|
|
272
288
|
|
|
273
289
|
const prioDelta = r2.options.priority - r1.options.priority;
|
|
@@ -329,6 +345,21 @@ export default class ServerRouter<
|
|
|
329
345
|
console.info(this.routes.length + " routes where registered.");
|
|
330
346
|
}
|
|
331
347
|
|
|
348
|
+
private genTypings() {
|
|
349
|
+
fs.outputFileSync( path.join(this.app.path.typings, 'routes.d.ts'), `
|
|
350
|
+
declare type Routes = {
|
|
351
|
+
${this.routes.map( route => `
|
|
352
|
+
'${route.path}': {
|
|
353
|
+
params: {
|
|
354
|
+
${route.keys.map( k => "'" + k + "': string").join(',\n')}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
`).join(',')}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
`);
|
|
361
|
+
}
|
|
362
|
+
|
|
332
363
|
/*----------------------------------
|
|
333
364
|
- RESOLUTION
|
|
334
365
|
----------------------------------*/
|
|
@@ -499,7 +530,7 @@ export default class ServerRouter<
|
|
|
499
530
|
request.res.json(responseData);
|
|
500
531
|
}
|
|
501
532
|
|
|
502
|
-
private async handleError(e:
|
|
533
|
+
private async handleError(e: CoreError, request: ServerRequest<ServerRouter>) {
|
|
503
534
|
|
|
504
535
|
const code = 'http' in e ? e.http : 500;
|
|
505
536
|
const route = this.errors[code];
|
|
@@ -10,22 +10,24 @@ import Bowser from "bowser";
|
|
|
10
10
|
|
|
11
11
|
// Core
|
|
12
12
|
import BaseRequest from '@common/router/request';
|
|
13
|
+
import type FileToUpload from '@client/components/inputv3/file/FileToUpload';
|
|
13
14
|
|
|
14
15
|
// Specific
|
|
15
|
-
import
|
|
16
|
+
import type {
|
|
17
|
+
default as Router, Config as RouterConfig,
|
|
18
|
+
HttpMethod, HttpHeaders
|
|
19
|
+
} from '..';
|
|
16
20
|
import ApiClient from './api';
|
|
21
|
+
import ServerResponse from '../response';
|
|
17
22
|
|
|
18
23
|
/*----------------------------------
|
|
19
24
|
- TYPES
|
|
20
25
|
----------------------------------*/
|
|
21
26
|
|
|
22
|
-
import type {
|
|
23
|
-
default as Router, Config as RouterConfig,
|
|
24
|
-
HttpMethod, HttpHeaders
|
|
25
|
-
} from '@server/services/router';
|
|
26
|
-
|
|
27
27
|
const localeFilter = (input: any) => typeof input === 'string' && ISO6391.validate(input) ? input : undefined;
|
|
28
28
|
|
|
29
|
+
export type UploadedFile = With<FileToUpload, 'md5'|'ext'>
|
|
30
|
+
|
|
29
31
|
/*----------------------------------
|
|
30
32
|
- CONTEXTE
|
|
31
33
|
----------------------------------*/
|
|
@@ -9,7 +9,7 @@ import SchemaValidator, { TFileValidator } from '@common/validation/validators';
|
|
|
9
9
|
|
|
10
10
|
import Validator, { EXCLUDE_VALUE,} from '@common/validation/validator';
|
|
11
11
|
|
|
12
|
-
import
|
|
12
|
+
import type FileToUpload from '@client/components/inputv3/file/FileToUpload';
|
|
13
13
|
|
|
14
14
|
/*----------------------------------
|
|
15
15
|
- TYPES
|
|
@@ -21,8 +21,8 @@ import NormalizedFile from '@common/data/file';
|
|
|
21
21
|
----------------------------------*/
|
|
22
22
|
export default class ServerSchemaValidator extends SchemaValidator {
|
|
23
23
|
|
|
24
|
-
public file = ({ ...opts }: TFileValidator
|
|
25
|
-
new Validator<
|
|
24
|
+
public file = ({ ...opts }: TFileValidator) =>
|
|
25
|
+
new Validator<FileToUpload>('file', (val, input, output) => {
|
|
26
26
|
|
|
27
27
|
// Chaine = url ancien fichier = exclusion de la valeur pour conserver l'ancien fichier
|
|
28
28
|
// NOTE: Si la valeur est présente mais undefined, alors on supprimera le fichier
|
|
@@ -33,14 +33,7 @@ export default class ServerSchemaValidator extends SchemaValidator {
|
|
|
33
33
|
const file = this.validateFile(opts, val, input, output);
|
|
34
34
|
|
|
35
35
|
if (file === undefined)
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
// Process Image
|
|
39
|
-
if (opts.sharp !== undefined) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
36
|
+
return EXCLUDE_VALUE;
|
|
44
37
|
|
|
45
38
|
return file;
|
|
46
39
|
}, opts)
|
|
@@ -7,14 +7,21 @@ import {
|
|
|
7
7
|
default as Router, RequestService, Request as ServerRequest
|
|
8
8
|
} from '@server/services/router';
|
|
9
9
|
|
|
10
|
-
import ServerSchemaValidator from '.';
|
|
11
|
-
|
|
12
10
|
import Schema, { TSchemaFields, TValidatedData } from '@common/validation/schema';
|
|
13
11
|
|
|
12
|
+
// Specific
|
|
13
|
+
import ServerSchemaValidator from '.';
|
|
14
|
+
|
|
14
15
|
/*----------------------------------
|
|
15
|
-
-
|
|
16
|
+
- SERVICE CONFIG
|
|
16
17
|
----------------------------------*/
|
|
17
18
|
|
|
19
|
+
const LogPrefix = `[router][validation]`;
|
|
20
|
+
|
|
21
|
+
export type TConfig = {
|
|
22
|
+
debug?: boolean
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
/*----------------------------------
|
|
19
26
|
- SERVICE
|
|
20
27
|
----------------------------------*/
|
|
@@ -22,6 +29,7 @@ export default class RequestValidator extends ServerSchemaValidator implements R
|
|
|
22
29
|
|
|
23
30
|
public constructor(
|
|
24
31
|
public request: ServerRequest<Router>,
|
|
32
|
+
public config: TConfig,
|
|
25
33
|
public router = request.router,
|
|
26
34
|
public app = router.app
|
|
27
35
|
) {
|
|
@@ -32,7 +40,7 @@ export default class RequestValidator extends ServerSchemaValidator implements R
|
|
|
32
40
|
|
|
33
41
|
public validate<TSchemaFieldsA extends TSchemaFields>( fields: TSchemaFieldsA ): TValidatedData<TSchemaFieldsA> {
|
|
34
42
|
|
|
35
|
-
console.log("Validate request data:", this.request.data);
|
|
43
|
+
this.config.debug && console.log(LogPrefix, "Validate request data:", this.request.data);
|
|
36
44
|
|
|
37
45
|
const schema = new Schema(fields);
|
|
38
46
|
|
|
@@ -42,9 +50,10 @@ export default class RequestValidator extends ServerSchemaValidator implements R
|
|
|
42
50
|
this.request.data,
|
|
43
51
|
{},
|
|
44
52
|
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
debug: this.config.debug,
|
|
54
|
+
throwError: true,
|
|
55
|
+
validateAll: true,
|
|
56
|
+
validateDeps: false
|
|
48
57
|
},
|
|
49
58
|
[]
|
|
50
59
|
);
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
RouterService
|
|
9
9
|
} from '@server/services/router';
|
|
10
10
|
|
|
11
|
-
import RequestValidator from './request';
|
|
11
|
+
import RequestValidator, { TConfig } from './request';
|
|
12
12
|
|
|
13
13
|
/*----------------------------------
|
|
14
14
|
- TYPES
|
|
@@ -23,11 +23,15 @@ export default class AuthenticationRouterService<
|
|
|
23
23
|
TUser extends {} = {}
|
|
24
24
|
> extends RouterService {
|
|
25
25
|
|
|
26
|
+
public constructor( protected config: TConfig ) {
|
|
27
|
+
super();
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
public async register() {
|
|
27
31
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
public requestService( request: ServerRequest< TRouterWithSchema<this>> ): RequestValidator {
|
|
31
|
-
return new RequestValidator( request );
|
|
35
|
+
return new RequestValidator( request, this.config );
|
|
32
36
|
}
|
|
33
37
|
}
|
|
@@ -6,38 +6,61 @@
|
|
|
6
6
|
import crypto from 'crypto';
|
|
7
7
|
|
|
8
8
|
// Core
|
|
9
|
+
import Application, { Service } from '@server/app';
|
|
9
10
|
import { Forbidden } from '@common/errors';
|
|
10
11
|
|
|
11
|
-
const debug = true;
|
|
12
|
-
|
|
13
12
|
/*----------------------------------
|
|
14
13
|
- CONFIG
|
|
15
14
|
----------------------------------*/
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
|
|
17
|
+
/*----------------------------------
|
|
18
|
+
- SERVICE CONFIG
|
|
19
|
+
----------------------------------*/
|
|
20
|
+
|
|
21
|
+
export type Config = {
|
|
22
|
+
debug?: boolean,
|
|
23
|
+
iv: string,
|
|
24
|
+
keys: {[keyName: string]: string}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type Hooks = {
|
|
28
|
+
|
|
29
|
+
}
|
|
19
30
|
|
|
20
31
|
/*----------------------------------
|
|
21
32
|
- SERVICE
|
|
22
33
|
----------------------------------*/
|
|
23
|
-
class AES {
|
|
34
|
+
export default class AES<TConfig extends Config = Config> extends Service<TConfig, Hooks, Application> {
|
|
24
35
|
|
|
25
|
-
public
|
|
36
|
+
public async register() {
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async start() {
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public encrypt( keyName: keyof TConfig["keys"], data: any ) {
|
|
45
|
+
|
|
46
|
+
const encKey = this.config.keys[ keyName as keyof typeof this.config.keys ];
|
|
26
47
|
|
|
27
48
|
data = JSON.stringify(data);
|
|
28
49
|
|
|
29
|
-
let cipher = crypto.createCipheriv('aes-256-cbc',
|
|
50
|
+
let cipher = crypto.createCipheriv('aes-256-cbc', encKey, this.config.iv);
|
|
30
51
|
let encrypted = cipher.update(data, 'utf8', 'base64');
|
|
31
52
|
encrypted += cipher.final('base64');
|
|
32
53
|
return encrypted;
|
|
33
54
|
|
|
34
55
|
}
|
|
35
56
|
|
|
36
|
-
public decrypt( data: string ) {
|
|
57
|
+
public decrypt( keyName: keyof TConfig["keys"], data: string ) {
|
|
58
|
+
|
|
59
|
+
const encKey = this.config.keys[ keyName as keyof typeof this.config.keys ];
|
|
37
60
|
|
|
38
61
|
try {
|
|
39
62
|
|
|
40
|
-
let decipher = crypto.createDecipheriv('aes-256-cbc',
|
|
63
|
+
let decipher = crypto.createDecipheriv('aes-256-cbc', encKey, this.config.iv);
|
|
41
64
|
let decrypted = decipher.update(data, 'base64', 'utf8');
|
|
42
65
|
return JSON.parse(decrypted + decipher.final('utf8'));
|
|
43
66
|
|
|
@@ -46,9 +69,5 @@ class AES {
|
|
|
46
69
|
throw new Forbidden("Invalid token.");
|
|
47
70
|
|
|
48
71
|
}
|
|
49
|
-
|
|
50
72
|
}
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export default new AES;
|
|
73
|
+
}
|
|
@@ -79,7 +79,7 @@ export default abstract class UsersManagementService<
|
|
|
79
79
|
public abstract login( ...args: any[] ): Promise<{ user: TUser, token: string }>;
|
|
80
80
|
public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser>;
|
|
81
81
|
|
|
82
|
-
protected abstract displayName(user
|
|
82
|
+
protected abstract displayName(user?: TUser | null): string;
|
|
83
83
|
protected abstract displaySessionName(session: TJwtSession): string;
|
|
84
84
|
|
|
85
85
|
public async decode( req: THttpRequest, withData: true ): Promise<TUser | null>;
|
|
@@ -118,7 +118,7 @@ export default abstract class UsersManagementService<
|
|
|
118
118
|
// Deserialize full user data
|
|
119
119
|
this.config.debug && console.log(LogPrefix, `Deserialize user ${sessionName}`);
|
|
120
120
|
const user = await this.decodeSession(session, req);
|
|
121
|
-
this.config.debug && console.log(LogPrefix, `Deserialized user ${sessionName}:`, user);
|
|
121
|
+
this.config.debug && console.log(LogPrefix, `Deserialized user ${sessionName}:`, this.displayName(user));
|
|
122
122
|
|
|
123
123
|
return user;
|
|
124
124
|
}
|
|
@@ -134,7 +134,7 @@ export default abstract class UsersManagementService<
|
|
|
134
134
|
return null;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
public createSession( session: TJwtSession, request: TRequest ): string {
|
|
138
138
|
|
|
139
139
|
this.config.debug && console.info(LogPrefix, `Creating new session:`, session);
|
|
140
140
|
|
|
@@ -43,4 +43,14 @@ declare type TStats<T> = {
|
|
|
43
43
|
interface IntrinsicElements {
|
|
44
44
|
i: { src: TIcons } & React.HTMLAttributes<HTMLElement>;
|
|
45
45
|
}
|
|
46
|
-
}*/
|
|
46
|
+
}*/
|
|
47
|
+
|
|
48
|
+
declare type Routes = {
|
|
49
|
+
[path: string]: {
|
|
50
|
+
params: {
|
|
51
|
+
[param: string]: any
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
declare type PrimitiveValue = string | number | boolean;
|
package/tsconfig.common.json
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
"allowJs": true,
|
|
10
10
|
"strict": false,
|
|
11
11
|
"downlevelIteration": true,
|
|
12
|
+
// Force case sensitive import filenames on Window and Mac
|
|
13
|
+
// https://briandesousa.net/?p=870
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
15
|
|
|
13
16
|
// Equivalent webpack: resolve.symblinks = false
|
|
14
17
|
"preserveSymlinks": true,
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import Champ from './Base';
|
|
7
|
-
|
|
8
|
-
import TextareaAutosize from 'react-textarea-autosize';
|
|
9
|
-
|
|
10
|
-
/*----------------------------------
|
|
11
|
-
- TYPES
|
|
12
|
-
----------------------------------*/
|
|
13
|
-
type TValeur = string;
|
|
14
|
-
const valeurDefaut = '' as string;
|
|
15
|
-
type TValeurDefaut = typeof valeurDefaut;
|
|
16
|
-
type TValeurOut = string;
|
|
17
|
-
|
|
18
|
-
export type Props = {
|
|
19
|
-
valeur: TValeur,
|
|
20
|
-
onPressEnter?: (valeur: TValeur) => void,
|
|
21
|
-
autoFocus?: boolean,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/*----------------------------------
|
|
25
|
-
- COMPOSANTS
|
|
26
|
-
----------------------------------*/
|
|
27
|
-
export default Champ<Props, TValeurDefaut, TValeurOut>('textarea', { valeurDefaut, saisieManuelle: true }, ({
|
|
28
|
-
onPressEnter, attrsChamp
|
|
29
|
-
}, { valeur, state, setState }, rendre) => {
|
|
30
|
-
|
|
31
|
-
if (onPressEnter)
|
|
32
|
-
attrsChamp.onKeyDown = (e: KeyboardEvent) => {
|
|
33
|
-
if (e.key === 'Enter') {
|
|
34
|
-
|
|
35
|
-
// Entrée seulement = envoi
|
|
36
|
-
if (!e.shiftKey) {
|
|
37
|
-
onPressEnter( valeur );
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Nouvelle ligne si shift key + valeur ok
|
|
41
|
-
if (!(e.shiftKey && valeur)) {
|
|
42
|
-
//e.stopPropagation();
|
|
43
|
-
e.preventDefault();
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return rendre((
|
|
50
|
-
<TextareaAutosize {...attrsChamp}
|
|
51
|
-
value={valeur}
|
|
52
|
-
onChange={(e: any) => {
|
|
53
|
-
setState({ valeur: e.target.value });
|
|
54
|
-
}}
|
|
55
|
-
/>
|
|
56
|
-
), { });
|
|
57
|
-
})
|