Riscrivi backend per hosting Node/MariaDB/PM2 (no Cloudflare)
L'utente ha un hosting Virtualmin esistente (musictools.djluza.com)
con Apache + Node 20 + MariaDB + PM2. Tutta l'infrastruttura
Cloudflare (Workers/D1/R2/Pages) e' rimpiazzata con un backend
Express che gira sul server gia' presente, a costo zero.
Cambia:
- server/src/*.ts (Workers) -> server/src/*.js (Node ESM puro)
- D1 (sqlite) -> MariaDB 10.11 via mysql2/promise
- R2 (storage) -> filesystem locale ~/builds/ + signed URL HMAC
- wrangler.toml -> ecosystem.config.cjs (PM2)
- Aggiunto src/migrate.js: runner SQL idempotente
Endpoints invariati - l'app desktop non vede differenze:
- POST /api/license/{activate,validate,deactivate}
- GET /api/latest, /api/download
- POST /api/webhook/lemonsqueezy
- GET /api/health
README riscritto con istruzioni complete: creazione DB,
deploy via rsync/git, config Apache reverse proxy via
Virtualmin, gestione PM2, backup, workflow release.
Email rimane su Resend (deliverability) - free tier sufficiente.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
339dd4f3cc
commit
2d8290579b
22 files changed
+892
-790
No files matched your search
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* JWT HS256 minimale (niente dipendenze). Stessa logica del worker
|
||||
* Cloudflare precedente: stesso token formato, stessa firma, stessa
|
||||
* verifica. L'app desktop non distingue.
|
||||
*/
|
||||
|
||||
import crypto from "node:crypto";
|
||||
|
||||
function b64url(buf) {
|
||||
return Buffer.from(buf).toString("base64")
|
||||
.replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
|
||||
function b64urlDecode(s) {
|
||||
s = s.replace(/-/g, "+").replace(/_/g, "/");
|
||||
s += "=".repeat((4 - (s.length % 4)) % 4);
|
||||
return Buffer.from(s, "base64");
|
||||
}
|
||||
|
||||
function hmac(secret, data) {
|
||||
return crypto.createHmac("sha256", secret).update(data).digest();
|
||||
}
|
||||
|
||||
export function signJwt(claims, secret) {
|
||||
const head = b64url(JSON.stringify({ alg: "HS256", typ: "JWT" }));
|
||||
const body = b64url(JSON.stringify(claims));
|
||||
const sig = b64url(hmac(secret, `${head}.${body}`));
|
||||
return `${head}.${body}.${sig}`;
|
||||
}
|
||||
|
||||
export function verifyJwt(token, secret) {
|
||||
if (typeof token !== "string") return null;
|
||||
const parts = token.split(".");
|
||||
if (parts.length !== 3) return null;
|
||||
const [head, body, sig] = parts;
|
||||
const expected = b64url(hmac(secret, `${head}.${body}`));
|
||||
// confronto a tempo costante
|
||||
if (sig.length !== expected.length) return null;
|
||||
let diff = 0;
|
||||
for (let i = 0; i < sig.length; i++) diff |= sig.charCodeAt(i) ^ expected.charCodeAt(i);
|
||||
if (diff !== 0) return null;
|
||||
try {
|
||||
const claims = JSON.parse(b64urlDecode(body).toString("utf-8"));
|
||||
if (typeof claims.exp === "number" && claims.exp < Math.floor(Date.now() / 1000)) {
|
||||
return null;
|
||||
}
|
||||
return claims;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user