Bài viết này trình bày cách Init Sentinel xây dựng widget dashboard: chỉ hiển thị thông tin cần thiết, có cache, có giới hạn quyền và dẫn đường rõ ràng tới trang theo dõi chi tiết.
Vai trò của widget trong kiến trúc Init Sentinel
Widget dashboard không phải là nơi phân tích dữ liệu sâu. Nó trả lời nhanh ba câu hỏi: có sự cố hay không, sự cố mới nhất là gì, và có cần đào sâu thêm không.
Vì vậy, widget phải nhanh, gọn và tuyệt đối không được gây chậm wp-admin.
Đăng ký widget và giới hạn quyền truy cập
Widget chỉ nên hiển thị cho người có đủ thẩm quyền. Init Sentinel giới hạn widget ở cấp quản trị cao để tránh lộ thông tin nhạy cảm.
// Register dashboard widget
add_action('wp_dashboard_setup', function () {
if ( ! current_user_can('manage_options') ) return;
wp_add_dashboard_widget(
'init_html_security_log_widget',
__('Recent Security Logs', 'init-html'),
'init_html_render_security_log_widget'
);
});
Việc kiểm tra quyền được thực hiện cả khi đăng ký widget lẫn khi render để tránh lộ dữ liệu qua hook ngoài ý muốn.
Render widget với kiểm tra table an toàn
Widget không giả định rằng bảng log luôn tồn tại. Điều này giúp tránh lỗi trong lần kích hoạt đầu tiên hoặc khi module bị tắt tạm thời.
// Render Sentinel widget
function init_html_render_security_log_widget() {
if ( ! current_user_can('manage_options') ) {
echo '<p>' . esc_html__('You do not have permission to view this widget.', 'init-html') . '</p>';
return;
}
global $wpdb;
$table = $wpdb->prefix . 'init_sentinel_security_log';
$has_table = $wpdb->get_var( $wpdb->prepare(
"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = %s",
$table
) );
if ( ! $has_table ) {
echo '<p>' . esc_html__('Security log table not found.', 'init-html') . '</p>';
return;
}
}
Cách làm này đảm bảo dashboard không bao giờ bị lỗi trắng chỉ vì thiếu bảng log.
Giới hạn số dòng và cache để giữ dashboard nhẹ
Widget chỉ hiển thị một số lượng log nhỏ, mặc định là 25, và cho phép điều chỉnh qua filter.
Dữ liệu được cache bằng wp_cache để tránh query lặp lại mỗi lần load dashboard.
$limit = (int) apply_filters('init_html_security_log_widget_limit', 25);
if ($limit < 5) $limit = 5; if ($limit > 100) $limit = 100;
$cache_group = 'init_html_sentinel';
$cache_key = 'widget_rows_' . $limit;
$ttl = (int) apply_filters('init_html_security_log_widget_ttl', 10 * MINUTE_IN_SECONDS);
$rows = wp_cache_get($cache_key, $cache_group);
if ( false === $rows ) {
$rows = $wpdb->get_results(
$wpdb->prepare(
"SELECT id, user_id, ip_address, endpoint, action, status_code, user_agent, created_at
FROM {$table}
ORDER BY created_at DESC
LIMIT %d",
$limit
)
);
wp_cache_set($cache_key, $rows, $cache_group, $ttl);
}
Cache ngắn hạn giúp widget phản hồi nhanh mà vẫn đủ “tươi” để phát hiện sự cố.
Hiển thị dữ liệu ưu tiên khả năng đọc
Widget tập trung vào các cột quan trọng: thời gian, endpoint, action, status code, user hoặc IP và user agent.
Status code được phân loại trực quan để quản trị viên nhận biết mức độ nghiêm trọng chỉ trong một cái nhìn.
Liên kết tới trang Security Logs đầy đủ
Widget không cố gắng hiển thị toàn bộ log. Khi có nhu cầu phân tích sâu, quản trị viên cần một trang riêng với khả năng lọc và tìm kiếm tốt hơn.
Vì vậy, widget luôn cung cấp link dẫn tới trang Security Logs đầy đủ.
$logs_url = admin_url('admin.php?page=init-html-security-logs');
echo '<a href="' . esc_url($logs_url) . '">' . esc_html__('View all logs', 'init-html') . '</a>';
Đây chính là điểm nối tự nhiên dẫn sang bài tiếp theo của Init Sentinel.
Kết luận
Widget dashboard của Init Sentinel là công cụ quan sát nhanh, không phải trung tâm phân tích. Nó được thiết kế để luôn nhẹ, an toàn và không làm gián đoạn trải nghiệm quản trị.
Ở bài tiếp theo, chúng ta sẽ xây dựng trang Security Logs đầy đủ, nơi dữ liệu được khai thác sâu và có thể theo dõi dài hạn.
Bình luận