Files
AutoBooking/autobooking-nav-guard.php

147 lines
5.7 KiB
PHP

<?php
/**
* Plugin Name: AutoBooking Nav Guard
* Version: 1.1.0
* Description: Protege páginas por token de navegación. Redirige al login/home si no hay token válido.
*/
defined('ABSPATH') || exit;
/* ── Páginas protegidas: destino => URL ────────────────────────────── */
define('AB_NAV_PAGES', [
'driver' => '/driver-dashboard-2/',
'passenger' => '/customer-dashboard/',
'corporate' => '/corporate-dashboard/',
]);
/* ── Session ───────────────────────────────────────────────────────── */
add_action('init', function () {
if (!session_id() && !headers_sent()) session_start();
}, 1);
/* ── Roles permitidos por destino ───────────────────────────────────── */
function ab_nav_allowed_roles() {
return [
'driver' => ['driver', 'driver_pending'],
'passenger' => ['subscriber', 'customer'],
'corporate' => ['corporate_admin'],
];
}
/* ── Protección via template_redirect (antes de cualquier output) ──── */
add_action('template_redirect', function () {
global $post;
if (!$post) return;
$dest = get_post_meta($post->ID, '_ab_nav_page', true);
if (!$dest) return;
if (!is_user_logged_in()) {
wp_redirect(wp_login_url(get_permalink()));
exit;
}
$uid = get_current_user_id();
$user = wp_get_current_user();
$roles = (array) $user->roles;
// Admins y manage_autobooking: acceso siempre sin token
if (in_array('administrator', $roles) || user_can($uid, 'manage_autobooking')) {
return;
}
if (!session_id()) session_start();
$token = $_SESSION['ab_nav'][$dest] ?? null;
// Token válido → pasar
if ($token && $token['user'] === $uid && $token['exp'] >= time()) {
return;
}
// Sin token pero tiene el rol correcto → auto-token y pasar
$allowed = ab_nav_allowed_roles()[$dest] ?? [];
if (array_intersect($roles, $allowed)) {
$_SESSION['ab_nav'][$dest] = ['user' => $uid, 'exp' => time() + 300];
return;
}
// Rol incorrecto para esta página → home
wp_redirect(home_url('/'));
exit;
});
/* ── Auto-token en login → acceso directo al dashboard ─────────────── */
add_action('wp_login', function ($login, $user) {
if (!session_id()) session_start();
$roles = (array) $user->roles;
$exp = time() + 300;
$role_map = [
'driver' => 'driver',
'driver_pending' => 'driver',
'subscriber' => 'passenger',
'customer' => 'passenger',
'corporate_admin' => 'corporate',
];
foreach ($role_map as $role => $dest) {
if (in_array($role, $roles, true)) {
$_SESSION['ab_nav'][$dest] = ['user' => $user->ID, 'exp' => $exp];
}
}
if (user_can($user->ID, 'manage_autobooking') || in_array('administrator', $roles, true)) {
foreach (array_keys(AB_NAV_PAGES) as $dest) {
$_SESSION['ab_nav'][$dest] = ['user' => $user->ID, 'exp' => $exp];
}
}
}, 10, 2);
/* ── Redirect post-login al dashboard según rol ────────────────────── */
add_filter('login_redirect', function ($redirect, $request, $user) {
if (is_wp_error($user)) return $redirect;
$roles = (array) $user->roles;
if (in_array('driver', $roles) || in_array('driver_pending', $roles))
return home_url(AB_NAV_PAGES['driver']);
if (in_array('corporate_admin', $roles))
return home_url(AB_NAV_PAGES['corporate']);
if (in_array('subscriber', $roles) || in_array('customer', $roles))
return home_url(AB_NAV_PAGES['passenger']);
return $redirect;
}, 10, 3);
/* ── REST: generar token desde JS ───────────────────────────────────── */
add_action('rest_api_init', function () {
register_rest_route('ab/v1', '/nav-token', [
'methods' => 'POST',
'callback' => function (WP_REST_Request $req) {
$dest = sanitize_text_field($req->get_param('destination'));
if (!$dest) return new WP_Error('missing', 'destination required', ['status' => 400]);
if (!session_id()) session_start();
$_SESSION['ab_nav'][$dest] = ['user' => get_current_user_id(), 'exp' => time() + 300];
return rest_ensure_response(['ok' => true, 'destination' => $dest]);
},
'permission_callback' => fn() => is_user_logged_in(),
]);
});
/* ── JS helper global ───────────────────────────────────────────────── */
add_action('wp_footer', function () {
if (!is_user_logged_in()) return;
echo '<script>window.ab_nav_go=function(dest,url){'
. 'fetch(' . json_encode(rest_url('ab/v1/nav-token')) . ','
. '{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":' . json_encode(wp_create_nonce('wp_rest')) . '},'
. 'body:JSON.stringify({destination:dest})})'
. '.then(r=>r.json()).then(d=>{if(d.ok)window.location.href=url||"/"});'
. '};</script>';
});
/* ── Limpieza de tokens expirados ───────────────────────────────────── */
add_action('init', function () {
if (!session_id() || empty($_SESSION['ab_nav'])) return;
$now = time();
foreach ($_SESSION['ab_nav'] as $k => $d) {
if ($d['exp'] < $now) unset($_SESSION['ab_nav'][$k]);
}
}, 5);