Derrière un proxy d'authentification, FanKarr demandait une seconde
connexion. Avec PROXY_AUTH_HEADER, la session est ouverte à partir du nom
d'utilisateur transmis par le proxy.
- server/lib/proxy-auth.ts : lecture de l'en-tête, uniquement pour les
connexions venant de PROXY_AUTH_TRUSTED_PROXIES (adresse du socket, pas
X-Forwarded-For) ; fonction désactivée si cette liste est vide
- compte rapproché par nom (sans casse) ; création d'un compte utilisateur
sans mot de passe avec PROXY_AUTH_AUTO_CREATE ; premier compte toujours
créé par l'assistant
- server/auth.ts : middleware proxyAuth avant les routes, qui ouvre ou
remplace la session ; /api/auth/status expose proxyAuth et logoutUrl
- déconnexion : redirection vers PROXY_AUTH_LOGOUT_URL si défini
- profil et gestion des utilisateurs : libellés pour les comptes sans mot
de passe qui ne viennent pas de Jellyfin
- tests vitest du module ; fichiers de test exclus de la compilation serveur
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FanKarr supposait jusqu'ici être servi à la racine du domaine. La variable
d'environnement BASE_URL (ex. /fankarr) permet de l'héberger dans un
sous-dossier, sans reconstruire l'image : le préfixe est appliqué au démarrage.
- server/config.ts : BASE_URL normalisée et validée ('' = racine)
- server/index.ts : toutes les routes montées sous BASE_URL via un Router,
index.html servi avec <base href> et window.__BASE_URL__, redirection de /
- server/auth.ts : cookie de session limité au chemin de base
- src/base-url.ts : préfixage des appels fetch('/api/…') en un point unique,
helpers withBase / absoluteUrl
- src/router : createWebHistory(BASE_URL)
- vite.config.ts : base './' (assets relatifs, résolus par <base href>)
Comportement inchangé lorsque BASE_URL n'est pas défini.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(jellyfin): vérifier que le jeton Jellyfin appartient à l'utilisateur annoncé
L'échange du plugin (POST /api/v1/auth/jellyfin) validait le jeton avec
GET /Users/{jellyfinUserId}, que Jellyfin accepte avec le jeton de
n'importe quel utilisateur. Un utilisateur Jellyfin pouvait ainsi obtenir
le jeton d'API FanKarr d'un autre compte, administrateur compris.
Le jeton est maintenant vérifié avec GET /Users/Me, et son propriétaire
doit correspondre à jellyfinUserId.
* feat(auth): connexion avec un compte Jellyfin
Les utilisateurs Jellyfin se connectent à l'interface web avec leurs
identifiants Jellyfin, vérifiés par Jellyfin (POST /Users/AuthenticateByName).
- Import des utilisateurs Jellyfin au choix depuis Paramètres › Jellyfin et
API ; l'import automatique horaire devient un réglage (activé par défaut).
Un compte FanKarr du même nom est lié au lieu d'être recréé.
- Seuls les comptes importés peuvent se connecter avec Jellyfin, sauf si
« Autoriser les comptes pas encore importés » est activé (désactivé par
défaut) : le compte invité est alors créé à la première connexion, depuis
l'interface web ou le plugin.
- Interrupteur « Connexion à FanKarr avec un compte Jellyfin » (activé par
défaut).
- L'identifiant du serveur Jellyfin est enregistré et vérifié à chaque
connexion ; la session Jellyfin ouverte pour la vérification est fermée
aussitôt.
- Connexion limitée à 5 échecs en 15 minutes par nom d'utilisateur et adresse.
- Les comptes importés n'ont pas de mot de passe FanKarr : la page Profil
l'indique, l'administrateur peut toujours en définir un.
- synology-ds: ajout cache _hashToSynoId (hash BT → dbid_X) peuplé dans
list(), utilisé dans remove() et getFiles() pour retrouver la tâche
même quand detail.hash et detail.uri sont vides dans la réponse DSM
- index: contrôle du retour de dispatchRemove et log d'erreur explicite
si la suppression échoue, au lieu de toujours logger "supprimé"
- Supprime le driver AllDebrid et son enregistrement
- Synology : extrait le vrai hash BT depuis additional.detail.hash
- Synology : ajoute les statuts finishing/extracting → seeding
- Synology : fix remove() pour matcher par hash BT ou ID Synology
- Synology : add() passe en POST form-encoded
fix(settings): la clé api n'apparait que dans un menu pour les admin
feat(client): ajout de alldebrid dans le tableau de comparatif
fix(settings): bug ou les parametre se sauvegarder en rentrant sur lla page avancé
feat(users): gestion des comptes et système d'invitations avec page d'administration
feat(requests): demandes de séries avec fusion des saisons, vue admin et widget dashboard
feat(jellyfin): synchronisation des comptes, SSO token exchange et API publique v1
fix(log): changement pour une notification plus explicit lors du test client
fix(import): supprime les entrees organiser quand on supprime un fichier
fix(start): url cliquable au demarrage dans le terminal
feat(organize): vérification de complétion par fichier avant d'importer
- Récupération de la progression par fichier (index + name + progress 0–1) dans qBittorrent, Transmission et rTorrent
- Ajout de getFiles() sur le driver qBittorrent et interface TorrentClientDriver
- Le worker filtre les fichiers incomplets (< 100%) avant move/copy/hardlink
fix(organize): retry EBUSY sur unlink — 5 tentatives × 500 ms (Windows)
fix(organize): suppression des entrées orphelines lors de la migration d'IDs
- Quand l'ancien ID est orphelin et le nouvel ID déjà présent, l'orphelin est supprimé au lieu d'être conservé
fix(qbittorrent): suppression de paused/stopped à l'ajout du torrent
- Le torrent est ajouté normalement pour permettre la récupération immédiate des métadonnées
- Premier poll de qbApplyFilePriority réduit à 100 ms
feat(serie): badges épisodes et chapitres extraits du synopsis
- Regex sur ep.plot pour extraire les plages "Ép. 628–634" et "Ch. 700–706"
- La phrase de couverture est retirée du synopsis affiché
- Badges violet (épisodes) et teal (chapitres) à côté des badges MULTI/VOSTFR
feat(serie): lien wiki dans le header de la série si serie.wiki est défini
fix(serie): header mobile — items-start + aspect-[2/3] sur le poster
oauth/start — X-Plex-Client-Identifier ajouté dans le body du POST (Plex l'exige dans le body pour la création du pin, pas juste dans les headers). forwardUrl pointe maintenant vers https://plex.tv au lieu d'être vide — sans ça Plex ne valide pas le pin côté serveur.
oauth/poll — X-Plex-Client-Identifier=fankarr passé en query param sur l'URL du GET. Plex exige que le même clientID que celui utilisé lors de la création soit présent pour récupérer le token.
feat: ajout d'un bouton supprimé l'importation dans le menu d'importation d'une serie
feat: ajout de badge quand le fichier est introuvable
feat: suppression des series supprimé
feat: bouton tous télécharger sur les saisons et series
fix: unlink before move
fix: l'organiseur prend les fichiers renommer maintenant
feat: ajout d'information dans le fichier d'organisation pour l'organisation manuel plus tard
fix: ajout d'une verif lors de l'écriture de la config sur les items dans body
fix: ne sauvegarde plus le mots de passe "fake" quand on edit un client
feat: ajout du driver rtorrent
fix: empeche un login failed de se repeter et de se faire bloquer par les clients
feat: ajout de synology downloader comme client
fix: augmentation du header size 8kb -> 32kb
feat: Ajout des mapping sur les clients
feat: auto update des fichiers nfo
Nouveau helper updateClient et un endpoint PUT /api/torrent-clients/:uuid qui enregistre les modifications, journalise les mises à jour et renvoie le client.
Mise à jour de l'UI des paramètres pour ajouter un bouton "Modifier" et réutiliser la modale d'ajout de client pour les éditions (afin d'assurer le suivi de l'uuid ), bascule méthode PUT pour les requêtes de mise à jour, et actualisation de la liste des clients ainsi que des notifications en cas de modification réussie.