Order Daemon implements an extensible security layer based on the Strategy and Composite design patterns. This system handles CSRF protection, capability checks, and audit logging for all sensitive operations.
Architecture
The system has five pieces:
- Guard Interface – contract all security checks implement
- Concrete Guards – individual checks (nonce, capability)
- CompositeGuard – chains multiple guards together
- GuardChecker – centralized execution with automatic audit logging
- GuardFactory – convenience factory for common patterns
classDiagram
Guard <|-- NonceGuard
Guard <|-- CapabilityGuard
Guard <|-- CompositeGuard
CompositeGuard o-- Guard
GuardChecker --> Guard : verifies
GuardFactory --> Guard : createsCore interfaces and classes
Guard interface
interface Guard {
public function verify(): void;
}All guards implement this. On failure they throw SecurityException.
Concrete guards
NonceGuard – CSRF protection using wp_verify_nonce().
CapabilityGuard – Role-based access via current_user_can(). Supports both general and object-specific capabilities.
CompositeGuard – All contained guards must pass. Fails on the first failure.
GuardChecker
Centralized execution with automatic audit logging of every check (success and failure).
$guard_checker = new GuardChecker();
$guard_checker->check($guard, ['context' => 'admin_action']);Logged data includes: guard type, user context (ID, roles, IP), request context (method, user agent, referer), execution time, error details.
GuardFactory
// Form submission
$guard = GuardFactory::createFormGuards(
$_POST['_wpnonce'],
'my_action',
'manage_woocommerce'
);
// AJAX
$guard = GuardFactory::createAjaxGuards(
$_POST['_wpnonce'],
'my_ajax_action',
'edit_shop_orders'
);
// REST API
$guard = GuardFactory::createRestGuards(
$request->get_header('X-WP-Nonce'),
'wp_rest',
'manage_options'
);Usage examples
Form submission
try {
$guard = GuardFactory::createFormGuards(
$_POST['_wpnonce'],
'my_plugin_action',
'manage_woocommerce'
);
$guard_checker = OrderDaemonCompletionManagerPlugin::get_guard_checker();
$guard_checker->check($guard, [
'operation' => 'rule_creation',
'rule_name' => sanitize_text_field($_POST['rule_name'])
]);
process_rule_creation($_POST);
} catch (SecurityException $e) {
wp_die('Security verification failed: ' . esc_html($e->getMessage()));
}AJAX handler
add_action('wp_ajax_my_ajax_action', function() {
try {
$guard = GuardFactory::createAjaxGuards(
$_POST['_wpnonce'],
'my_ajax_action',
'edit_shop_orders'
);
$guard_checker = OrderDaemonCompletionManagerPlugin::get_guard_checker();
$guard_checker->check($guard, ['operation' => 'order_update']);
wp_send_json_success(process_order_update($_POST));
} catch (SecurityException $e) {
wp_send_json_error(['message' => $e->getMessage()], 403);
}
});REST endpoint
register_rest_route('my-plugin/v1', '/secure-endpoint', [
'methods' => 'POST',
'permission_callback' => '__return_true', // handled by guard
'callback' => function($request) {
try {
$guard = GuardFactory::createRestGuards(
$request->get_header('X-WP-Nonce'),
'wp_rest',
'manage_woocommerce'
);
$guard_checker = OrderDaemonCompletionManagerPlugin::get_guard_checker();
$guard_checker->check($guard, ['endpoint' => 'secure_endpoint']);
return new WP_REST_Response(process_api_request($request));
} catch (SecurityException $e) {
return new WP_Error('security_failure', $e->getMessage(), ['status' => 403]);
}
},
]);Custom guard
class CustomGuard implements Guard {
public function verify(): void {
if (!custom_security_check()) {
throw new SecurityException('Custom security check failed', [
'check_type' => 'custom_validation',
]);
}
}
}
$guard_checker->check(new CustomGuard(), ['context' => 'custom_operation']);Composite guard
$guard = new CompositeGuard(
new NonceGuard($_POST['_wpnonce'], 'custom_action'),
new CapabilityGuard('edit_shop_orders', 'order_management'),
new CustomGuard(),
);
$guard_checker->check($guard, ['operation' => 'complex_operation']);Capability reference
| Operation | Capability |
|---|---|
| Most admin operations | manage_woocommerce |
| Order-related actions | edit_shop_orders |
| Plugin settings | manage_options |
Troubleshooting
Nonce verification fails:
- Ensure the nonce field is output in forms:
wp_nonce_field('my_action') - Verify action strings match between creation and verification
- Check AJAX requests include the nonce in POST data
Capability check fails:
- Confirm the user has the required WordPress role
- Check for capability filters modifying access
- Verify object-specific capabilities use correct object IDs
GuardChecker instance unavailable:
- Ensure the plugin is fully initialized before calling
- Check for fatal errors during plugin bootstrap
Viewing security events: All guard checks are logged with security_check_passed or security_check_failed event types. Filter by these in the Insight Dashboard to audit security activity.