alado 2.5.1 → 2.5.3

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/README.md CHANGED
@@ -965,22 +965,56 @@ export const optionalAuth: RequestAuthentication = {
965
965
 
966
966
  ## Access Control
967
967
 
968
- The `@accessControl` decorator enables fine-grained permission checking on route handlers by comparing values from the request against expected values.
968
+ The `@accessControl` decorator provides a flexible and intuitive way to implement permission checking on your route handlers. It allows you to validate that requests meet specific authorization requirements by comparing values from the incoming request against expected values.
969
969
 
970
970
  ### Configuration
971
971
 
972
972
  ```typescript
973
973
  export type AccessControlConfig<T> = {
974
- inputProperty: string; // Property path to extract from request (e.g., 'auth.user.id')
975
- transformInputProperty?: (inputPropertyValue: unknown) => T | Promise<T>; // Optional transform
976
- compareWithProperty?: string; // Property path to compare against
977
- expectedValue?: T; // Expected value (if not using compareWithProperty)
978
- statusCode: number; // HTTP status on access denial
979
- message: string; // Error message on denial
974
+ /**
975
+ * The property path to extract from the request.
976
+ * Examples: 'auth.user.id'
977
+ */
978
+ inputProperty: string;
979
+
980
+ /**
981
+ * Optional transformation function to process the extracted value.
982
+ * Useful for normalizing or converting data types before comparison.
983
+ */
984
+ transformInputProperty?: (inputPropertyValue: unknown) => T | Promise<T>;
985
+
986
+ /**
987
+ * Property path to compare against in the request.
988
+ * Examples: 'path.id' (URL parameter), 'body.user.id' (request body)
989
+ */
990
+ compareWithProperty?: string;
991
+
992
+ /**
993
+ * The expected value to compare against.
994
+ * Use this if you have a fixed value rather than a dynamic property path.
995
+ */
996
+ expectedValue?: T;
997
+
998
+ /**
999
+ * Custom access control handler for complex permission logic.
1000
+ * Receives the extracted input value and should return true if access is granted.
1001
+ */
1002
+ accessControlHandler?: (inputPropertyValue: unknown) => Promise<boolean>;
1003
+
1004
+ /**
1005
+ * HTTP status code to return when access is denied.
1006
+ * Commonly 403 (Forbidden) or 401 (Unauthorized).
1007
+ */
1008
+ statusCode: number;
1009
+
1010
+ /**
1011
+ * User-friendly error message displayed when access is denied.
1012
+ */
1013
+ message: string;
980
1014
  };
981
1015
  ```
982
1016
 
983
- Either provide `compareWithProperty` to compare two request values, or `expectedValue` to check against a fixed value.
1017
+ Either provide `compareWithProperty` to compare two request values, or `expectedValue` to check against a fixed value or `accessControlHandler` to implement complex logic.
984
1018
 
985
1019
  ### Usage Example
986
1020
 
@@ -4,4 +4,5 @@ export type AccessControlConfig<T> = {
4
4
  transformInputProperty?: (inputPropertyValue: unknown) => T | Promise<T>;
5
5
  compareWithProperty?: string;
6
6
  expectedValue?: T;
7
+ accessControlHandler: (inputPropertyValue: unknown) => Promise<boolean>;
7
8
  } & AladoServerError;
@@ -6,7 +6,7 @@ async function accessControlChecker(context, request) {
6
6
  const { accessControl } = context;
7
7
  let success = true;
8
8
  for (const item of accessControl) {
9
- const { inputProperty, transformInputProperty, statusCode, message, compareWithProperty, expectedValue } = item;
9
+ const { inputProperty, transformInputProperty, statusCode, message, compareWithProperty, expectedValue, accessControlHandler, } = item;
10
10
  let providedValue = (0, accessor_1.getProperty)(request, inputProperty);
11
11
  if (typeof transformInputProperty === 'function') {
12
12
  providedValue = await transformInputProperty(providedValue);
@@ -24,6 +24,12 @@ async function accessControlChecker(context, request) {
24
24
  if (!success) {
25
25
  return { statusCode, message };
26
26
  }
27
+ if (typeof accessControlHandler === 'function') {
28
+ success = await accessControlHandler(providedValue);
29
+ }
30
+ if (!success) {
31
+ return { statusCode, message };
32
+ }
27
33
  }
28
34
  }
29
35
  //# sourceMappingURL=access-control-checker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"access-control-checker.js","sourceRoot":"","sources":["../../../src/helpers/parser/access-control-checker.ts"],"names":[],"mappings":";;AAGA,oDA6BC;AA/BD,0CAA0C;AAEnC,KAAK,UAAU,oBAAoB,CAAC,OAAqB,EAAE,OAAY;IAC5E,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAClC,IAAI,OAAO,GAAY,IAAI,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,EAAE,aAAa,EAAE,sBAAsB,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;QAEhH,IAAI,aAAa,GAAY,IAAA,sBAAW,EAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAEjE,IAAI,OAAO,sBAAsB,KAAK,UAAU,EAAE,CAAC;YACjD,aAAa,GAAG,MAAM,sBAAsB,CAAC,aAAa,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,GAAG,aAAa,KAAK,aAAa,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;QAED,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,eAAe,GAAG,IAAA,sBAAW,EAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;YAClE,OAAO,GAAG,eAAe,KAAK,aAAa,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"access-control-checker.js","sourceRoot":"","sources":["../../../src/helpers/parser/access-control-checker.ts"],"names":[],"mappings":";;AAGA,oDA6CC;AA/CD,0CAA0C;AAEnC,KAAK,UAAU,oBAAoB,CAAC,OAAqB,EAAE,OAAY;IAC5E,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAClC,IAAI,OAAO,GAAY,IAAI,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,EACJ,aAAa,EACb,sBAAsB,EACtB,UAAU,EACV,OAAO,EACP,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GACrB,GAAG,IAAI,CAAC;QAET,IAAI,aAAa,GAAY,IAAA,sBAAW,EAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAEjE,IAAI,OAAO,sBAAsB,KAAK,UAAU,EAAE,CAAC;YACjD,aAAa,GAAG,MAAM,sBAAsB,CAAC,aAAa,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,GAAG,aAAa,KAAK,aAAa,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;QAED,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,eAAe,GAAG,IAAA,sBAAW,EAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;YAClE,OAAO,GAAG,eAAe,KAAK,aAAa,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;QAED,IAAI,OAAO,oBAAoB,KAAK,UAAU,EAAE,CAAC;YAC/C,OAAO,GAAG,MAAM,oBAAoB,CAAC,aAAa,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alado",
3
- "version": "2.5.1",
3
+ "version": "2.5.3",
4
4
  "description": "Extremely fast, lightweight, robust framework for HTTP applications written in Node.js",
5
5
  "keywords": [
6
6
  "HTTP",
@@ -19,26 +19,26 @@
19
19
  "postinstall": "node postinstall.js",
20
20
  "eslint": "eslint src --ext .ts",
21
21
  "test": "echo \"Error: no test specified\" && exit 0",
22
- "prettier-check": "prettier . --check",
23
- "prettier-write": "prettier . --write",
22
+ "check-format": "prettier . --check",
23
+ "format": "prettier . --write",
24
24
  "prepare": "husky"
25
25
  },
26
26
  "dependencies": {
27
- "swagger-ui-dist": "5.32.6"
27
+ "swagger-ui-dist": "5.32.8"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@eslint/js": "^10.0.1",
31
31
  "@types/node": "24.13.1",
32
32
  "@types/prettier": "3.0.0",
33
- "@typescript-eslint/eslint-plugin": "8.62.0",
34
- "@typescript-eslint/parser": "8.62.0",
35
- "eslint": "10.5.0",
33
+ "@typescript-eslint/eslint-plugin": "8.62.1",
34
+ "@typescript-eslint/parser": "8.62.1",
35
+ "eslint": "10.6.0",
36
36
  "husky": "9.1.7",
37
- "prettier": "3.8.4",
37
+ "prettier": "3.9.4",
38
38
  "prettier-plugin-multiline-arrays": "4.1.9",
39
39
  "tsc-alias": "1.8.17",
40
40
  "typescript": "5.9.3",
41
- "typescript-eslint": "^8.62.0"
41
+ "typescript-eslint": "^8.62.1"
42
42
  },
43
43
  "repository": {
44
44
  "type": "git",