From eddac152e6196bab75c6d47b2d7ea6826dcf9635 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:22:20 +0000 Subject: [PATCH 01/21] chore: bump webonyx/graphql-php in the composer group across 1 directory Bumps the composer group with 1 update in the / directory: [webonyx/graphql-php](https://github.com/webonyx/graphql-php). Updates `webonyx/graphql-php` from 15.31.3 to 15.31.5 - [Release notes](https://github.com/webonyx/graphql-php/releases) - [Changelog](https://github.com/webonyx/graphql-php/blob/master/CHANGELOG.md) - [Commits](https://github.com/webonyx/graphql-php/compare/v15.31.3...v15.31.5) --- updated-dependencies: - dependency-name: webonyx/graphql-php dependency-version: 15.31.5 dependency-type: direct:production dependency-group: composer ... Signed-off-by: dependabot[bot] --- composer.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 717323e5..cb080020 100644 --- a/composer.lock +++ b/composer.lock @@ -72,16 +72,16 @@ }, { "name": "webonyx/graphql-php", - "version": "v15.31.3", + "version": "v15.31.5", "source": { "type": "git", "url": "https://github.com/webonyx/graphql-php.git", - "reference": "c20acbef1cb4af427ef6797512bfb2e651a85db9" + "reference": "089c4ef7e112df85788cfe06596278a8f99f4aa9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/c20acbef1cb4af427ef6797512bfb2e651a85db9", - "reference": "c20acbef1cb4af427ef6797512bfb2e651a85db9", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/089c4ef7e112df85788cfe06596278a8f99f4aa9", + "reference": "089c4ef7e112df85788cfe06596278a8f99f4aa9", "shasum": "" }, "require": { @@ -99,7 +99,7 @@ "nyholm/psr7": "^1.5", "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "2.1.43", + "phpstan/phpstan": "2.1.46", "phpstan/phpstan-phpunit": "2.0.16", "phpstan/phpstan-strict-rules": "2.0.10", "phpunit/phpunit": "^9.5 || ^10.5.21 || ^11", @@ -110,7 +110,7 @@ "symfony/polyfill-php81": "^1.23", "symfony/var-exporter": "^5 || ^6 || ^7 || ^8", "thecodingmachine/safe": "^1.3 || ^2 || ^3", - "ticketswap/phpstan-error-formatter": "1.2.6" + "ticketswap/phpstan-error-formatter": "1.3.0" }, "suggest": { "amphp/http-server": "To leverage async resolving with webserver on AMPHP platform", @@ -135,7 +135,7 @@ ], "support": { "issues": "https://github.com/webonyx/graphql-php/issues", - "source": "https://github.com/webonyx/graphql-php/tree/v15.31.3" + "source": "https://github.com/webonyx/graphql-php/tree/v15.31.5" }, "funding": [ { @@ -147,7 +147,7 @@ "type": "open_collective" } ], - "time": "2026-03-29T18:22:41+00:00" + "time": "2026-04-11T18:06:15+00:00" } ], "packages-dev": [], From 3227d60988495ae5522eba76f1fc059e96be6b07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 07:47:16 -0600 Subject: [PATCH 02/21] chore: bump @stoplight/spectral-cli from 6.15.0 to 6.15.1 (#888) --- package-lock.json | 18 ++++++++++++------ package.json | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 45b3545e..dc7ec7dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,10 +4,9 @@ "requires": true, "packages": { "": { - "name": "pfsense-api", "devDependencies": { "@prettier/plugin-php": "^0.25.0", - "@stoplight/spectral-cli": "^6.15.0", + "@stoplight/spectral-cli": "^6.15.1", "prettier": "^3.8.1" } }, @@ -242,9 +241,9 @@ } }, "node_modules/@stoplight/spectral-cli": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-cli/-/spectral-cli-6.15.0.tgz", - "integrity": "sha512-FVeQIuqQQnnLfa8vy+oatTKUve7uU+3SaaAfdjpX/B+uB1NcfkKRJYhKT9wMEehDRaMPL5AKIRYMCFerdEbIpw==", + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-cli/-/spectral-cli-6.15.1.tgz", + "integrity": "sha512-ev72bUglbaZvFSMWCP5o1Iso5NGgbLZOAuedvRxYrUMey9dVCR83i033tSFvDv6cpj86HsbEmiilh8vwrY/asQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -262,7 +261,7 @@ "chalk": "4.1.2", "fast-glob": "~3.2.12", "hpagent": "~1.2.0", - "lodash": "~4.17.21", + "lodash": "^4.18.1", "pony-cause": "^1.1.1", "stacktracey": "^2.1.8", "tslib": "^2.8.1", @@ -275,6 +274,13 @@ "node": "^16.20 || ^18.18 || >= 20.17" } }, + "node_modules/@stoplight/spectral-cli/node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@stoplight/spectral-core": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.21.0.tgz", diff --git a/package.json b/package.json index 3fcccbb2..e40baf9d 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "devDependencies": { "prettier": "^3.8.1", "@prettier/plugin-php": "^0.25.0", - "@stoplight/spectral-cli": "^6.15.0" + "@stoplight/spectral-cli": "^6.15.1" } } From ca9c2971fb05d229dcd24ebbe6f82b6f0a4d16d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 07:48:08 -0600 Subject: [PATCH 03/21] chore: bump firebase/php-jwt from 7.0.4 to 7.0.5 (#881) --- composer.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index cb080020..8244803b 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "firebase/php-jwt", - "version": "v7.0.4", + "version": "v7.0.5", "source": { "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "e41f1bd7dbe3c5455c3f72d4338cfeb083b71931" + "url": "https://github.com/googleapis/php-jwt.git", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/e41f1bd7dbe3c5455c3f72d4338cfeb083b71931", - "reference": "e41f1bd7dbe3c5455c3f72d4338cfeb083b71931", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", "shasum": "" }, "require": { @@ -65,10 +65,10 @@ "php" ], "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v7.0.4" + "issues": "https://github.com/googleapis/php-jwt/issues", + "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" }, - "time": "2026-03-27T21:17:19+00:00" + "time": "2026-04-01T20:38:03+00:00" }, { "name": "webonyx/graphql-php", From c5125ea73ca024a7b66be7df6d0d76a37dba11de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 04:24:03 +0000 Subject: [PATCH 04/21] chore: bump actions/upload-artifact from 7.0.0 to 7.0.1 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 4 ++-- .github/workflows/release.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b66b3eb8..3690b7f6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: /usr/local/bin/VBoxManage controlvm ${{ matrix.FREEBSD_VERSION }} poweroff || true /usr/local/bin/VBoxManage snapshot ${{matrix.FREEBSD_VERSION}} restore initial - - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: pfSense-pkg-RESTAPI-${{ env.BUILD_VERSION }}-${{ matrix.FREEBSD_ID }}.pkg path: pfSense-pkg-RESTAPI-${{ env.BUILD_VERSION }}-${{ matrix.FREEBSD_ID }}.pkg @@ -96,7 +96,7 @@ jobs: /usr/local/bin/VBoxManage controlvm ${{ matrix.PFSENSE_VERSION }} poweroff || true /usr/local/bin/VBoxManage snapshot ${{ matrix.PFSENSE_VERSION }} restore initial - - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: openapi-${{ matrix.PFSENSE_VERSION }}.json path: openapi-${{ matrix.PFSENSE_VERSION }}.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 47e0b6c0..297a3ac1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,7 +64,7 @@ jobs: /usr/local/bin/VBoxManage controlvm ${{ matrix.FREEBSD_VERSION }} poweroff || true /usr/local/bin/VBoxManage snapshot ${{matrix.FREEBSD_VERSION}} restore initial - - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: pfSense-${{ matrix.PFSENSE_VERSION }}-pkg-RESTAPI.pkg path: pfSense-${{ matrix.PFSENSE_VERSION }}-pkg-RESTAPI.pkg @@ -116,13 +116,13 @@ jobs: /usr/local/bin/VBoxManage snapshot pfSense-${{ env.DEFAULT_PFSENSE_VERSION }}-RELEASE restore initial - name: Upload OpenAPI schema - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: openapi.json path: openapi.json - name: Upload GraphQL schema - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: schema.graphql path: schema.graphql From a29c57a506fef31828cdc529e7735a095314d180 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 13:48:31 +0000 Subject: [PATCH 05/21] chore: bump prettier from 3.8.1 to 3.8.3 Bumps [prettier](https://github.com/prettier/prettier) from 3.8.1 to 3.8.3. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.8.1...3.8.3) --- updated-dependencies: - dependency-name: prettier dependency-version: 3.8.3 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc7ec7dc..ea6bb71a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "devDependencies": { "@prettier/plugin-php": "^0.25.0", "@stoplight/spectral-cli": "^6.15.1", - "prettier": "^3.8.1" + "prettier": "^3.8.3" } }, "node_modules/@asyncapi/specs": { @@ -2173,9 +2173,9 @@ } }, "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index e40baf9d..e0401f37 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "devDependencies": { - "prettier": "^3.8.1", + "prettier": "^3.8.3", "@prettier/plugin-php": "^0.25.0", "@stoplight/spectral-cli": "^6.15.1" } From 7fd99f0a342966d2005d90a8228a154a2b6b60bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 07:50:58 -0600 Subject: [PATCH 06/21] chore: bump actions/setup-node from 6.3.0 to 6.4.0 (#887) --- .github/workflows/build.yml | 2 +- .github/workflows/quality.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3690b7f6..d5faef96 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,7 +119,7 @@ jobs: path: openapi-${{ matrix.PFSENSE_VERSION }}.json - name: Install Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "20" diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index c2450ab3..6358f03d 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 20 - name: Install npm packages From 39230cbe6d1523c03a2c3594e17ac7d2bee080c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 19:07:02 +0000 Subject: [PATCH 07/21] chore: bump webonyx/graphql-php from 15.31.5 to 15.32.3 (#882) Bumps [webonyx/graphql-php](https://github.com/webonyx/graphql-php) from 15.31.5 to 15.32.3. - [Release notes](https://github.com/webonyx/graphql-php/releases) - [Changelog](https://github.com/webonyx/graphql-php/blob/master/CHANGELOG.md) - [Commits](https://github.com/webonyx/graphql-php/compare/v15.31.5...v15.32.3) --- updated-dependencies: - dependency-name: webonyx/graphql-php dependency-version: 15.32.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jared Hendrickson --- composer.lock | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/composer.lock b/composer.lock index 8244803b..322cb115 100644 --- a/composer.lock +++ b/composer.lock @@ -72,16 +72,16 @@ }, { "name": "webonyx/graphql-php", - "version": "v15.31.5", + "version": "v15.32.3", "source": { "type": "git", "url": "https://github.com/webonyx/graphql-php.git", - "reference": "089c4ef7e112df85788cfe06596278a8f99f4aa9" + "reference": "993bf0bea17f870412ad8a90f60c41cb8d5f1145" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/089c4ef7e112df85788cfe06596278a8f99f4aa9", - "reference": "089c4ef7e112df85788cfe06596278a8f99f4aa9", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/993bf0bea17f870412ad8a90f60c41cb8d5f1145", + "reference": "993bf0bea17f870412ad8a90f60c41cb8d5f1145", "shasum": "" }, "require": { @@ -90,16 +90,16 @@ "php": "^7.4 || ^8" }, "require-dev": { - "amphp/amp": "^2.6", - "amphp/http-server": "^2.1", + "amphp/amp": "^2.6 || ^3", + "amphp/http-server": "^2.1 || ^3", "dms/phpunit-arraysubset-asserts": "dev-master", "ergebnis/composer-normalize": "^2.28", - "friendsofphp/php-cs-fixer": "3.94.2", + "friendsofphp/php-cs-fixer": "3.95.1", "mll-lab/php-cs-fixer-config": "5.13.0", "nyholm/psr7": "^1.5", "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "2.1.46", + "phpstan/phpstan": "2.1.51", "phpstan/phpstan-phpunit": "2.0.16", "phpstan/phpstan-strict-rules": "2.0.10", "phpunit/phpunit": "^9.5 || ^10.5.21 || ^11", @@ -113,6 +113,7 @@ "ticketswap/phpstan-error-formatter": "1.3.0" }, "suggest": { + "amphp/amp": "To leverage async resolving on AMPHP platform (v3 with AmpFutureAdapter, v2 with AmpPromiseAdapter)", "amphp/http-server": "To leverage async resolving with webserver on AMPHP platform", "psr/http-message": "To use standard GraphQL server", "react/promise": "To leverage async resolving on React PHP platform" @@ -135,7 +136,7 @@ ], "support": { "issues": "https://github.com/webonyx/graphql-php/issues", - "source": "https://github.com/webonyx/graphql-php/tree/v15.31.5" + "source": "https://github.com/webonyx/graphql-php/tree/v15.32.3" }, "funding": [ { @@ -147,7 +148,7 @@ "type": "open_collective" } ], - "time": "2026-04-11T18:06:15+00:00" + "time": "2026-04-24T13:49:35+00:00" } ], "packages-dev": [], From f846dcf3aacf0e50af3f391f5f489344a1eae9ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 20:09:23 -0600 Subject: [PATCH 08/21] chore: bump lodash in the npm_and_yarn group across 1 directory (#892) Bumps the npm_and_yarn group with 1 update in the / directory: [lodash](https://github.com/lodash/lodash). Updates `lodash` from 4.17.23 to 4.18.1 - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 76 +++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index ea6bb71a..d90e2d16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -274,17 +274,10 @@ "node": "^16.20 || ^18.18 || >= 20.17" } }, - "node_modules/@stoplight/spectral-cli/node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@stoplight/spectral-core": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.21.0.tgz", - "integrity": "sha512-oj4e/FrDLUhBRocIW+lRMKlJ/q/rDZw61HkLbTFsdMd+f/FTkli2xHNB1YC6n1mrMKjjvy7XlUuFkC7XxtgbWw==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.22.0.tgz", + "integrity": "sha512-4hTxMDs4TFUG4/jKjaZttA65gNuV2PCKI9+51I+J4nL6ylo17DlbW+sl6byKnBuV/85HxaV33ri5fEGlp8lTSA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -297,17 +290,17 @@ "@stoplight/types": "~13.6.0", "@types/es-aggregate-error": "^1.0.2", "@types/json-schema": "^7.0.11", - "ajv": "^8.17.1", + "ajv": "^8.18.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.1", "es-aggregate-error": "^1.0.7", + "expr-eval-fork": "^3.0.1", "jsonpath-plus": "^10.3.0", - "lodash": "~4.17.23", + "lodash": "^4.18.1", "lodash.topath": "^4.5.2", - "minimatch": "3.1.2", + "minimatch": "^3.1.4", "nimma": "0.2.3", "pony-cause": "^1.1.1", - "simple-eval": "1.0.1", "tslib": "^2.8.1" }, "engines": { @@ -368,9 +361,9 @@ } }, "node_modules/@stoplight/spectral-functions": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.10.1.tgz", - "integrity": "sha512-obu8ZfoHxELOapfGsCJixKZXZcffjg+lSoNuttpmUFuDzVLT3VmH8QkPXfOGOL5Pz80BR35ClNAToDkdnYIURg==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.10.2.tgz", + "integrity": "sha512-PIfPUgTRo8EtAnL1MIrzhHoUuojSaE8shGSMaHS3BxGyc8d079BE5+TqJa1/WLUb9YT9JQnZ0Aj4xfi8NcJOIw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -379,11 +372,11 @@ "@stoplight/spectral-core": "^1.19.4", "@stoplight/spectral-formats": "^1.8.1", "@stoplight/spectral-runtime": "^1.1.2", - "ajv": "^8.17.1", + "ajv": "^8.18.0", "ajv-draft-04": "~1.0.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.1", - "lodash": "~4.17.21", + "lodash": "^4.18.1", "tslib": "^2.8.1" }, "engines": { @@ -510,9 +503,9 @@ "dev": true }, "node_modules/@stoplight/spectral-rulesets": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.22.0.tgz", - "integrity": "sha512-l2EY2jiKKLsvnPfGy+pXC0LeGsbJzcQP5G/AojHgf+cwN//VYxW1Wvv4WKFx/CLmLxc42mJYF2juwWofjWYNIQ==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.22.1.tgz", + "integrity": "sha512-DaaQJioKuYkRsOuKIJfX2ek7G7f6OCU3CI3K7ABaOcTFMiHj29SJLDdb04mCjXZFXMlXHjmCl2ZpKW6heieXpw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -525,11 +518,11 @@ "@stoplight/spectral-runtime": "^1.1.2", "@stoplight/types": "^13.6.0", "@types/json-schema": "^7.0.7", - "ajv": "^8.17.1", + "ajv": "^8.18.0", "ajv-formats": "~2.1.1", "json-schema-traverse": "^1.0.0", "leven": "3.1.0", - "lodash": "~4.17.21", + "lodash": "^4.18.1", "tslib": "^2.8.1" }, "engines": { @@ -1225,6 +1218,16 @@ "node": ">=6" } }, + "node_modules/expr-eval-fork": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/expr-eval-fork/-/expr-eval-fork-3.0.3.tgz", + "integrity": "sha512-BhC+hbc5lIVjygr840n5DEkW3MQq7H9o+mc1/N7Z5uIiCFVyESLL5DIE7LNq4CYUNxy+XjA+3jRrL/h0Kt2xcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1960,9 +1963,9 @@ "license": "MIT" }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, @@ -2011,10 +2014,11 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2415,18 +2419,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/simple-eval": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-eval/-/simple-eval-1.0.1.tgz", - "integrity": "sha512-LH7FpTAkeD+y5xQC4fzS+tFtaNlvt3Ib1zKzvhjv/Y+cioV4zIuw4IZr2yhRLu67CWL7FR9/6KXKnjRoZTvGGQ==", - "dev": true, - "dependencies": { - "jsep": "^1.3.6" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", From 49ba7a0be39751e645394f534097c125e984032c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 20:09:49 -0600 Subject: [PATCH 09/21] chore: bump actions/upload-pages-artifact from 4.0.0 to 5.0.0 (#889) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 4.0.0 to 5.0.0. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/7b1f4a764d45c48632c6b24a0339c27f5614fb0b...fc324d3547104276b827a68afc52ff2a11cc49c9) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jared Hendrickson --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 297a3ac1..6119bd8c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -207,7 +207,7 @@ jobs: mv ./.phpdoc/build/* ./www/php-docs/ - name: Upload artifact - uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: path: "./www" From f8d55753adfb3e6f283fdc83b114a5bb76f29938 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 20:10:12 -0600 Subject: [PATCH 10/21] chore: bump softprops/action-gh-release from 2.6.1 to 3.0.0 (#890) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.6.1 to 3.0.0. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/153bb8e04406b158c6c84fc1615b65b24149a1fe...b4309332981a82ec1c5618f44dd2e27cc8bfbfda) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 3.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jared Hendrickson --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6119bd8c..d53e5c84 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -70,7 +70,7 @@ jobs: path: pfSense-${{ matrix.PFSENSE_VERSION }}-pkg-RESTAPI.pkg - name: Release - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 + uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 with: files: pfSense-${{ matrix.PFSENSE_VERSION }}-pkg-RESTAPI.pkg From 0783bde01080b5f2bbc527b9fc92760f230eb143 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 20:10:44 -0600 Subject: [PATCH 11/21] chore: bump actions/deploy-pages from 4.0.5 to 5.0.0 (#891) Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 4.0.5 to 5.0.0. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e...cd2ce8fcbc39b97be8ca5fce6e763baed58fa128) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jared Hendrickson --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d53e5c84..9ea964fa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -213,4 +213,4 @@ jobs: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 From 605082c98a91fab23b43ef090b4c95097fc306e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 May 2026 08:22:36 -0600 Subject: [PATCH 12/21] chore: bump fast-uri in the npm_and_yarn group across 1 directory (#893) Bumps the npm_and_yarn group with 1 update in the / directory: [fast-uri](https://github.com/fastify/fast-uri). Updates `fast-uri` from 3.0.2 to 3.1.2 - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](https://github.com/fastify/fast-uri/compare/v3.0.2...v3.1.2) --- updated-dependencies: - dependency-name: fast-uri dependency-version: 3.1.2 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index d90e2d16..fdc00204 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1257,10 +1257,21 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", - "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", - "dev": true + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, "node_modules/fastq": { "version": "1.17.1", From c89de07880d9dc161fff5d35faca629b7a738f4a Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sat, 9 May 2026 08:30:05 -0600 Subject: [PATCH 13/21] fix(Field): increase maximum size of arrays for many fields #879 Initially there was a concern if too many objects had large 'many' values, as it did not play nicely with the level of recursion required for HATEOAS and other object relationship systems. This is not as big of a concern anymore after the ModelCache was created so increasing this significantly is warranted. --- .../files/usr/local/pkg/RESTAPI/Core/Field.inc | 7 ++++++- .../files/usr/local/pkg/RESTAPI/Fields/Base64Field.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/DateTimeField.inc | 2 +- .../usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/FloatField.inc | 2 +- .../usr/local/pkg/RESTAPI/Fields/ForeignModelField.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/IntegerField.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/ObjectField.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/PortField.inc | 2 +- .../usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/StringField.inc | 2 +- .../files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc | 2 +- 13 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Core/Field.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Core/Field.inc index 2e052053..4914f279 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Core/Field.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Core/Field.inc @@ -26,6 +26,11 @@ class Field { */ const SENSITIVE_MASK = '********'; + /** + * @const MANY_MAXIMUM is the maximum number of items a 'many' field can hold it's array. + */ + const MANY_MAXIMUM = 65535; + /** * Represents the current value for this Field. * @@ -144,7 +149,7 @@ class Field { public bool $representation_only = false, public bool $many = false, public int $many_minimum = 0, - public int $many_maximum = 128, + public int $many_maximum = Field::MANY_MAXIMUM, public string|null $delimiter = ',', public string $verbose_name = '', public string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/Base64Field.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/Base64Field.inc index 9805a488..b36fa094 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/Base64Field.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/Base64Field.inc @@ -85,7 +85,7 @@ class Base64Field extends Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, string|null $delimiter = ',', string $verbose_name = '', string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/DateTimeField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/DateTimeField.inc index 34b85f9b..b0a992db 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/DateTimeField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/DateTimeField.inc @@ -93,7 +93,7 @@ class DateTimeField extends Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, string|null $delimiter = ',', string $verbose_name = '', string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc index c74aa375..41112e8a 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc @@ -111,7 +111,7 @@ class FilterAddressField extends InterfaceField { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, string|null $delimiter = ',', string $verbose_name = '', string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc index 25665d8e..62568cf2 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc @@ -80,7 +80,7 @@ class FloatField extends RESTAPI\Core\Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, public int $minimum = 0, public int $maximum = PHP_INT_MAX, string|null $delimiter = ',', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ForeignModelField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ForeignModelField.inc index a740b189..9a2920e8 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ForeignModelField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ForeignModelField.inc @@ -118,7 +118,7 @@ class ForeignModelField extends Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, string|null $delimiter = ',', string $verbose_name = '', string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/IntegerField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/IntegerField.inc index d77c79a1..538887dd 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/IntegerField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/IntegerField.inc @@ -81,7 +81,7 @@ class IntegerField extends Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, public int $minimum = 0, public int $maximum = PHP_INT_MAX, string|null $delimiter = ',', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc index c37421f0..9d4223a3 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc @@ -97,7 +97,7 @@ class InterfaceField extends StringField { bool $editable = true, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, string|null $delimiter = ',', string $verbose_name = '', string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ObjectField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ObjectField.inc index 8b323da0..a88a52f2 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ObjectField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/ObjectField.inc @@ -90,7 +90,7 @@ class ObjectField extends Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, public int $minimum_length = 0, public int $maximum_length = 1024, string|null $delimiter = ',', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/PortField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/PortField.inc index 097ebaaf..afed1b7a 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/PortField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/PortField.inc @@ -94,7 +94,7 @@ class PortField extends Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, ?string $delimiter = ',', string $verbose_name = '', string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc index 07c3af67..8665e8d1 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc @@ -103,7 +103,7 @@ class SpecialNetworkField extends InterfaceField { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, string|null $delimiter = ',', string $verbose_name = '', string $verbose_name_plural = '', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/StringField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/StringField.inc index c239f034..45565b28 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/StringField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/StringField.inc @@ -85,7 +85,7 @@ class StringField extends Field { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, public int $minimum_length = 0, public int $maximum_length = 1024, string|null $delimiter = ',', diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc index 47aac9c5..f5da69ac 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc @@ -85,7 +85,7 @@ class UnixTimeField extends IntegerField { bool $representation_only = false, bool $many = false, int $many_minimum = 0, - int $many_maximum = 128, + int $many_maximum = Field::MANY_MAXIMUM, int $minimum = 0, int $maximum = PHP_INT_MAX, public bool $auto_add_now = true, From f17217569044640c8be9508d9643fb4d16dd925b Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sat, 9 May 2026 09:15:33 -0600 Subject: [PATCH 14/21] fix(IPsecPhase2Encryption): allow 'auto' keylen to be represented as 0 #880 --- .../local/pkg/RESTAPI/Fields/KeyLenField.inc | 204 ++++++++++++++++++ .../RESTAPI/Models/IPsecPhase2Encryption.inc | 33 +-- .../Tests/APIFieldsKeyLenFieldTestCase.inc | 97 +++++++++ ...APIModelsIPsecPhase2EncryptionTestCase.inc | 45 ++-- 4 files changed, 335 insertions(+), 44 deletions(-) create mode 100644 pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/KeyLenField.inc create mode 100644 pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/KeyLenField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/KeyLenField.inc new file mode 100644 index 00000000..67ff48ea --- /dev/null +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/KeyLenField.inc @@ -0,0 +1,204 @@ + "type1"] to this parameter. + * @param array $validators An array of Validator objects to run against this field. + * @param string $help_text Set a description for this field. This description will be used in API documentation. + */ + public function __construct( + bool $required = false, + bool $unique = false, + mixed $default = null, + string $default_callable = '', + array $choices = [], + string $choices_callable = '', + bool $allow_null = false, + bool $editable = true, + bool $read_only = false, + bool $write_only = false, + bool $representation_only = false, + bool $many = false, + int $many_minimum = 0, + int $many_maximum = Field::MANY_MAXIMUM, + public int $minimum = 0, + public int $maximum = PHP_INT_MAX, + string|null $delimiter = ',', + string $verbose_name = '', + string $verbose_name_plural = '', + string $internal_name = '', + string $internal_namespace = '', + array $referenced_by = [], + array $conditions = [], + array $validators = [], + string $help_text = '', + ) { + parent::__construct( + type: 'integer', + required: $required, + unique: $unique, + default: $default, + default_callable: $default_callable, + choices: $choices, + choices_callable: $choices_callable, + allow_null: $allow_null, + editable: $editable, + read_only: $read_only, + write_only: $write_only, + representation_only: $representation_only, + many: $many, + many_minimum: $many_minimum, + many_maximum: $many_maximum, + delimiter: $delimiter, + verbose_name: $verbose_name, + verbose_name_plural: $verbose_name_plural, + internal_name: $internal_name, + internal_namespace: $internal_namespace, + referenced_by: $referenced_by, + conditions: $conditions, + validators: $validators + [ + new RESTAPI\Validators\NumericRangeValidator(minimum: $minimum, maximum: $maximum), + ], + help_text: $help_text, + ); + } + + /** + * Converts the field value from its representation value into it's internal value. This namely handles converting + * 0 to 'auto'. + * @param mixed $representation_value The representation value to convert to its internal value + */ + protected function _to_internal(mixed $representation_value): array|string|null { + if ($representation_value === 0) { + return parent::_to_internal('auto'); + } + return parent::_to_internal($representation_value); + } + + /** + * Converts the field value to its representation form from its internal pfSense configuration value. + * @param string $internal_value The internal value from the pfSense configuration. + * @return int The field value in its representation form. + */ + protected function _from_internal(mixed $internal_value): mixed { + # Return the value as an integer if it's numeric + if (is_numeric($internal_value)) { + return intval($internal_value); + } + + # If the value is 'auto', return 0 (0 is the representation we use for auto) + if ($internal_value === 'auto') { + return 0; + } + + # If the value is an empty string, assume it's null + if ($internal_value === '') { + return null; + } + + # Otherwise, the internal value cannot be represented by this Field. Throw an error. + throw new RESTAPI\Responses\ServerError( + message: "Cannot parse KeyLenField '$this->name' from internal because its internal value is not a " . + "numeric value or 'auto'. Consider changing this field to a StringField.", + response_id: 'KEYLEN_FIELD_WITH_NON_INTEGER_INTERNAL_VALUE', + ); + } + + /** + * Converts this Field object to a PHP array representation of an OpenAPI schema property configuration. This is + * used when auto-generating API documentation. This method can be extended to add additional options to the OpenAPI + * schema property. + * @link https://swagger.io/docs/specification/data-models/ + * @return array A PHP array containing this field as a OpenAPI schema property configuration. + */ + public function to_openapi_property(): array { + # Run the parent to_openapi_property() to obtain the base property object, then make changes as needed. + $openapi_property = parent::to_openapi_property(); + + # Add the minimum and maximum to the OpenAPI property. + if ($this->many) { + $openapi_property['items']['minimum'] = $this->minimum; + $openapi_property['items']['maximum'] = $this->maximum; + } else { + $openapi_property['minimum'] = $this->minimum; + $openapi_property['maximum'] = $this->maximum; + } + + return $openapi_property; + } + + /** + * Converts this Field object into a pfSense webConfigurator form input. This method can be overridden by a child + * class to add custom input field creation. + * @param string $type The HTML input tag type. Not all Fields support input types. + * @param array $attributes An array of additional HTML input tag attributes. Not all Fields support input attributes. + * @return object The pfSense webConfigurator form input object. + * @link https://github.com/pfsense/pfsense/tree/master/src/usr/local/www/classes/Form + */ + public function to_form_input(string $type = 'number', array $attributes = []): object { + $attributes += ['min' => $this->minimum, 'max' => $this->maximum]; + return parent::to_form_input(type: $type, attributes: $attributes); + } +} diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc index 92dcb61a..be159645 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc @@ -5,6 +5,7 @@ namespace RESTAPI\Models; use RESTAPI\Core\Model; use RESTAPI\Dispatchers\IPsecApplyDispatcher; use RESTAPI\Fields\IntegerField; +use RESTAPI\Fields\KeyLenField; use RESTAPI\Fields\StringField; use RESTAPI\Responses\ValidationError; @@ -13,7 +14,7 @@ use RESTAPI\Responses\ValidationError; */ class IPsecPhase2Encryption extends Model { public StringField $name; - public IntegerField $keylen; + public KeyLenField $keylen; public function __construct(mixed $id = null, mixed $parent_id = null, array $data = [], mixed ...$options) { # Obtain global p2 algorithm variables @@ -34,38 +35,17 @@ class IPsecPhase2Encryption extends Model { internal_name: 'name', help_text: 'The name of the encryption algorithm to use for this P2 encryption item.', ); - $this->keylen = new IntegerField( + $this->keylen = new KeyLenField( required: true, + choices_callable: 'get_supported_keylens', internal_name: 'keylen', conditions: ['name' => $this->get_keylen_enabled_algos()], - help_text: 'The key length for the encryption algorithm.', + help_text: 'The key length for the encryption algorithm. Use 0 to select key length automatically.', ); parent::__construct($id, $parent_id, $data, ...$options); } - /** - * Adds extra validation to the `keylen` field. - * @param int $keylen The incoming value to be validated. - * @returns int The validated value to be assigned. - * @throws ValidationError When the $keylen is not supported by the - * `name` field's assigned value. - */ - public function validate_keylen(int $keylen): int { - # Variables - $supported_keylens = $this->get_supported_keylens(name: $this->name->value); - - # Throw a validation error if this $keylen is not supported for the assigned algo - if (!in_array($keylen, $supported_keylens)) { - throw new ValidationError( - message: "Field `keylen` value `$keylen` is not valid for the `{$this->name->value}` algorithm.", - response_id: 'IPSEC_PHASE_2_ENCRYPTION_ALGORITHM_KEYLEN_INVALID_CHOICE', - ); - } - - return $keylen; - } - /** * Obtains all supported key lengths for an encryption algorithm with a provided algorithm name. * @param string $name The encryption algorithm name to obtain key lengths for. @@ -100,6 +80,9 @@ class IPsecPhase2Encryption extends Model { } } + # Accept '0', as this is the representation keyword for 'auto' + $key_lens[] = 0; + return $key_lens; } diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc new file mode 100644 index 00000000..f46e5a59 --- /dev/null +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc @@ -0,0 +1,97 @@ +assert_equals(get_class($field->validators[0]), 'RESTAPI\Validators\NumericRangeValidator'); + } + + /** + * Checks that `_from_internal()` converts a numeric string to an integer. + */ + public function test_from_internal_numeric_string_returns_integer(): void { + $field = new KeyLenField(); + $field->from_internal('256'); + $this->assert_equals($field->value, 256); + $this->assert_is_true(is_int($field->value)); + } + + /** + * Checks that `_from_internal()` converts the 'auto' keyword to 0. + */ + public function test_from_internal_auto_returns_zero(): void { + $field = new KeyLenField(); + $field->from_internal('auto'); + $this->assert_equals($field->value, 0); + } + + /** + * Checks that `_from_internal()` converts an empty string to null. + */ + public function test_from_internal_empty_string_returns_null(): void { + $field = new KeyLenField(allow_null: true); + $field->from_internal(''); + $this->assert_is_null($field->value); + } + + /** + * Checks that `_from_internal()` throws a ServerError for non-numeric, non-'auto' values. + */ + public function test_from_internal_invalid_value_throws_server_error(): void { + $this->assert_throws_response( + response_id: 'KEYLEN_FIELD_WITH_NON_INTEGER_INTERNAL_VALUE', + code: 500, + callable: function () { + $field = new KeyLenField(); + $field->from_internal('not_valid'); + }, + ); + } + + /** + * Checks that `keylen` can be assigned the value 0 and that `to_internal()` converts it to 'auto'. + */ + public function test_to_internal_zero_returns_auto(): void { + $field = new KeyLenField(default: 0); + $field->value = 0; + $this->assert_equals($field->value, 0); + $this->assert_equals($field->to_internal(), 'auto'); + } + + /** + * Checks that `to_internal()` passes non-zero integers through normally. + */ + public function test_to_internal_non_zero_passes_through(): void { + $field = new KeyLenField(default: 128); + $field->value = 128; + $this->assert_equals($field->to_internal(), 128); + } + + /** + * Checks that `to_openapi_property()` includes `minimum` and `maximum` for non-many fields. + */ + public function test_to_openapi_property_includes_min_max(): void { + $field = new KeyLenField(minimum: 64, maximum: 512); + $property = $field->to_openapi_property(); + $this->assert_equals($property['minimum'], 64); + $this->assert_equals($property['maximum'], 512); + } + + /** + * Checks that `to_openapi_property()` includes `minimum` and `maximum` under `items` for many fields. + */ + public function test_to_openapi_property_includes_min_max_for_many(): void { + $field = new KeyLenField(many: true, minimum: 64, maximum: 512); + $property = $field->to_openapi_property(); + $this->assert_equals($property['items']['minimum'], 64); + $this->assert_equals($property['items']['maximum'], 512); + } +} diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc index 56536a12..1a428abd 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc @@ -3,34 +3,41 @@ namespace RESTAPI\Tests; use RESTAPI\Core\TestCase; +use RESTAPI\Fields\KeyLenField; use RESTAPI\Models\IPsecPhase2Encryption; class APIModelsIPsecPhase2EncryptionTestCase extends TestCase { # NOTE: This model is partially tested by /RESTAPI/Tests/APIModelsIPsecPhase2TestCase /** - * Checks that the `keylen` must be valid for the given encryption algorithm `name`. + * Checks that the `keylen` field is a KeyLenField instance. + */ + public function test_keylen_field_type(): void { + $p2 = new IPsecPhase2Encryption(); + $this->assert_is_true($p2->keylen instanceof KeyLenField); + } + + /** + * Checks that the `keylen` field uses `get_supported_keylens` as its choices callable. + */ + public function test_keylen_field_uses_choices_callable(): void { + $p2 = new IPsecPhase2Encryption(); + $this->assert_equals($p2->keylen->choices_callable, 'get_supported_keylens'); + } + + /** + * Checks that the `keylen` field's choices_callable correctly restricts values + * to those supported by the selected encryption algorithm. */ public function test_keylen_choices(): void { - # Ensure an error is thrown if the requested key length is not supported for the given encryption algorithm - $this->assert_throws_response( - response_id: 'IPSEC_PHASE_2_ENCRYPTION_ALGORITHM_KEYLEN_INVALID_CHOICE', - code: 400, - callable: function () { - $p2 = new IPsecPhase2Encryption(); - $p2->name->value = 'aes'; - $p2->validate_keylen(257); - }, - ); + # Ensure that `get_supported_keylens` returns only valid key lengths for 'aes' + $supported = IPsecPhase2Encryption::get_supported_keylens('aes'); + $this->assert_is_true(in_array(128, $supported, true)); + $this->assert_is_true(in_array(256, $supported, true)); + $this->assert_is_false(in_array(257, $supported, true)); - # Ensure no error is thrown when the key length is supported for the given encryption algorithm - $this->assert_does_not_throw( - callable: function () { - $p2 = new IPsecPhase2Encryption(); - $p2->name->value = 'aes'; - $p2->validate_keylen(256); - }, - ); + # Ensure 0 (auto) is always included in the supported key lengths + $this->assert_is_true(in_array(0, $supported, true)); } /** From e51496dd48f92ffa0158e69c2b3a279524b3c026 Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sat, 9 May 2026 18:43:39 -0600 Subject: [PATCH 15/21] test: fix null assertion in KeyLenField test --- .../local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc index f46e5a59..14321d53 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc @@ -39,7 +39,7 @@ class APIFieldsKeyLenFieldTestCase extends TestCase { public function test_from_internal_empty_string_returns_null(): void { $field = new KeyLenField(allow_null: true); $field->from_internal(''); - $this->assert_is_null($field->value); + $this->assert_equals($field->value, null); } /** From 46092f540dc9fa72dcab7947105963bc28a6df34 Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sat, 9 May 2026 18:44:08 -0600 Subject: [PATCH 16/21] chore: cleanup unused import in IPsecPhase2Encryption --- .../files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc index be159645..dca621c3 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc @@ -4,7 +4,6 @@ namespace RESTAPI\Models; use RESTAPI\Core\Model; use RESTAPI\Dispatchers\IPsecApplyDispatcher; -use RESTAPI\Fields\IntegerField; use RESTAPI\Fields\KeyLenField; use RESTAPI\Fields\StringField; use RESTAPI\Responses\ValidationError; From cd562b0b53333a7d7bcd8a6e9d7b9c5d09a68030 Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sat, 9 May 2026 18:47:28 -0600 Subject: [PATCH 17/21] chore: add missing Field class imports --- .../files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc | 1 + .../files/usr/local/pkg/RESTAPI/Fields/FloatField.inc | 4 +++- .../files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc | 1 + .../usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc | 1 + .../files/usr/local/pkg/RESTAPI/Fields/UIDField.inc | 3 ++- .../files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc | 1 + 6 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc index 41112e8a..ecaa3ccc 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FilterAddressField.inc @@ -5,6 +5,7 @@ namespace RESTAPI\Fields; require_once 'RESTAPI/autoloader.inc'; require_once 'RESTAPI/Fields/InterfaceField.inc'; +use RESTAPI\Core\Field; use RESTAPI\Models\FirewallAlias; use RESTAPI\Responses\ServerError; use RESTAPI\Responses\ValidationError; diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc index 62568cf2..c188e978 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc @@ -5,11 +5,13 @@ namespace RESTAPI\Fields; require_once 'RESTAPI/autoloader.inc'; use RESTAPI; +use RESTAPI\Core\Field; /** * Defines a Field object for validating and storing a floating point number. */ -class FloatField extends RESTAPI\Core\Field { +class FloatField extends Field +{ /** * Defines the FloatField object and sets its options. * @param bool $required If `true`, this field is required to have a value at all times. diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc index 9d4223a3..27d941ab 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/InterfaceField.inc @@ -6,6 +6,7 @@ require_once 'RESTAPI/Fields/StringField.inc'; require_once 'RESTAPI/autoloader.inc'; use RESTAPI; +use RESTAPI\Core\Field; use RESTAPI\Core\Model; use RESTAPI\Core\ModelSet; use RESTAPI\Models\NetworkInterface; diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc index 8665e8d1..f3f76b84 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/SpecialNetworkField.inc @@ -5,6 +5,7 @@ namespace RESTAPI\Fields; require_once 'RESTAPI/autoloader.inc'; require_once 'RESTAPI/Fields/InterfaceField.inc'; +use RESTAPI\Core\Field; use RESTAPI\Models\FirewallAlias; use RESTAPI\Models\NetworkInterface; use RESTAPI\Responses\ServerError; diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UIDField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UIDField.inc index fa9da148..f04efc46 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UIDField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UIDField.inc @@ -5,11 +5,12 @@ namespace RESTAPI\Fields; require_once 'RESTAPI/autoloader.inc'; use RESTAPI; +use RESTAPI\Core\Field; /** * Defines a Field that contains a unique ID. This field will automatically populate a unique ID that is immutable. */ -class UIDField extends RESTAPI\Core\Field { +class UIDField extends Field { /** * Defines the UIDField object and sets its options. * @param string $prefix A specific string to prefix to the generated UID. diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc index f5da69ac..1b3a23da 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/UnixTimeField.inc @@ -5,6 +5,7 @@ namespace RESTAPI\Fields; require_once 'RESTAPI/autoloader.inc'; use RESTAPI; +use RESTAPI\Core\Field; use RESTAPI\Responses\ServerError; /** From c82d733eb6090a60e902725e1c010841388db589 Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sat, 9 May 2026 18:47:54 -0600 Subject: [PATCH 18/21] style: run prettier on changed files --- .../files/usr/local/pkg/RESTAPI/Fields/FloatField.inc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc index c188e978..234323be 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Fields/FloatField.inc @@ -10,8 +10,7 @@ use RESTAPI\Core\Field; /** * Defines a Field object for validating and storing a floating point number. */ -class FloatField extends Field -{ +class FloatField extends Field { /** * Defines the FloatField object and sets its options. * @param bool $required If `true`, this field is required to have a value at all times. From 3c9decc08fefcb434cc1cae0dcc55183eaa8424b Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sun, 10 May 2026 09:19:55 -0600 Subject: [PATCH 19/21] chore(IPsecPhase2Encryption): source algo name from name field, not direct arg --- .../local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc index dca621c3..bd0777de 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Models/IPsecPhase2Encryption.inc @@ -50,19 +50,19 @@ class IPsecPhase2Encryption extends Model { * @param string $name The encryption algorithm name to obtain key lengths for. * @returns array An array of supported key lengths for this encryption algorithm. */ - public static function get_supported_keylens(string $name): array { + public function get_supported_keylens(): array { global $p2_ealgos; # Throw an error if an encryption algorithm does not exist with this name. - if (!array_key_exists($name, $p2_ealgos)) { + if (!array_key_exists($this->name->value, $p2_ealgos)) { throw new ValidationError( - message: "Could not obtain supported key lengths for unknown algorithm `$name`.", + message: "Could not obtain supported key lengths for unknown algorithm `{$this->name->value}`.", response_id: 'IPSEC_PHASE_2_ENCRYPTION_COULD_NOT_GET_KEYLENS_FOR_UNKNOWN_ALGO', ); } # Obtain the attributes for the encryption algorithm with this $name - $p2_ealgo = $p2_ealgos[$name]; + $p2_ealgo = $p2_ealgos[$this->name->value]; $key_lens = []; # Determine available key lengths for this algo when selections are available From 187cc93425d91f2acf1369e5b1737f1c65da9abf Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sun, 10 May 2026 09:30:53 -0600 Subject: [PATCH 20/21] test(KeyLenField): to internal should produce a string, not int --- .../local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc index 14321d53..b4c9fa92 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIFieldsKeyLenFieldTestCase.inc @@ -72,7 +72,7 @@ class APIFieldsKeyLenFieldTestCase extends TestCase { public function test_to_internal_non_zero_passes_through(): void { $field = new KeyLenField(default: 128); $field->value = 128; - $this->assert_equals($field->to_internal(), 128); + $this->assert_equals($field->to_internal(), '128'); } /** From 19f32921dd3487cd34f0e3a963a21f6214c6e039 Mon Sep 17 00:00:00 2001 From: Jared Hendrickson Date: Sun, 10 May 2026 09:31:24 -0600 Subject: [PATCH 21/21] test(IPsecPhase2Encryption): replace references to old get_supported_keylens --- ...APIModelsIPsecPhase2EncryptionTestCase.inc | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc index 1a428abd..75114714 100644 --- a/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc +++ b/pfSense-pkg-RESTAPI/files/usr/local/pkg/RESTAPI/Tests/APIModelsIPsecPhase2EncryptionTestCase.inc @@ -9,14 +9,6 @@ use RESTAPI\Models\IPsecPhase2Encryption; class APIModelsIPsecPhase2EncryptionTestCase extends TestCase { # NOTE: This model is partially tested by /RESTAPI/Tests/APIModelsIPsecPhase2TestCase - /** - * Checks that the `keylen` field is a KeyLenField instance. - */ - public function test_keylen_field_type(): void { - $p2 = new IPsecPhase2Encryption(); - $this->assert_is_true($p2->keylen instanceof KeyLenField); - } - /** * Checks that the `keylen` field uses `get_supported_keylens` as its choices callable. */ @@ -31,7 +23,9 @@ class APIModelsIPsecPhase2EncryptionTestCase extends TestCase { */ public function test_keylen_choices(): void { # Ensure that `get_supported_keylens` returns only valid key lengths for 'aes' - $supported = IPsecPhase2Encryption::get_supported_keylens('aes'); + $p2e = new IPsecPhase2Encryption(name: 'aes'); + $supported = $p2e->get_supported_keylens(); + $this->assert_is_true(in_array(128, $supported, true)); $this->assert_is_true(in_array(256, $supported, true)); $this->assert_is_false(in_array(257, $supported, true)); @@ -48,8 +42,8 @@ class APIModelsIPsecPhase2EncryptionTestCase extends TestCase { # Ensure an error is not thrown if `get_supported_keylens()` receives a valid `name` $this->assert_does_not_throw( callable: function () { - $keylen_enabled_algo = IPsecPhase2Encryption::get_keylen_enabled_algos()[0]; - IPsecPhase2Encryption::get_supported_keylens(name: $keylen_enabled_algo); + $p2e = new IPsecPhase2Encryption(name: 'aes'); + $p2e->get_supported_keylens(); }, ); @@ -58,7 +52,8 @@ class APIModelsIPsecPhase2EncryptionTestCase extends TestCase { response_id: 'IPSEC_PHASE_2_ENCRYPTION_COULD_NOT_GET_KEYLENS_FOR_UNKNOWN_ALGO', code: 400, callable: function () { - IPsecPhase2Encryption::get_supported_keylens(name: 'not a valid encryption algorithm'); + $p2e = new IPsecPhase2Encryption(name: 'not a valid encryption algorithm'); + $p2e->get_supported_keylens(); }, ); } @@ -70,10 +65,19 @@ class APIModelsIPsecPhase2EncryptionTestCase extends TestCase { public function test_get_supported_keylens(): void { global $p2_ealgos; + $p2e = new IPsecPhase2Encryption(); + # Loop each encryption algorithm that supported variable key lengths foreach (IPsecPhase2Encryption::get_keylen_enabled_algos() as $algo) { + $p2e->name->value = $algo; + # Loop through each key length option available to this algorithm and ensure it meets the correct parameters - foreach (IPsecPhase2Encryption::get_supported_keylens(name: $algo) as $keylen) { + foreach ($p2e->get_supported_keylens() as $keylen) { + # Skip 0 as it's always considered valid + if ($keylen === 0) { + continue; + } + # Obtain the parameters for supported key lengths $min_keylen = $p2_ealgos[$algo]['keysel']['lo']; $max_keylen = $p2_ealgos[$algo]['keysel']['hi'];