Some checks failed
Security Monitoring & Compliance / Static Code Security Analysis (push) Has been cancelled
Security Monitoring & Compliance / Security Compliance Validation (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Security Analysis (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Code Quality & Standards (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Unit Tests (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Integration Tests (push) Has been cancelled
Security Monitoring & Compliance / Dependency Vulnerability Scan (push) Has been cancelled
Security Monitoring & Compliance / Secrets & Credential Scan (push) Has been cancelled
Security Monitoring & Compliance / WordPress Security Analysis (push) Has been cancelled
Security Monitoring & Compliance / Security Summary Report (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Deploy to Production (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Notification (push) Has been cancelled
Security Monitoring & Compliance / Security Team Notification (push) Has been cancelled
Major modernization of HVAC plugin for PHP 8+ with full backward compatibility: CORE MODERNIZATION: - Implement strict type declarations throughout codebase - Modernize main plugin class with PHP 8+ features - Convert array syntax to modern PHP format - Add constructor property promotion where applicable - Enhance security helpers with modern PHP patterns COMPATIBILITY FIXES: - Fix PHP 8.1+ enum compatibility (convert to class constants) - Fix union type compatibility (true|WP_Error → bool|WP_Error) - Remove mixed type declarations for PHP 8.0 compatibility - Add default arms to match expressions preventing UnhandledMatchError - Fix method naming inconsistency (ensureRegistrationAccess callback) - Add null coalescing in TEC integration for strict type compliance DEPLOYMENT STATUS: ✅ Successfully deployed and tested on staging ✅ Site functional at https://upskill-staging.measurequick.com ✅ Expert code review completed with GPT-5 validation ✅ MCP Playwright testing confirms functionality Ready for production deployment when requested. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
234 lines
No EOL
5.3 KiB
PHP
234 lines
No EOL
5.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* HVAC Community Events Security Helper
|
|
*
|
|
* Provides security utilities and validation methods
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @subpackage Includes
|
|
* @since 1.1.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Class HVAC_Security
|
|
*/
|
|
class HVAC_Security {
|
|
|
|
/**
|
|
* Verify a nonce with proper error handling
|
|
*
|
|
* @param string $nonce The nonce to verify
|
|
* @param string $action The nonce action
|
|
* @param bool $die_on_fail Whether to die on failure
|
|
* @return bool
|
|
*/
|
|
public static function verify_nonce( $nonce, $action, $die_on_fail = false ) {
|
|
$is_valid = wp_verify_nonce( $nonce, $action );
|
|
|
|
if ( ! $is_valid ) {
|
|
HVAC_Logger::warning( 'Nonce verification failed', 'Security', [
|
|
'action' => $action,
|
|
'user_id' => get_current_user_id(),
|
|
] );
|
|
|
|
if ( $die_on_fail ) {
|
|
wp_die( __( 'Security check failed. Please refresh the page and try again.', 'hvac-community-events' ) );
|
|
}
|
|
}
|
|
|
|
return $is_valid;
|
|
}
|
|
|
|
/**
|
|
* Check if current user has required capability
|
|
*
|
|
* @param string $capability The capability to check
|
|
* @param bool $die_on_fail Whether to die on failure
|
|
* @return bool
|
|
*/
|
|
public static function check_capability( $capability, $die_on_fail = false ) {
|
|
$has_cap = current_user_can( $capability );
|
|
|
|
if ( ! $has_cap ) {
|
|
HVAC_Logger::warning( 'Capability check failed', 'Security', [
|
|
'capability' => $capability,
|
|
'user_id' => get_current_user_id(),
|
|
] );
|
|
|
|
if ( $die_on_fail ) {
|
|
wp_die( __( 'You do not have permission to perform this action.', 'hvac-community-events' ) );
|
|
}
|
|
}
|
|
|
|
return $has_cap;
|
|
}
|
|
|
|
/**
|
|
* Check if user is logged in with optional redirect
|
|
*
|
|
* @param string $redirect_to URL to redirect if not logged in
|
|
* @return bool
|
|
*/
|
|
public static function require_login( $redirect_to = '' ) {
|
|
if ( ! is_user_logged_in() ) {
|
|
if ( ! empty( $redirect_to ) ) {
|
|
wp_safe_redirect( $redirect_to );
|
|
exit;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Sanitize and validate email
|
|
*
|
|
* @param string $email Email to validate
|
|
* @return string|false Sanitized email or false if invalid
|
|
*/
|
|
public static function sanitize_email( $email ) {
|
|
$email = sanitize_email( $email );
|
|
return is_email( $email ) ? $email : false;
|
|
}
|
|
|
|
/**
|
|
* Sanitize and validate URL
|
|
*
|
|
* @param string $url URL to validate
|
|
* @return string|false Sanitized URL or false if invalid
|
|
*/
|
|
public static function sanitize_url( $url ) {
|
|
$url = esc_url_raw( $url );
|
|
return filter_var( $url, FILTER_VALIDATE_URL ) ? $url : false;
|
|
}
|
|
|
|
/**
|
|
* Sanitize array of values
|
|
*
|
|
* @param array $array Array to sanitize
|
|
* @param string $type Type of sanitization (text|email|url|int)
|
|
* @return array
|
|
*/
|
|
public static function sanitize_array( $array, $type = 'text' ) {
|
|
if ( ! is_array( $array ) ) {
|
|
return [];
|
|
}
|
|
|
|
$sanitized = [];
|
|
foreach ( $array as $key => $value ) {
|
|
switch ( $type ) {
|
|
case 'email':
|
|
$clean = self::sanitize_email( $value );
|
|
if ( $clean ) {
|
|
$sanitized[ $key ] = $clean;
|
|
}
|
|
break;
|
|
case 'url':
|
|
$clean = self::sanitize_url( $value );
|
|
if ( $clean ) {
|
|
$sanitized[ $key ] = $clean;
|
|
}
|
|
break;
|
|
case 'int':
|
|
$sanitized[ $key ] = intval( $value );
|
|
break;
|
|
default:
|
|
$sanitized[ $key ] = sanitize_text_field( $value );
|
|
}
|
|
}
|
|
|
|
return $sanitized;
|
|
}
|
|
|
|
/**
|
|
* Escape output based on context
|
|
*
|
|
* @param mixed $value Value to escape
|
|
* @param string $context Context (html|attr|url|js)
|
|
* @return string
|
|
*/
|
|
public static function escape_output( $value, $context = 'html' ) {
|
|
switch ( $context ) {
|
|
case 'attr':
|
|
return esc_attr( $value );
|
|
case 'url':
|
|
return esc_url( $value );
|
|
case 'js':
|
|
return esc_js( $value );
|
|
case 'textarea':
|
|
return esc_textarea( $value );
|
|
default:
|
|
return esc_html( $value );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if request is AJAX
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_ajax_request() {
|
|
return defined( 'DOING_AJAX' ) && DOING_AJAX;
|
|
}
|
|
|
|
/**
|
|
* Get user IP address
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_user_ip() {
|
|
$ip = '';
|
|
|
|
if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
|
|
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
|
} elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
|
|
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
|
} elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
|
|
$ip = $_SERVER['REMOTE_ADDR'];
|
|
}
|
|
|
|
return sanitize_text_field( $ip );
|
|
}
|
|
|
|
/**
|
|
* Rate limiting check
|
|
*
|
|
* @param string $action Action to limit
|
|
* @param int $limit Number of attempts allowed
|
|
* @param int $window Time window in seconds
|
|
* @param string $identifier User identifier (defaults to IP)
|
|
* @return bool True if within limits, false if exceeded
|
|
*/
|
|
public static function check_rate_limit( $action, $limit = 5, $window = 300, $identifier = null ) {
|
|
if ( null === $identifier ) {
|
|
$identifier = self::get_user_ip();
|
|
}
|
|
|
|
$key = 'hvac_rate_limit_' . md5( $action . $identifier );
|
|
$attempts = get_transient( $key );
|
|
|
|
if ( false === $attempts ) {
|
|
set_transient( $key, 1, $window );
|
|
return true;
|
|
}
|
|
|
|
if ( $attempts >= $limit ) {
|
|
HVAC_Logger::warning( 'Rate limit exceeded', 'Security', [
|
|
'action' => $action,
|
|
'identifier' => $identifier,
|
|
'attempts' => $attempts,
|
|
] );
|
|
return false;
|
|
}
|
|
|
|
set_transient( $key, $attempts + 1, $window );
|
|
return true;
|
|
}
|
|
} |