1 Commits
Author SHA1 Message Date
superadmin f0060f3eb8 Actualizar local desde main 2026-10-02 16:55:46 +00:00
5 changed files with 21 additions and 94 deletions
+5 -21
View File
@@ -34,7 +34,6 @@ class AcaiAPI
// ── Cache flags (mirror CocoDB interface) ───────────────────────── // ── Cache flags (mirror CocoDB interface) ─────────────────────────
public static $redis = null; public static $redis = null;
public static $redis_expireTime = 0; public static $redis_expireTime = 0;
public static $redis_no_disponible = false;
public static $force_load_cache = false; public static $force_load_cache = false;
public static $force_redis = false; public static $force_redis = false;
public static $force_redis_module = false; // consumed by external cache layer public static $force_redis_module = false; // consumed by external cache layer
@@ -648,29 +647,14 @@ class AcaiAPI
/** Connect to Redis (idempotent). */ /** Connect to Redis (idempotent). */
static function initCache() static function initCache()
{ {
// Sin Redis (hosting propio sin el servicio o sin la extensión, o el
// servicio caído) la web sigue SIN caché en vez de morir con un fatal:
// cacheGet/cacheSet ya no hacen nada si no hay conexión. Se marca para
// no reintentar en cada consulta de la misma petición.
if (self::$redis_no_disponible) return;
if (!class_exists('Redis')) {
self::$redis_no_disponible = true;
self::$redis = null;
return;
}
$redisHost = getenv('REDIS_HOST') ?: '127.0.0.1'; $redisHost = getenv('REDIS_HOST') ?: '127.0.0.1';
$redisPort = (int)(getenv('REDIS_PORT') ?: 6379); $redisPort = (int)(getenv('REDIS_PORT') ?: 6379);
try { if (!self::$redis) {
if (!self::$redis) self::$redis = new Redis(); self::$redis = new Redis();
if (!self::$redis->isConnected() && !self::$redis->connect($redisHost, $redisPort)) { self::$redis->connect($redisHost, $redisPort);
throw new RuntimeException("no se pudo conectar a $redisHost:$redisPort"); } elseif (!self::$redis->isConnected()) {
} self::$redis->connect($redisHost, $redisPort);
} catch (Throwable $e) {
self::$redis_no_disponible = true;
self::$redis = null;
error_log('[cache] Redis no disponible, se sigue sin caché: ' . $e->getMessage());
} }
} }
+5 -21
View File
@@ -14,7 +14,6 @@ class CocoDB
public static $trackData = []; public static $trackData = [];
public static $redis = null; public static $redis = null;
public static $redis_expireTime = 0; public static $redis_expireTime = 0;
public static $redis_no_disponible = false;
public static $force_load_cache = false; public static $force_load_cache = false;
public static $force_redis = false; public static $force_redis = false;
public static $force_redis_module = false; public static $force_redis_module = false;
@@ -1177,29 +1176,14 @@ class CocoDB
*/ */
static function initCache() static function initCache()
{ {
// Sin Redis (hosting propio sin el servicio o sin la extensión, o el
// servicio caído) la web sigue SIN caché en vez de morir con un fatal:
// cacheGet/cacheSet ya no hacen nada si no hay conexión. Se marca para
// no reintentar en cada consulta de la misma petición.
if (self::$redis_no_disponible) return;
if (!class_exists('Redis')) {
self::$redis_no_disponible = true;
self::$redis = null;
return;
}
$redisHost = getenv('REDIS_HOST') ?: '127.0.0.1'; $redisHost = getenv('REDIS_HOST') ?: '127.0.0.1';
$redisPort = (int)(getenv('REDIS_PORT') ?: 6379); $redisPort = (int)(getenv('REDIS_PORT') ?: 6379);
try { if (!self::$redis) {
if (!self::$redis) self::$redis = new Redis(); self::$redis = new Redis();
if (!self::$redis->isConnected() && !self::$redis->connect($redisHost, $redisPort)) { self::$redis->connect($redisHost, $redisPort);
throw new RuntimeException("no se pudo conectar a $redisHost:$redisPort"); } else if (!self::$redis->isConnected()) {
} self::$redis->connect($redisHost, $redisPort);
} catch (Throwable $e) {
self::$redis_no_disponible = true;
self::$redis = null;
error_log('[cache] Redis no disponible, se sigue sin caché: ' . $e->getMessage());
} }
} }
+8 -25
View File
@@ -406,13 +406,10 @@ function _renameFile() {
* (install/uninstall/enable/disable) quedaban inservibles ahi con un * (install/uninstall/enable/disable) quedaban inservibles ahi con un
* "Token no valido" que no tenia nada que ver con el token. * "Token no valido" que no tenia nada que ver con el token.
* *
* No es un bypass: se compara un secreto recibido en el cuerpo con el que la * No es un bypass: se compara el par token+tokenHash recibido con el que la
* propia web guarda en su .acai. Sin .acai (produccion), con mode=production, * propia web guarda en su .acai, que es exactamente el que Forge envia. Sin
* o sin coincidencia exacta, no autoriza nada. Dos formas de coincidir: * .acai (produccion), con mode=production, o sin coincidencia exacta, no
* - secretoLocal (cuerpo) == secreto_local (.acai): el secreto de la copia, * autoriza nada.
* que no es una credencial de ninguna persona. Es la via buena.
* - token+tokenHash (cuerpo) == token+tokenHash (.acai): la de siempre.
* Las cadenas vacias nunca coinciden. Los secretos no se registran nunca.
*/ */
function _lifecycleTokenLocalValido($datosAuth) { function _lifecycleTokenLocalValido($datosAuth) {
$acaiPath = __DIR__ . "/../../../.acai"; $acaiPath = __DIR__ . "/../../../.acai";
@@ -423,24 +420,10 @@ function _lifecycleTokenLocalValido($datosAuth) {
if (!is_array($acai) || @$acai["mode"] === "production") { if (!is_array($acai) || @$acai["mode"] === "production") {
return false; return false;
} }
if (!is_array($datosAuth)) { $token = (string) @$datosAuth["token"];
return false; $hash = (string) @$datosAuth["tokenHash"];
} $tokenLocal = (string) @$acai["token"];
$hashLocal = (string) @$acai["tokenHash"];
// Via buena: el secreto propio de la copia local.
$secretoLocal = @$acai["secreto_local"];
$secreto = @$datosAuth["secretoLocal"];
if (is_string($secretoLocal) && $secretoLocal !== ""
&& is_scalar($secreto) && (string) $secreto !== ""
&& hash_equals($secretoLocal, (string) $secreto)) {
return true;
}
// transitorio: quitar cuando el .acai ya no lleve token (fase 1d)
$token = is_scalar(@$datosAuth["token"]) ? (string) $datosAuth["token"] : "";
$hash = is_scalar(@$datosAuth["tokenHash"]) ? (string) $datosAuth["tokenHash"] : "";
$tokenLocal = is_scalar(@$acai["token"]) ? (string) $acai["token"] : "";
$hashLocal = is_scalar(@$acai["tokenHash"]) ? (string) $acai["tokenHash"] : "";
if ($token === "" || $hash === "" || $tokenLocal === "" || $hashLocal === "") { if ($token === "" || $hash === "" || $tokenLocal === "" || $hashLocal === "") {
return false; return false;
} }
+1 -9
View File
@@ -20,15 +20,7 @@ if (file_exists($filePath)) {
# <?=strtoupper($configuracionRecord["tienda_nombre_empresa"]);?> # <?=strtoupper($configuracionRecord["tienda_nombre_empresa"]);?>
User-agent: * User-agent: *
<? <? if (strpos($_SERVER["HTTP_HOST"], "plandeweb.com")) {?>
// Cerrada mientras no este publicada: la regla es `acaiRobotsBloqueados` del
// plugin builder_saas (la misma de header.php y de la puerta de las webs
// Astro). Un robots.txt propio de la web manda sobre esto (arriba). Sin el
// plugin, como siempre: solo se cierran los dominios de pruebas.
$robotsBloqueados = strpos($_SERVER["HTTP_HOST"], "plandeweb.com")
|| (function_exists("acaiRobotsBloqueados")
&& acaiRobotsBloqueados(is_file(dirname(__DIR__) . "/.acai"), @$configuracionRecord['pagina_publicada']));
if ($robotsBloqueados) {?>
Disallow: / Disallow: /
<? }?> <? }?>
<? if (@$configuracionRecord['pagina_publicada']) {?> <? if (@$configuracionRecord['pagina_publicada']) {?>
+2 -18
View File
@@ -78,32 +78,16 @@ $config_header = array(
// prod + publicada -> se ve // prod + publicada -> se ve
// prod + sin publicar + ?pruebas -> se ve, con el cartel rojo // prod + sin publicar + ?pruebas -> se ve, con el cartel rojo
// prod + sin publicar + visitante -> mantenimiento // prod + sin publicar + visitante -> mantenimiento
//
// La tabla de arriba es UNA regla para todas las webs (PHP y Astro) y para el
// robots.txt: `acaiVisibilidadWeb` del plugin builder_saas (ws_respond.php),
// que se reparte entero a todas las webs. Se llama con function_exists por la
// misma razon que la señal va en linea: si una web no trae el plugin, se
// queda con la RESERVA de abajo, que es la regla de siempre (y el cartel con
// 200, sin las cabeceras 503 de `acaiCabecerasMantenimiento`).
$esEntornoLocal = is_file(dirname(__FILE__) . "/.acai"); $esEntornoLocal = is_file(dirname(__FILE__) . "/.acai");
if (function_exists("acaiVisibilidadWeb")) { if ($esEntornoLocal || @$configuracionRecord["pagina_publicada"] || isset($_SESSION["pruebas"])) {
$visibilidadWeb = acaiVisibilidadWeb($esEntornoLocal, @$configuracionRecord["pagina_publicada"], isset($_SESSION["pruebas"]));
} else {
// RESERVA (sin el plugin): la misma tabla, en linea.
$visibilidadWeb = ($esEntornoLocal || @$configuracionRecord["pagina_publicada"]) ? "visible"
: (isset($_SESSION["pruebas"]) ? "pruebas" : "mantenimiento");
}
if ($visibilidadWeb !== "mantenimiento") {
if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header); if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header);
if ($visibilidadWeb === "pruebas") { if (!$esEntornoLocal && isset($_SESSION["pruebas"]) && @$configuracionRecord["pagina_publicada"] == 0) {
?> ?>
<div style="position:absolute;top:0px;width:150px;background-color:red;color:#fff;font-size:12px;padding:0 10px;z-index:99999999;transform:translateZ(1000px);">SITIO EN PRUEBAS</div> <div style="position:absolute;top:0px;width:150px;background-color:red;color:#fff;font-size:12px;padding:0 10px;z-index:99999999;transform:translateZ(1000px);">SITIO EN PRUEBAS</div>
<? <?
} }
} else { } else {
if (function_exists("acaiCabecerasMantenimiento")) acaiCabecerasMantenimiento();
die(tpl('mantenimiento',$config_header)); die(tpl('mantenimiento',$config_header));
} }
?> ?>