> $request * @return bool|WP_Error */ public function authorize_as_authenticated( WP_REST_Request $request ) { $authorized = $this->authorize_as_authenticated_ignoring_enablement( $request ); if ( true !== $authorized ) { return $authorized; } return wc_get_container()->get( PushNotifications::class )->should_be_enabled(); } /** * Checks the request is signed with the Jetpack blog token, so only WPCOM * can reach the endpoint. * * The module does not have to be enabled. WPCOM reads a disabled store to see * which devices it has registered, and a store is most worth looking at once * push notifications have been switched off for it. * * @param WP_REST_Request $request The request object. * @phpstan-param WP_REST_Request> $request * @return bool|WP_Error * * @since 11.2.0 */ public function authorize_as_from_wpcom( WP_REST_Request $request ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found -- Kept so every permission callback in this trait takes the same argument. if ( $this->is_signed_with_blog_token() ) { return true; } return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you are not allowed to do that.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); } /** * Checks the caller is either WPCOM or an allowed user, without requiring * the module to be enabled. * * WPCOM reads this endpoint to decide how to reach a store, and signs those * requests with the Jetpack blog token, which identifies no user. Requiring a * role would reject them. * * @param WP_REST_Request $request The request object. * @phpstan-param WP_REST_Request> $request * @return bool|WP_Error * * @since 11.2.0 */ public function authorize_as_from_wpcom_or_allowed_user( WP_REST_Request $request ) { if ( $this->is_signed_with_blog_token() ) { return true; } return $this->authorize_as_authenticated_ignoring_enablement( $request ); } /** * Allows WPCOM whatever the module's state, and allowed users only while * the module is enabled. * * WPCOM can remove a token before the store is switched back on and starts * sending to it again. Users of a disabled store get the missing-route 404 * the apps read as push notifications being unavailable. * * @param WP_REST_Request $request The request object. * @phpstan-param WP_REST_Request> $request * @return bool|WP_Error * * @since 11.3.0 */ public function authorize_wpcom_always_or_push_user_when_enabled( WP_REST_Request $request ) { if ( ! $this->is_signed_with_blog_token() && ! wc_get_container()->get( PushNotifications::class )->should_be_enabled() ) { return new WP_Error( 'rest_no_route', __( 'No route was found matching the URL and request method.', 'woocommerce' ), array( 'status' => WP_Http::NOT_FOUND ) ); } return $this->authorize_as_from_wpcom_or_allowed_user( $request ); } /** * Checks the user is authenticated and holds at least one role allowed to * interact with push notifications. * * @param WP_REST_Request $request The request object. * @phpstan-param WP_REST_Request> $request * @return bool|WP_Error */ private function authorize_as_authenticated_ignoring_enablement( WP_REST_Request $request ) { if ( ! get_current_user_id() ) { return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you are not allowed to do that.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); } return array_reduce( PushNotifications::ROLES_WITH_PUSH_NOTIFICATIONS_ENABLED, fn ( $carry, $role ) => $this->check_permission( $request, $role ) === true ? true : $carry, false ); } /** * Determines whether the request is signed with the Jetpack blog token, which * only WPCOM holds. * * @return bool * * @since 11.2.0 */ protected function is_signed_with_blog_token(): bool { return class_exists( Rest_Authentication::class ) && Rest_Authentication::is_signed_with_blog_token(); } }