From 431590149f2cbc77990a1932faf88267d5bbf85d Mon Sep 17 00:00:00 2001 From: Milind More Date: Tue, 7 Jul 2026 12:34:37 +0530 Subject: [PATCH] fix: support port comparison in REST origin validation, update lint-staged config, and document multi-environment setup --- .lefthook.yml | 8 ++-- .lintstagedrc.mjs | 2 +- AGENTS.md | 43 ++++++++++++++----- inc/Modules/Rest/Abstract_REST_Controller.php | 32 ++++++++++---- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/.lefthook.yml b/.lefthook.yml index bc61411..2aaea7a 100644 --- a/.lefthook.yml +++ b/.lefthook.yml @@ -1,4 +1,4 @@ -# pre-commit: -# commands: -# lint-staged: -# run: npx --no-install lint-staged +pre-commit: + commands: + lint-staged: + run: npx --no-install lint-staged diff --git a/.lintstagedrc.mjs b/.lintstagedrc.mjs index 61c8dfc..7453d0a 100644 --- a/.lintstagedrc.mjs +++ b/.lintstagedrc.mjs @@ -11,7 +11,7 @@ export default { '**/*.php': ( filenames ) => { const cwd = process.cwd(); const relativeFilenames = filenames - .map( ( filename ) => `"${ filename.replace( cwd + '/', '' ) }"` ) + .map( ( filename ) => `'${ filename.replace( cwd + '/', '' ) }'` ) .join( ' ' ); // Only fail if phpcbf itself failed (exit code 3). diff --git a/AGENTS.md b/AGENTS.md index a7164ed..266c3e0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,13 +1,36 @@ ## Important Files -- @docs/DEVELOPMENT.md: Detailed development guidelines, tools, directory tree map, and best practices. -- inc/: Contains the main plugin PHP code. -- assets/src/: Contains the source files for the plugin's assets (JavaScript, CSS). -- package.json: Contains our script commands. + +- @docs/DEVELOPMENT.md: detailed development guidelines and instructions, tools, directory tree map, and best practices. +- inc/: contains the main plugin code +- assets/src/: contains the source files for the plugin's assets (e.g., JavaScript, CSS). +- package.json: contains our script commands. ## Important Notes -Use `wp-env` for local development and testing. Key commands include: -- `npm run wp-env {command}`: Manage the local environment. -- `npm run wp-env:cli {command}`: Run commands inside the local environment's CLI container. -- `npm run wp-env run {container} -- --env-cwd=wp-content/plugins/oneupdate {command}`: Run commands inside a specific container in the plugin directory. -- `npm run wp-env start --xdebug-mode=coverage`: Start local environment with Xdebug enabled. -- `npm run wp-env:cli -- composer install`: Install composer dependencies inside the CLI container. + +- Use `wp-env` (v11 parallel environments setup) for local development and testing: + + ```cli + # Start the governing site (port 8888) + npm run wp-env start + + # Start the child/brand site (port 8890) + npm run wp-env:child start + + # Start the test environment (port 8889) + npm run wp-env:test start + + # Run CLI/Composer commands in the governing site + npm run wp-env:cli -- composer install + + # Run CLI commands in the child site + npm run wp-env:child run cli -- --env-cwd=wp-content/plugins/oneupdate {command} + + # Run PHPUnit tests + npm run test:php + ``` + +- Git Hooks & Pre-commit: + - Lefthook manages the git hooks. You can manually run the pre-commit hook on staged files with: + ```bash + npx --no-install lint-staged + ``` diff --git a/inc/Modules/Rest/Abstract_REST_Controller.php b/inc/Modules/Rest/Abstract_REST_Controller.php index be72828..f77c85e 100644 --- a/inc/Modules/Rest/Abstract_REST_Controller.php +++ b/inc/Modules/Rest/Abstract_REST_Controller.php @@ -77,12 +77,14 @@ public function check_api_permissions( $request ): bool { $request_origin = ! empty( $request_origin ) ? esc_url_raw( wp_unslash( $request_origin ) ) : ''; $parsed_origin = wp_parse_url( $request_origin ); $request_url = ! empty( $parsed_origin['scheme'] ) && ! empty( $parsed_origin['host'] ) ? sprintf( - '%s://%s', + '%s://%s%s', $parsed_origin['scheme'], - $parsed_origin['host'] + $parsed_origin['host'], + isset( $parsed_origin['port'] ) ? ':' . $parsed_origin['port'] : '' ) : ''; - if ( empty( $request_url ) || $this->is_url_from_host( get_site_url(), $parsed_origin['host'] ) ) { + $origin_port = $parsed_origin['port'] ?? 80; + if ( empty( $request_url ) || $this->is_url_from_host( get_site_url(), $parsed_origin['host'], $origin_port ) ) { return current_user_can( 'manage_options' ); } @@ -106,7 +108,7 @@ public function check_api_permissions( $request ): bool { // If it's not a healthcheck, compare the origins. $governing_site_url = Settings::get_parent_site_url(); if ( '/' . $this->namespace . '/health-check' !== $request->get_route() ) { - return ! empty( $governing_site_url ) ? $this->is_url_from_host( $governing_site_url, $parsed_origin['host'] ) : false; + return ! empty( $governing_site_url ) ? $this->is_url_from_host( $governing_site_url, $parsed_origin['host'], $origin_port ) : false; } // For health-checks, if no governing site is set, we set it now. @@ -117,15 +119,27 @@ public function check_api_permissions( $request ): bool { /** * Check if two URLs belong to the same host. * - * @param string $url The URL to check. - * @param string $host The host to compare against. + * @param string $url The URL to check. + * @param string $host The host to compare against. + * @param int|null $port Optional. The port to compare against. * - * @return bool True if both URLs belong to the same domain, false otherwise. + * @return bool True if both URLs belong to the same host (and port if specified), false otherwise. */ - private function is_url_from_host( string $url, string $host ): bool { + protected function is_url_from_host( string $url, string $host, ?int $port = null ): bool { $parsed_url = wp_parse_url( $url ); - return isset( $parsed_url['host'] ) && $parsed_url['host'] === $host; + // Compare both host and port to properly handle localhost with different ports. + if ( ! isset( $parsed_url['host'] ) || $parsed_url['host'] !== $host ) { + return false; + } + + // If a port was provided, also compare ports. + if ( null !== $port ) { + $url_port = $parsed_url['port'] ?? 80; + return $url_port === $port; + } + + return true; } /**