Tofu/app/tools/webdav/describeWebdavFailure.js

85 lines
3.2 KiB
JavaScript

// Turns a WebDAV failure into a diagnosis a user can act on.
// `url` is optional: when the caller knows it, a plain misconfiguration (an address
// that is not https) is told apart from a request the browser refused to send at all.
// A rejected fetch carries no detail by design — the browser hides whether the server
// answered without CORS headers or never answered — so that case is named for what it
// almost always is rather than left as a vague network error.
export function describeWebdavFailure({ error, response, method = '', url = '' }) {
const status = Number(response?.status ?? 0)
if (status >= 400) return describeHttpStatus(status, response.statusText ?? '', method)
if (error && error.name === 'SyntaxError') {
return {
kind: 'parse',
message: "Le fichier a été lu, mais son contenu n'est pas du JSON valide.",
hint: 'Il a peut-être été modifié à la main ou enregistré à moitié. Le supprimer repart sur une base saine.',
}
}
if (url !== '' && !url.startsWith('https://')) {
return {
kind: 'network',
message: "L'adresse du serveur est inutilisable : elle doit commencer par https://.",
hint: 'Saisir une adresse complète, par exemple https://cloud.exemple.fr.',
}
}
if (error) {
return {
kind: 'cors',
message: "Le navigateur a bloqué la requête avant d'obtenir une réponse. C'est presque toujours CORS : le Nextcloud ne renvoie pas les en-têtes autorisant cette origine.",
hint: 'Voir docs/webdav-nextcloud.md : le serveur doit autoriser cette origine et les méthodes WebDAV.',
}
}
return {
kind: 'network',
message: "Le serveur n'a pas pu être joint : aucune réponse n'est arrivée.",
hint: "Vérifier l'adresse du serveur et la connexion réseau, puis réessayer.",
}
}
function describeHttpStatus(status, statusText, method) {
switch (status) {
case 401:
return {
kind: 'auth',
message: "Identifiants refusés. Vérifier l'utilisateur et le mot de passe d'application.",
hint: "Dans Nextcloud : Paramètres personnels, Sécurité, Créer un mot de passe d'application.",
}
case 403:
return {
kind: 'forbidden',
message: "Accès refusé : ce compte n'a pas les droits nécessaires sur cette ressource.",
hint: 'Vérifier les droits du dossier, et que le compte peut y écrire.',
}
case 404:
return {
kind: 'notFound',
message: "La ressource demandée n'existe pas sur le serveur.",
hint: 'Vérifier le nom du dossier distant.',
}
case 409:
return {
kind: 'conflict',
message: "Le dossier parent n'existe pas.",
hint: "Créer le dossier avant d'y écrire un fichier.",
}
default:
return {
kind: 'http',
message: `${describeRequest(method)} : le serveur a répondu ${describeStatus(status, statusText)}.`,
hint: 'Regarder les journaux du serveur Nextcloud pour connaître la cause exacte.',
}
}
}
function describeRequest(method) {
if (method === '') return 'La requête a échoué'
return `La requête ${method} a échoué`
}
function describeStatus(status, statusText) {
if (statusText === '') return String(status)
return `${status} ${statusText}`
}