@nattyjs/core 0.0.1-beta.37 → 0.0.1-beta.39

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 CHANGED
@@ -27,6 +27,12 @@ function route(path) {
27
27
  const CONTROLLER = "controller";
28
28
  const INVALID_VALUE = "INVALID_VALUE";
29
29
  const BLANK = "";
30
+ const DENY_BY_DEFAULT = {
31
+ type: "https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html#deny-by-default",
32
+ title: "Deny-by-default",
33
+ description: `Zero Trust Architecture (NIST SP 800-207) \u2014 Core principle is "never trust, always verify," which translates to deny-by-default behavior. OWASP Secure Defaults Principle \u2014 \u201CSecurity should be a default setting, and everything should be locked down unless explicitly permitted.\u201D`,
34
+ solution: `Please implement proper authentication and authorization checks. If this API needs to be accessed anonymously, add the @anonymous() decorator above the HTTP action.`
35
+ };
30
36
 
31
37
  function get(path) {
32
38
  return function(target, propertyKey, descriptor) {
@@ -863,6 +869,8 @@ class ModelBindingContext extends ParameterTypeConverter {
863
869
  else
864
870
  this.data = body;
865
871
  this.instance = this.convertToInstance(this.type, this.data);
872
+ if (!this.isValid)
873
+ throw new HttpBadRequestException(CreateProblemDetail(this.type, this.errors));
866
874
  }
867
875
  get isValid() {
868
876
  const errors = runValidators(this.type, this.instance);
@@ -879,6 +887,9 @@ class ActionExecutedContext extends AbstractExecutionContext {
879
887
  super(httpContext, routeInfo);
880
888
  this.content = content;
881
889
  }
890
+ get response() {
891
+ return this.context.response;
892
+ }
882
893
  }
883
894
 
884
895
  class AuthorizationContext extends AbstractExecutionContext {
@@ -919,6 +930,8 @@ class RequestProcessor extends RouteParser {
919
930
  const authentication = this.getAuthenticationClass();
920
931
  const authenticationFilter = authentication ? this.resolveFilter(authentication) : void 0;
921
932
  const anonymousInfo = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.anonymous);
933
+ if (!anonymousInfo && !authenticationFilter)
934
+ throw new UnauthorizedAccessException(DENY_BY_DEFAULT);
922
935
  if (authenticationFilter) {
923
936
  const result = await authenticationFilter.onAuthentication(this.httpContext);
924
937
  this.httpContext.user = result;
@@ -943,8 +956,19 @@ class RequestProcessor extends RouteParser {
943
956
  throw new ForbiddenAccessException(authorizationFilter.onFailedAuthorization());
944
957
  }
945
958
  }
946
- async onActionExecuting(methodParameters) {
947
- await this.onAuthorization(methodParameters);
959
+ async onModelBinding(methodParameters) {
960
+ const { actionExecutingContext, actionFilters } = this.getExecutingContext(methodParameters);
961
+ for (const actionFilter of actionFilters) {
962
+ const filter = this.resolveFilter(actionFilter);
963
+ this.actionFilterInstances.push(filter);
964
+ await filter.onActionExecuting(actionExecutingContext);
965
+ if (actionExecutingContext.result) {
966
+ return actionExecutingContext.result;
967
+ }
968
+ }
969
+ return null;
970
+ }
971
+ getExecutingContext(methodParameters) {
948
972
  let actionFilters = common.commonContainer.globalConfig.actionFilters || [];
949
973
  const actionFiltersConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.useFilter);
950
974
  actionFilters = [...actionFilters, ...actionFiltersConfig.controllerConfig?.actionFilters || [], ...actionFiltersConfig.methodConfig?.actionFilters || []];
@@ -953,6 +977,11 @@ class RequestProcessor extends RouteParser {
953
977
  this.httpContext,
954
978
  this.routeInfo
955
979
  );
980
+ return { actionFilters, actionExecutingContext };
981
+ }
982
+ async onActionExecuting(methodParameters) {
983
+ await this.onAuthorization(methodParameters);
984
+ const { actionExecutingContext, actionFilters } = this.getExecutingContext(methodParameters);
956
985
  for (const actionFilter of actionFilters) {
957
986
  const filter = this.resolveFilter(actionFilter);
958
987
  this.actionFilterInstances.push(filter);
package/dist/index.mjs CHANGED
@@ -25,6 +25,12 @@ function route(path) {
25
25
  const CONTROLLER = "controller";
26
26
  const INVALID_VALUE = "INVALID_VALUE";
27
27
  const BLANK = "";
28
+ const DENY_BY_DEFAULT = {
29
+ type: "https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html#deny-by-default",
30
+ title: "Deny-by-default",
31
+ description: `Zero Trust Architecture (NIST SP 800-207) \u2014 Core principle is "never trust, always verify," which translates to deny-by-default behavior. OWASP Secure Defaults Principle \u2014 \u201CSecurity should be a default setting, and everything should be locked down unless explicitly permitted.\u201D`,
32
+ solution: `Please implement proper authentication and authorization checks. If this API needs to be accessed anonymously, add the @anonymous() decorator above the HTTP action.`
33
+ };
28
34
 
29
35
  function get(path) {
30
36
  return function(target, propertyKey, descriptor) {
@@ -861,6 +867,8 @@ class ModelBindingContext extends ParameterTypeConverter {
861
867
  else
862
868
  this.data = body;
863
869
  this.instance = this.convertToInstance(this.type, this.data);
870
+ if (!this.isValid)
871
+ throw new HttpBadRequestException(CreateProblemDetail(this.type, this.errors));
864
872
  }
865
873
  get isValid() {
866
874
  const errors = runValidators(this.type, this.instance);
@@ -877,6 +885,9 @@ class ActionExecutedContext extends AbstractExecutionContext {
877
885
  super(httpContext, routeInfo);
878
886
  this.content = content;
879
887
  }
888
+ get response() {
889
+ return this.context.response;
890
+ }
880
891
  }
881
892
 
882
893
  class AuthorizationContext extends AbstractExecutionContext {
@@ -917,6 +928,8 @@ class RequestProcessor extends RouteParser {
917
928
  const authentication = this.getAuthenticationClass();
918
929
  const authenticationFilter = authentication ? this.resolveFilter(authentication) : void 0;
919
930
  const anonymousInfo = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.anonymous);
931
+ if (!anonymousInfo && !authenticationFilter)
932
+ throw new UnauthorizedAccessException(DENY_BY_DEFAULT);
920
933
  if (authenticationFilter) {
921
934
  const result = await authenticationFilter.onAuthentication(this.httpContext);
922
935
  this.httpContext.user = result;
@@ -941,8 +954,19 @@ class RequestProcessor extends RouteParser {
941
954
  throw new ForbiddenAccessException(authorizationFilter.onFailedAuthorization());
942
955
  }
943
956
  }
944
- async onActionExecuting(methodParameters) {
945
- await this.onAuthorization(methodParameters);
957
+ async onModelBinding(methodParameters) {
958
+ const { actionExecutingContext, actionFilters } = this.getExecutingContext(methodParameters);
959
+ for (const actionFilter of actionFilters) {
960
+ const filter = this.resolveFilter(actionFilter);
961
+ this.actionFilterInstances.push(filter);
962
+ await filter.onActionExecuting(actionExecutingContext);
963
+ if (actionExecutingContext.result) {
964
+ return actionExecutingContext.result;
965
+ }
966
+ }
967
+ return null;
968
+ }
969
+ getExecutingContext(methodParameters) {
946
970
  let actionFilters = commonContainer.globalConfig.actionFilters || [];
947
971
  const actionFiltersConfig = decoratorStateContainer.getInfo(this.routeInfo.controller.name, this.routeInfo.methodInfo.name, DecoratorType.useFilter);
948
972
  actionFilters = [...actionFilters, ...actionFiltersConfig.controllerConfig?.actionFilters || [], ...actionFiltersConfig.methodConfig?.actionFilters || []];
@@ -951,6 +975,11 @@ class RequestProcessor extends RouteParser {
951
975
  this.httpContext,
952
976
  this.routeInfo
953
977
  );
978
+ return { actionFilters, actionExecutingContext };
979
+ }
980
+ async onActionExecuting(methodParameters) {
981
+ await this.onAuthorization(methodParameters);
982
+ const { actionExecutingContext, actionFilters } = this.getExecutingContext(methodParameters);
954
983
  for (const actionFilter of actionFilters) {
955
984
  const filter = this.resolveFilter(actionFilter);
956
985
  this.actionFilterInstances.push(filter);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nattyjs/core",
3
- "version": "0.0.1-beta.37",
3
+ "version": "0.0.1-beta.39",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "author": "ajayojha",
@@ -18,7 +18,7 @@
18
18
  "reflect-metadata": "0.2.2",
19
19
  "tsyringe": "^4.7.0",
20
20
  "path-to-regexp": "6.2.1",
21
- "@nattyjs/common": "0.0.1-beta.37"
21
+ "@nattyjs/common": "0.0.1-beta.39"
22
22
  },
23
23
  "devDependencies": {
24
24
  "unbuild": "1.2.1"