discovery-media-player 0.1.75 → 0.1.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server/appelant.js +59 -0
- package/server/handler.js +13 -864
- package/server/routes-agent.js +148 -0
- package/server/routes-direct.js +232 -0
- package/server/routes-liens.js +451 -0
- package/server/routes-visiteur.js +63 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "discovery-media-player",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.76",
|
|
4
4
|
"description": "Self-hosted document viewer: per-recipient tracked links, reading analytics, live presentation. The core knows nothing about the application hosting it — everything it borrows arrives through an injected context.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pdf-viewer",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// EXTRAIT DE handler.js (refactor lot 3 — routes, 19/08/2026) — blocs déplacés À L'IDENTIQUE.
|
|
2
|
+
// Reste à PLAT dans server/ (les gardes de forge ciblent server/*.js).
|
|
3
|
+
|
|
4
|
+
let PLAYER = null;
|
|
5
|
+
const init = (ctx) => { PLAYER = ctx; };
|
|
6
|
+
|
|
7
|
+
// ⚠️ `X-Forwarded-For` EST UN EN-TÊTE, DONC UNE AFFIRMATION DU CLIENT.
|
|
8
|
+
//
|
|
9
|
+
// Onze endroits en prenaient la première valeur pour identifier l'appelant, et toutes les limites
|
|
10
|
+
// de débit s'appuyaient dessus. Un client qui atteint directement le serveur — c'est le cas du
|
|
11
|
+
// serveur autonome, et de toute instance dont le proxy ne réécrit pas cet en-tête — pouvait donc
|
|
12
|
+
// en changer à chaque requête et n'être jamais limité. La limite existait, elle ne limitait rien.
|
|
13
|
+
//
|
|
14
|
+
// Le caractère « par processus » des compteurs était documenté ; la confiance dans un en-tête non
|
|
15
|
+
// authentifié ne l'était pas. C'est la différence entre une limite approximative et une limite
|
|
16
|
+
// décorative.
|
|
17
|
+
//
|
|
18
|
+
// La décision revient à l'hôte, parce que lui seul sait s'il y a un proxy devant lui :
|
|
19
|
+
// `identity.clientIp(req)` s'il la fournit, sinon l'adresse de la socket — jamais l'en-tête. Un
|
|
20
|
+
// hôte derrière un proxy déclare sa politique dans son câblage ; un hôte sans proxy n'a rien à
|
|
21
|
+
// faire, et il est protégé par défaut.
|
|
22
|
+
function adresseAppelant(req) {
|
|
23
|
+
try {
|
|
24
|
+
if (PLAYER.identity && typeof PLAYER.identity.clientIp === "function") {
|
|
25
|
+
const v = PLAYER.identity.clientIp(req);
|
|
26
|
+
if (v) return String(v).slice(0, 60);
|
|
27
|
+
}
|
|
28
|
+
} catch { /* une IP indisponible ne doit pas empêcher de lire un document */ }
|
|
29
|
+
return String((req.socket && req.socket.remoteAddress) || "").slice(0, 60);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** La clé d'un membre : son adresse, normalisée — la recherche de ligne est exacte. */
|
|
33
|
+
function lcMembre(email) {
|
|
34
|
+
return String(email || "").trim().toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function cleAnonyme(brut) {
|
|
38
|
+
const v = String(brut == null ? "" : brut).trim().slice(0, 120);
|
|
39
|
+
return /^anon-[A-Za-z0-9_-]{4,}$/.test(v) ? v : "anon-inconnu";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function profilDuJeton(req) {
|
|
43
|
+
try {
|
|
44
|
+
const u = await PLAYER.identity.verifyToken((req.headers && req.headers.authorization) || "");
|
|
45
|
+
if (!u || !u.email) return null;
|
|
46
|
+
if (typeof PLAYER.identity.profileOf === "function") {
|
|
47
|
+
const p = PLAYER.identity.profileOf(u) || {};
|
|
48
|
+
return { email: String(p.email || u.email), name: String(p.name || ""), avatar: String(p.avatar || "") };
|
|
49
|
+
}
|
|
50
|
+
const meta = (u && u.user_metadata) || {};
|
|
51
|
+
return {
|
|
52
|
+
email: String(u.email),
|
|
53
|
+
name: String(u.name || meta.name || meta.full_name || ""),
|
|
54
|
+
avatar: String(u.avatar || meta.avatarUrl || meta.avatar_url || ""),
|
|
55
|
+
};
|
|
56
|
+
} catch { return null; }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { init, adresseAppelant, lcMembre, cleAnonyme, profilDuJeton };
|