@nattyjs/core 0.0.1-beta.3 → 0.0.1-beta.30
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/index.cjs +79 -21
- package/dist/index.d.ts +82 -59
- package/dist/index.mjs +76 -22
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -60,10 +60,13 @@ const nattyContainer = new class {
|
|
|
60
60
|
this.container = /* @__PURE__ */ new Map();
|
|
61
61
|
this.containerState = /* @__PURE__ */ new Map();
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
get types() {
|
|
64
|
+
return common.commonContainer.types;
|
|
65
|
+
}
|
|
66
|
+
setup(config, routes, resolver) {
|
|
64
67
|
this.config = config;
|
|
65
68
|
this.routes = routes;
|
|
66
|
-
this.
|
|
69
|
+
this.resolver = resolver;
|
|
67
70
|
}
|
|
68
71
|
getTypes() {
|
|
69
72
|
return StaticContainer.types;
|
|
@@ -116,7 +119,7 @@ const nattyContainer = new class {
|
|
|
116
119
|
function init(config, appConfig) {
|
|
117
120
|
common.commonContainer.setupConfig(config);
|
|
118
121
|
common.commonContainer.setEnvTsDefinition(appConfig.envTsDefinition);
|
|
119
|
-
nattyContainer.setup(config, appConfig.routes, appConfig.
|
|
122
|
+
nattyContainer.setup(config, appConfig.routes, appConfig.resolver);
|
|
120
123
|
return initializeModule(config);
|
|
121
124
|
}
|
|
122
125
|
function initializeModule(config) {
|
|
@@ -207,6 +210,26 @@ var RequestPipeline = /* @__PURE__ */ ((RequestPipeline2) => {
|
|
|
207
210
|
return RequestPipeline2;
|
|
208
211
|
})(RequestPipeline || {});
|
|
209
212
|
|
|
213
|
+
function lessThan(value) {
|
|
214
|
+
return value ? value.replace(/</g, "<") : value;
|
|
215
|
+
}
|
|
216
|
+
function greaterThan(value) {
|
|
217
|
+
return value ? value.replace(/>/g, ">") : value;
|
|
218
|
+
}
|
|
219
|
+
function ampersand(value) {
|
|
220
|
+
return value ? value.replace(/&/g, "&") : value;
|
|
221
|
+
}
|
|
222
|
+
function doubleDash(value) {
|
|
223
|
+
return value ? value.replace(/--/g, "") : value;
|
|
224
|
+
}
|
|
225
|
+
function sanitizeSpecialCodes(value) {
|
|
226
|
+
value = ampersand(value);
|
|
227
|
+
value = lessThan(value);
|
|
228
|
+
value = greaterThan(value);
|
|
229
|
+
value = doubleDash(value);
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
232
|
+
|
|
210
233
|
function isBoolean(value) {
|
|
211
234
|
return typeof value === "boolean" || value === "1" || value === "true" || value === "0" || value === "false";
|
|
212
235
|
}
|
|
@@ -267,7 +290,7 @@ function toInt(value, radix = 0) {
|
|
|
267
290
|
}
|
|
268
291
|
function toString(value) {
|
|
269
292
|
if (isNotBlank(value))
|
|
270
|
-
return String(value);
|
|
293
|
+
return sanitizeSpecialCodes(String(value));
|
|
271
294
|
return value;
|
|
272
295
|
}
|
|
273
296
|
function whitelist(value, chars) {
|
|
@@ -348,6 +371,7 @@ class BaseResult {
|
|
|
348
371
|
}
|
|
349
372
|
|
|
350
373
|
function getResponseBodyObject(body, props) {
|
|
374
|
+
const sensitiveProps = common.commonContainer.nattyConfig?.secure?.sensitiveProps;
|
|
351
375
|
if (body instanceof common.List)
|
|
352
376
|
return getResponseBodyObject(body.values, body.props);
|
|
353
377
|
if (Array.isArray(body)) {
|
|
@@ -361,7 +385,8 @@ function getResponseBodyObject(body, props) {
|
|
|
361
385
|
const keys = Object.keys(body);
|
|
362
386
|
const getterProps = props ? Object.keys(props).map((key) => props[key]) : [];
|
|
363
387
|
for (const key of [...keys, ...getterProps])
|
|
364
|
-
|
|
388
|
+
if (!sensitiveProps || sensitiveProps.filter((t) => t == key.toLowerCase()).length == 0)
|
|
389
|
+
jObject[key] = getResponseBodyObject(body[key]);
|
|
365
390
|
return jObject;
|
|
366
391
|
}
|
|
367
392
|
return body;
|
|
@@ -524,12 +549,14 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
524
549
|
} else {
|
|
525
550
|
if (this.isArrayType(property.type) && Array.isArray(value)) {
|
|
526
551
|
let arrayValue = body[property.name] = [];
|
|
527
|
-
let arrayInvalidProps = invalidProps[property.name] = [];
|
|
528
552
|
for (const item of value) {
|
|
529
553
|
const sanitizeValue = this.sanitizer[property.type.toLowerCase()] ? this.sanitizer[property.type.toLowerCase()](item) : item;
|
|
530
|
-
if (sanitizeValue === INVALID_VALUE)
|
|
554
|
+
if (sanitizeValue === INVALID_VALUE) {
|
|
555
|
+
let arrayInvalidProps = invalidProps[property.name];
|
|
556
|
+
if (!arrayInvalidProps)
|
|
557
|
+
arrayInvalidProps = invalidProps[property.name] = [];
|
|
531
558
|
arrayInvalidProps.push(property);
|
|
532
|
-
else
|
|
559
|
+
} else
|
|
533
560
|
arrayValue.push(sanitizeValue);
|
|
534
561
|
}
|
|
535
562
|
} else
|
|
@@ -557,7 +584,7 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
557
584
|
}
|
|
558
585
|
convertToInstance(entityName, data) {
|
|
559
586
|
const typesInfo = this.types[entityName];
|
|
560
|
-
const target = this.getClassTarget(typesInfo.path) || entityContainer.getTarget(entityName);
|
|
587
|
+
const target = this.getClassTarget(typesInfo.path, entityName) || entityContainer.getTarget(entityName);
|
|
561
588
|
let instance = null;
|
|
562
589
|
if (target) {
|
|
563
590
|
instance = new target();
|
|
@@ -566,11 +593,10 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
566
593
|
instance = data;
|
|
567
594
|
return instance;
|
|
568
595
|
}
|
|
569
|
-
getClassTarget(
|
|
570
|
-
if (
|
|
571
|
-
const classInfo = resolver();
|
|
572
|
-
|
|
573
|
-
return classInfo[name];
|
|
596
|
+
getClassTarget(path, entityName) {
|
|
597
|
+
if (path) {
|
|
598
|
+
const classInfo = nattyContainer.resolver(path);
|
|
599
|
+
return classInfo[entityName];
|
|
574
600
|
}
|
|
575
601
|
return void 0;
|
|
576
602
|
}
|
|
@@ -847,6 +873,14 @@ class ActionExecutedContext extends AbstractExecutionContext {
|
|
|
847
873
|
}
|
|
848
874
|
}
|
|
849
875
|
|
|
876
|
+
class AuthorizationContext extends AbstractExecutionContext {
|
|
877
|
+
constructor(models, context, routeInfo, config) {
|
|
878
|
+
super(context, routeInfo);
|
|
879
|
+
this.models = models;
|
|
880
|
+
this.config = config;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
850
884
|
class RequestProcessor extends RouteParser {
|
|
851
885
|
constructor() {
|
|
852
886
|
super(...arguments);
|
|
@@ -857,9 +891,6 @@ class RequestProcessor extends RouteParser {
|
|
|
857
891
|
case RequestPipeline.onAuthentication:
|
|
858
892
|
await this.onAuthentication();
|
|
859
893
|
break;
|
|
860
|
-
case RequestPipeline.onAuthorization:
|
|
861
|
-
await this.onAuthorization();
|
|
862
|
-
break;
|
|
863
894
|
}
|
|
864
895
|
}
|
|
865
896
|
resolveFilter(instance) {
|
|
@@ -885,21 +916,27 @@ class RequestProcessor extends RouteParser {
|
|
|
885
916
|
this.httpContext.user = result;
|
|
886
917
|
if (!result.isAuthenticate && !anonymousInfo.controllerConfig && !anonymousInfo.methodConfig)
|
|
887
918
|
throw new UnauthorizedAccessException(authenticationFilter.onFailedResponse());
|
|
888
|
-
await this.onAuthorization();
|
|
889
919
|
}
|
|
890
920
|
}
|
|
891
|
-
async onAuthorization() {
|
|
921
|
+
async onAuthorization(methodParameters) {
|
|
892
922
|
const authorization = common.commonContainer.globalConfig.authorization;
|
|
893
923
|
const authorizationFilter = authorization ? this.resolveFilter(authorization) : void 0;
|
|
894
924
|
const authorizeConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.authorize);
|
|
895
925
|
const authenticationOnly = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.authenticationOnly);
|
|
896
|
-
if (this.httpContext.user?.isAuthenticate && authorizationFilter && (!authenticationOnly.controllerConfig && !authenticationOnly.methodConfig)) {
|
|
897
|
-
const
|
|
926
|
+
if (this.httpContext.user?.isAuthenticate && authorizationFilter && (authorizeConfig.controllerConfig || authorizeConfig.methodConfig) && (!authenticationOnly.controllerConfig && !authenticationOnly.methodConfig)) {
|
|
927
|
+
const authorizationContext = new AuthorizationContext(
|
|
928
|
+
methodParameters.filter((t) => t instanceof ModelBindingContext),
|
|
929
|
+
this.httpContext,
|
|
930
|
+
this.routeInfo,
|
|
931
|
+
authorizeConfig.methodConfig || authorizeConfig.controllerConfig
|
|
932
|
+
);
|
|
933
|
+
const result = await authorizationFilter.onAuthorization(authorizationContext);
|
|
898
934
|
if (!result)
|
|
899
935
|
throw new ForbiddenAccessException(authorizationFilter.onFailedAuthorization());
|
|
900
936
|
}
|
|
901
937
|
}
|
|
902
938
|
async onActionExecuting(methodParameters) {
|
|
939
|
+
await this.onAuthorization(methodParameters);
|
|
903
940
|
let actionFilters = common.commonContainer.globalConfig.actionFilters || [];
|
|
904
941
|
const actionFiltersConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.useFilter);
|
|
905
942
|
actionFilters = [...actionFilters, ...actionFiltersConfig.controllerConfig?.actionFilters || [], ...actionFiltersConfig.methodConfig?.actionFilters || []];
|
|
@@ -1231,10 +1268,28 @@ function authenticationOnly() {
|
|
|
1231
1268
|
};
|
|
1232
1269
|
}
|
|
1233
1270
|
|
|
1271
|
+
function setEnvInfo(envTsDefinition, envValueInfo) {
|
|
1272
|
+
if (envTsDefinition && envValueInfo) {
|
|
1273
|
+
common.commonContainer.setEnvTsDefinition(envTsDefinition);
|
|
1274
|
+
Object.keys(envValueInfo).forEach((key) => process.env[key] = envValueInfo[key]);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
function authorize(permission) {
|
|
1279
|
+
return function(target, propertyKey, descriptor) {
|
|
1280
|
+
base({
|
|
1281
|
+
target,
|
|
1282
|
+
propertyKey,
|
|
1283
|
+
descriptor
|
|
1284
|
+
}, DecoratorType.authorize, permission);
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1234
1288
|
exports.$request = $request;
|
|
1235
1289
|
exports.AbstractModelState = AbstractModelState;
|
|
1236
1290
|
exports.BadRequestResult = BadRequestResult;
|
|
1237
1291
|
exports.BaseController = BaseController;
|
|
1292
|
+
exports.CreateProblemDetail = CreateProblemDetail;
|
|
1238
1293
|
exports.CreatedResult = CreatedResult;
|
|
1239
1294
|
exports.Delete = Delete;
|
|
1240
1295
|
exports.ForbiddenAccessException = ForbiddenAccessException;
|
|
@@ -1245,6 +1300,7 @@ exports.HttpException = HttpException;
|
|
|
1245
1300
|
exports.HttpHandler = HttpHandler;
|
|
1246
1301
|
exports.HttpNotFoundException = HttpNotFoundException;
|
|
1247
1302
|
exports.HttpResponse = HttpResponse;
|
|
1303
|
+
exports.HttpStatusCode = HttpStatusCode;
|
|
1248
1304
|
exports.ModelBindingContext = ModelBindingContext;
|
|
1249
1305
|
exports.NoContentResult = NoContentResult;
|
|
1250
1306
|
exports.NotFoundResult = NotFoundResult;
|
|
@@ -1253,6 +1309,7 @@ exports.RunOn = RunOn;
|
|
|
1253
1309
|
exports.UnauthorizedAccessException = UnauthorizedAccessException;
|
|
1254
1310
|
exports.anonymous = anonymous;
|
|
1255
1311
|
exports.authenticationOnly = authenticationOnly;
|
|
1312
|
+
exports.authorize = authorize;
|
|
1256
1313
|
exports.badRequest = badRequest;
|
|
1257
1314
|
exports.created = created;
|
|
1258
1315
|
exports.defineNattyConfig = defineNattyConfig;
|
|
@@ -1269,4 +1326,5 @@ exports.post = post;
|
|
|
1269
1326
|
exports.put = put;
|
|
1270
1327
|
exports.registerDecorator = registerDecorator;
|
|
1271
1328
|
exports.route = route;
|
|
1329
|
+
exports.setEnvInfo = setEnvInfo;
|
|
1272
1330
|
exports.useFilter = useFilter;
|
package/dist/index.d.ts
CHANGED
|
@@ -59,6 +59,64 @@ declare function put(path: string): (target: any, propertyKey?: string, descript
|
|
|
59
59
|
|
|
60
60
|
declare function Delete(): (target: any, propertyKey?: string, descriptor?: any) => void;
|
|
61
61
|
|
|
62
|
+
interface RouteConfig {
|
|
63
|
+
controller: Function;
|
|
64
|
+
parameters: Array<{
|
|
65
|
+
name: string;
|
|
66
|
+
type: string;
|
|
67
|
+
}>;
|
|
68
|
+
get: {
|
|
69
|
+
[key: string]: {
|
|
70
|
+
name: string;
|
|
71
|
+
parameters: Array<{
|
|
72
|
+
name: string;
|
|
73
|
+
type: string;
|
|
74
|
+
}>;
|
|
75
|
+
returnType: string;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
post: {
|
|
79
|
+
[key: string]: {
|
|
80
|
+
name: string;
|
|
81
|
+
parameters: Array<{
|
|
82
|
+
name: string;
|
|
83
|
+
type: string;
|
|
84
|
+
}>;
|
|
85
|
+
returnType: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
put: {
|
|
89
|
+
[key: string]: {
|
|
90
|
+
name: string;
|
|
91
|
+
parameters: Array<{
|
|
92
|
+
name: string;
|
|
93
|
+
type: string;
|
|
94
|
+
}>;
|
|
95
|
+
returnType: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
delete: {
|
|
99
|
+
[key: string]: {
|
|
100
|
+
name: string;
|
|
101
|
+
parameters: Array<{
|
|
102
|
+
name: string;
|
|
103
|
+
type: string;
|
|
104
|
+
}>;
|
|
105
|
+
returnType: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
declare function init(config: NattyConfig, appConfig: {
|
|
111
|
+
routes: {
|
|
112
|
+
[key: string]: RouteConfig;
|
|
113
|
+
};
|
|
114
|
+
envTsDefinition: {
|
|
115
|
+
[key: string]: string;
|
|
116
|
+
};
|
|
117
|
+
resolver: (path: string) => {};
|
|
118
|
+
}): any;
|
|
119
|
+
|
|
62
120
|
interface DecoratorInfo {
|
|
63
121
|
httpMethod: string;
|
|
64
122
|
route: string;
|
|
@@ -190,64 +248,6 @@ interface IHttpResult {
|
|
|
190
248
|
getResponse(): HttpResponseInit;
|
|
191
249
|
}
|
|
192
250
|
|
|
193
|
-
interface RouteConfig {
|
|
194
|
-
controller: Function;
|
|
195
|
-
parameters: Array<{
|
|
196
|
-
name: string;
|
|
197
|
-
type: string;
|
|
198
|
-
}>;
|
|
199
|
-
get: {
|
|
200
|
-
[key: string]: {
|
|
201
|
-
name: string;
|
|
202
|
-
parameters: Array<{
|
|
203
|
-
name: string;
|
|
204
|
-
type: string;
|
|
205
|
-
}>;
|
|
206
|
-
returnType: string;
|
|
207
|
-
};
|
|
208
|
-
};
|
|
209
|
-
post: {
|
|
210
|
-
[key: string]: {
|
|
211
|
-
name: string;
|
|
212
|
-
parameters: Array<{
|
|
213
|
-
name: string;
|
|
214
|
-
type: string;
|
|
215
|
-
}>;
|
|
216
|
-
returnType: string;
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
put: {
|
|
220
|
-
[key: string]: {
|
|
221
|
-
name: string;
|
|
222
|
-
parameters: Array<{
|
|
223
|
-
name: string;
|
|
224
|
-
type: string;
|
|
225
|
-
}>;
|
|
226
|
-
returnType: string;
|
|
227
|
-
};
|
|
228
|
-
};
|
|
229
|
-
delete: {
|
|
230
|
-
[key: string]: {
|
|
231
|
-
name: string;
|
|
232
|
-
parameters: Array<{
|
|
233
|
-
name: string;
|
|
234
|
-
type: string;
|
|
235
|
-
}>;
|
|
236
|
-
returnType: string;
|
|
237
|
-
};
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
declare function init(config: NattyConfig, appConfig: {
|
|
242
|
-
routes: {
|
|
243
|
-
[key: string]: RouteConfig;
|
|
244
|
-
};
|
|
245
|
-
envTsDefinition: {
|
|
246
|
-
[key: string]: string;
|
|
247
|
-
};
|
|
248
|
-
types?: TypesInfo;
|
|
249
|
-
}): any;
|
|
250
|
-
|
|
251
251
|
declare class HttpRequest {
|
|
252
252
|
private httpRequest;
|
|
253
253
|
constructor(http: HttpRequestInit);
|
|
@@ -463,4 +463,27 @@ declare function anonymous(): (target: any, propertyKey?: string, descriptor?: a
|
|
|
463
463
|
|
|
464
464
|
declare function authenticationOnly(): (target: any, propertyKey?: string, descriptor?: any) => void;
|
|
465
465
|
|
|
466
|
-
|
|
466
|
+
declare function setEnvInfo(envTsDefinition: {
|
|
467
|
+
[key: string]: string;
|
|
468
|
+
}, envValueInfo: {
|
|
469
|
+
[key: string]: any;
|
|
470
|
+
}): void;
|
|
471
|
+
|
|
472
|
+
declare enum HttpStatusCode {
|
|
473
|
+
success = 200,
|
|
474
|
+
created = 201,
|
|
475
|
+
noContent = 204,
|
|
476
|
+
notFound = 404,
|
|
477
|
+
unAuthorized = 401,
|
|
478
|
+
forbiddenAccess = 403,
|
|
479
|
+
badRequest = 400,
|
|
480
|
+
serverError = 500
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
declare function authorize(permission: {
|
|
484
|
+
[key: string]: any;
|
|
485
|
+
}): (target: any, propertyKey?: string, descriptor?: any) => void;
|
|
486
|
+
|
|
487
|
+
declare function CreateProblemDetail(modelName: string, detail: any): ProblemDetail;
|
|
488
|
+
|
|
489
|
+
export { $request, AbstractModelState, BadRequestResult, BaseController, BuildOptions, ClassTypeInfo, CreateProblemDetail, CreatedResult, Delete, ForbiddenAccessException, ForbiddenAccessInfoResult, HttpBadRequestException, HttpContext, HttpException, HttpHandler, HttpModule, HttpNotFoundException, HttpResponse, HttpStatusCode, MethodInfo$1 as MethodInfo, ModelBindingContext, NoContentResult, NotFoundResult, OkResult, ParameterInfo, RunOn, TypeInfo$1 as TypeInfo, UnauthorizedAccessException, anonymous, authenticationOnly, authorize, badRequest, created, defineNattyConfig, entityContainer, filter, forbiddenAccessInfo, get, init, injectable, noContent, notFound, ok, post, put, registerDecorator, route, setEnvInfo, useFilter };
|
package/dist/index.mjs
CHANGED
|
@@ -58,10 +58,13 @@ const nattyContainer = new class {
|
|
|
58
58
|
this.container = /* @__PURE__ */ new Map();
|
|
59
59
|
this.containerState = /* @__PURE__ */ new Map();
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
get types() {
|
|
62
|
+
return commonContainer.types;
|
|
63
|
+
}
|
|
64
|
+
setup(config, routes, resolver) {
|
|
62
65
|
this.config = config;
|
|
63
66
|
this.routes = routes;
|
|
64
|
-
this.
|
|
67
|
+
this.resolver = resolver;
|
|
65
68
|
}
|
|
66
69
|
getTypes() {
|
|
67
70
|
return StaticContainer.types;
|
|
@@ -114,7 +117,7 @@ const nattyContainer = new class {
|
|
|
114
117
|
function init(config, appConfig) {
|
|
115
118
|
commonContainer.setupConfig(config);
|
|
116
119
|
commonContainer.setEnvTsDefinition(appConfig.envTsDefinition);
|
|
117
|
-
nattyContainer.setup(config, appConfig.routes, appConfig.
|
|
120
|
+
nattyContainer.setup(config, appConfig.routes, appConfig.resolver);
|
|
118
121
|
return initializeModule(config);
|
|
119
122
|
}
|
|
120
123
|
function initializeModule(config) {
|
|
@@ -205,6 +208,26 @@ var RequestPipeline = /* @__PURE__ */ ((RequestPipeline2) => {
|
|
|
205
208
|
return RequestPipeline2;
|
|
206
209
|
})(RequestPipeline || {});
|
|
207
210
|
|
|
211
|
+
function lessThan(value) {
|
|
212
|
+
return value ? value.replace(/</g, "<") : value;
|
|
213
|
+
}
|
|
214
|
+
function greaterThan(value) {
|
|
215
|
+
return value ? value.replace(/>/g, ">") : value;
|
|
216
|
+
}
|
|
217
|
+
function ampersand(value) {
|
|
218
|
+
return value ? value.replace(/&/g, "&") : value;
|
|
219
|
+
}
|
|
220
|
+
function doubleDash(value) {
|
|
221
|
+
return value ? value.replace(/--/g, "") : value;
|
|
222
|
+
}
|
|
223
|
+
function sanitizeSpecialCodes(value) {
|
|
224
|
+
value = ampersand(value);
|
|
225
|
+
value = lessThan(value);
|
|
226
|
+
value = greaterThan(value);
|
|
227
|
+
value = doubleDash(value);
|
|
228
|
+
return value;
|
|
229
|
+
}
|
|
230
|
+
|
|
208
231
|
function isBoolean(value) {
|
|
209
232
|
return typeof value === "boolean" || value === "1" || value === "true" || value === "0" || value === "false";
|
|
210
233
|
}
|
|
@@ -265,7 +288,7 @@ function toInt(value, radix = 0) {
|
|
|
265
288
|
}
|
|
266
289
|
function toString(value) {
|
|
267
290
|
if (isNotBlank(value))
|
|
268
|
-
return String(value);
|
|
291
|
+
return sanitizeSpecialCodes(String(value));
|
|
269
292
|
return value;
|
|
270
293
|
}
|
|
271
294
|
function whitelist(value, chars) {
|
|
@@ -346,6 +369,7 @@ class BaseResult {
|
|
|
346
369
|
}
|
|
347
370
|
|
|
348
371
|
function getResponseBodyObject(body, props) {
|
|
372
|
+
const sensitiveProps = commonContainer.nattyConfig?.secure?.sensitiveProps;
|
|
349
373
|
if (body instanceof List)
|
|
350
374
|
return getResponseBodyObject(body.values, body.props);
|
|
351
375
|
if (Array.isArray(body)) {
|
|
@@ -359,7 +383,8 @@ function getResponseBodyObject(body, props) {
|
|
|
359
383
|
const keys = Object.keys(body);
|
|
360
384
|
const getterProps = props ? Object.keys(props).map((key) => props[key]) : [];
|
|
361
385
|
for (const key of [...keys, ...getterProps])
|
|
362
|
-
|
|
386
|
+
if (!sensitiveProps || sensitiveProps.filter((t) => t == key.toLowerCase()).length == 0)
|
|
387
|
+
jObject[key] = getResponseBodyObject(body[key]);
|
|
363
388
|
return jObject;
|
|
364
389
|
}
|
|
365
390
|
return body;
|
|
@@ -522,12 +547,14 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
522
547
|
} else {
|
|
523
548
|
if (this.isArrayType(property.type) && Array.isArray(value)) {
|
|
524
549
|
let arrayValue = body[property.name] = [];
|
|
525
|
-
let arrayInvalidProps = invalidProps[property.name] = [];
|
|
526
550
|
for (const item of value) {
|
|
527
551
|
const sanitizeValue = this.sanitizer[property.type.toLowerCase()] ? this.sanitizer[property.type.toLowerCase()](item) : item;
|
|
528
|
-
if (sanitizeValue === INVALID_VALUE)
|
|
552
|
+
if (sanitizeValue === INVALID_VALUE) {
|
|
553
|
+
let arrayInvalidProps = invalidProps[property.name];
|
|
554
|
+
if (!arrayInvalidProps)
|
|
555
|
+
arrayInvalidProps = invalidProps[property.name] = [];
|
|
529
556
|
arrayInvalidProps.push(property);
|
|
530
|
-
else
|
|
557
|
+
} else
|
|
531
558
|
arrayValue.push(sanitizeValue);
|
|
532
559
|
}
|
|
533
560
|
} else
|
|
@@ -555,7 +582,7 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
555
582
|
}
|
|
556
583
|
convertToInstance(entityName, data) {
|
|
557
584
|
const typesInfo = this.types[entityName];
|
|
558
|
-
const target = this.getClassTarget(typesInfo.path) || entityContainer.getTarget(entityName);
|
|
585
|
+
const target = this.getClassTarget(typesInfo.path, entityName) || entityContainer.getTarget(entityName);
|
|
559
586
|
let instance = null;
|
|
560
587
|
if (target) {
|
|
561
588
|
instance = new target();
|
|
@@ -564,11 +591,10 @@ class ParameterTypeConverter extends BaseResponse {
|
|
|
564
591
|
instance = data;
|
|
565
592
|
return instance;
|
|
566
593
|
}
|
|
567
|
-
getClassTarget(
|
|
568
|
-
if (
|
|
569
|
-
const classInfo = resolver();
|
|
570
|
-
|
|
571
|
-
return classInfo[name];
|
|
594
|
+
getClassTarget(path, entityName) {
|
|
595
|
+
if (path) {
|
|
596
|
+
const classInfo = nattyContainer.resolver(path);
|
|
597
|
+
return classInfo[entityName];
|
|
572
598
|
}
|
|
573
599
|
return void 0;
|
|
574
600
|
}
|
|
@@ -845,6 +871,14 @@ class ActionExecutedContext extends AbstractExecutionContext {
|
|
|
845
871
|
}
|
|
846
872
|
}
|
|
847
873
|
|
|
874
|
+
class AuthorizationContext extends AbstractExecutionContext {
|
|
875
|
+
constructor(models, context, routeInfo, config) {
|
|
876
|
+
super(context, routeInfo);
|
|
877
|
+
this.models = models;
|
|
878
|
+
this.config = config;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
848
882
|
class RequestProcessor extends RouteParser {
|
|
849
883
|
constructor() {
|
|
850
884
|
super(...arguments);
|
|
@@ -855,9 +889,6 @@ class RequestProcessor extends RouteParser {
|
|
|
855
889
|
case RequestPipeline.onAuthentication:
|
|
856
890
|
await this.onAuthentication();
|
|
857
891
|
break;
|
|
858
|
-
case RequestPipeline.onAuthorization:
|
|
859
|
-
await this.onAuthorization();
|
|
860
|
-
break;
|
|
861
892
|
}
|
|
862
893
|
}
|
|
863
894
|
resolveFilter(instance) {
|
|
@@ -883,21 +914,27 @@ class RequestProcessor extends RouteParser {
|
|
|
883
914
|
this.httpContext.user = result;
|
|
884
915
|
if (!result.isAuthenticate && !anonymousInfo.controllerConfig && !anonymousInfo.methodConfig)
|
|
885
916
|
throw new UnauthorizedAccessException(authenticationFilter.onFailedResponse());
|
|
886
|
-
await this.onAuthorization();
|
|
887
917
|
}
|
|
888
918
|
}
|
|
889
|
-
async onAuthorization() {
|
|
919
|
+
async onAuthorization(methodParameters) {
|
|
890
920
|
const authorization = commonContainer.globalConfig.authorization;
|
|
891
921
|
const authorizationFilter = authorization ? this.resolveFilter(authorization) : void 0;
|
|
892
922
|
const authorizeConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.authorize);
|
|
893
923
|
const authenticationOnly = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.authenticationOnly);
|
|
894
|
-
if (this.httpContext.user?.isAuthenticate && authorizationFilter && (!authenticationOnly.controllerConfig && !authenticationOnly.methodConfig)) {
|
|
895
|
-
const
|
|
924
|
+
if (this.httpContext.user?.isAuthenticate && authorizationFilter && (authorizeConfig.controllerConfig || authorizeConfig.methodConfig) && (!authenticationOnly.controllerConfig && !authenticationOnly.methodConfig)) {
|
|
925
|
+
const authorizationContext = new AuthorizationContext(
|
|
926
|
+
methodParameters.filter((t) => t instanceof ModelBindingContext),
|
|
927
|
+
this.httpContext,
|
|
928
|
+
this.routeInfo,
|
|
929
|
+
authorizeConfig.methodConfig || authorizeConfig.controllerConfig
|
|
930
|
+
);
|
|
931
|
+
const result = await authorizationFilter.onAuthorization(authorizationContext);
|
|
896
932
|
if (!result)
|
|
897
933
|
throw new ForbiddenAccessException(authorizationFilter.onFailedAuthorization());
|
|
898
934
|
}
|
|
899
935
|
}
|
|
900
936
|
async onActionExecuting(methodParameters) {
|
|
937
|
+
await this.onAuthorization(methodParameters);
|
|
901
938
|
let actionFilters = commonContainer.globalConfig.actionFilters || [];
|
|
902
939
|
const actionFiltersConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.useFilter);
|
|
903
940
|
actionFilters = [...actionFilters, ...actionFiltersConfig.controllerConfig?.actionFilters || [], ...actionFiltersConfig.methodConfig?.actionFilters || []];
|
|
@@ -1229,4 +1266,21 @@ function authenticationOnly() {
|
|
|
1229
1266
|
};
|
|
1230
1267
|
}
|
|
1231
1268
|
|
|
1232
|
-
|
|
1269
|
+
function setEnvInfo(envTsDefinition, envValueInfo) {
|
|
1270
|
+
if (envTsDefinition && envValueInfo) {
|
|
1271
|
+
commonContainer.setEnvTsDefinition(envTsDefinition);
|
|
1272
|
+
Object.keys(envValueInfo).forEach((key) => process.env[key] = envValueInfo[key]);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
function authorize(permission) {
|
|
1277
|
+
return function(target, propertyKey, descriptor) {
|
|
1278
|
+
base({
|
|
1279
|
+
target,
|
|
1280
|
+
propertyKey,
|
|
1281
|
+
descriptor
|
|
1282
|
+
}, DecoratorType.authorize, permission);
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
export { $request, AbstractModelState, BadRequestResult, BaseController, CreateProblemDetail, CreatedResult, Delete, ForbiddenAccessException, ForbiddenAccessInfoResult, HttpBadRequestException, HttpContext, HttpException, HttpHandler, HttpNotFoundException, HttpResponse, HttpStatusCode, ModelBindingContext, NoContentResult, NotFoundResult, OkResult, RunOn, UnauthorizedAccessException, anonymous, authenticationOnly, authorize, badRequest, created, defineNattyConfig, entityContainer, filter, forbiddenAccessInfo, get, init, injectable, noContent, notFound, ok, post, put, registerDecorator, route, setEnvInfo, useFilter };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nattyjs/core",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.30",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "ajayojha",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"tsyringe": "^4.7.0",
|
|
19
19
|
"path-to-regexp": "6.2.1",
|
|
20
|
-
"@nattyjs/common": "0.0.1-beta.
|
|
20
|
+
"@nattyjs/common": "0.0.1-beta.30"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"unbuild": "1.2.1"
|