Client (Python/JS):
- core/license.py: attivazione, validazione, deactivate (HTTP client + JWT decode)
- core/config.py: campi license_* + URL endpoint + costanti grace/revalidate
- api/bridge.py: get_init_data ritorna license status; activate_license/
deactivate_license/revalidate_license/open_purchase_page
- check_update riscritto: punta a musictools.djluza.com/api/latest con
Bearer token, URL di download firmato dal server solo se licensed
- webui: schermata di attivazione bloccante all'avvio; sezione Licenza
in Impostazioni con verifica/disattiva
Backend (server/):
- Cloudflare Worker + D1 + R2 (vedi server/README.md)
- Endpoints: /api/license/{activate,validate,deactivate}, /api/latest,
/api/webhook/lemonsqueezy, /api/health
- JWT HS256 con rotazione; max 3 attivazioni/licenza
- Generazione licenze via webhook Lemon Squeezy + email Resend
- Schema D1 in migrations/0001_init.sql
Memory: nuova musictools-commercial-launch.md, rimosso pending obsoleto
NON taggare finche backend non e' deployato (l'app e' bloccante)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
42 lines
1.0 KiB
TypeScript
42 lines
1.0 KiB
TypeScript
export function json(body: unknown, status = 200, headers: HeadersInit = {}): Response {
|
|
return new Response(JSON.stringify(body), {
|
|
status,
|
|
headers: {
|
|
"Content-Type": "application/json; charset=utf-8",
|
|
"Access-Control-Allow-Origin": "*",
|
|
...headers,
|
|
},
|
|
});
|
|
}
|
|
|
|
export function notFound(): Response {
|
|
return json({ error: "Not found" }, 404);
|
|
}
|
|
|
|
export function methodNotAllowed(): Response {
|
|
return json({ error: "Method not allowed" }, 405);
|
|
}
|
|
|
|
export function badRequest(msg: string): Response {
|
|
return json({ error: msg }, 400);
|
|
}
|
|
|
|
export function unauthorized(msg = "Unauthorized"): Response {
|
|
return json({ error: msg }, 401);
|
|
}
|
|
|
|
export async function readJson<T = any>(req: Request): Promise<T> {
|
|
try {
|
|
return (await req.json()) as T;
|
|
} catch {
|
|
throw new Response(JSON.stringify({ error: "Invalid JSON" }), {
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
}
|
|
}
|
|
|
|
export function now(): number {
|
|
return Math.floor(Date.now() / 1000);
|
|
}
|