99 lines
3.9 KiB
JavaScript
99 lines
3.9 KiB
JavaScript
// End-to-end check of a WebDAV connection, run once when the user connects.
|
||
//
|
||
// It makes no request of its own: it drives the client and turns the round trip
|
||
// into a readable report. Every step is recorded, including the one that fails,
|
||
// so the user sees how far it went — "it does not work" is never an answer.
|
||
// The run stops at the first failure, because every later step depends on it.
|
||
|
||
const CHECK_FILE_NAME = 'tofu-check.json'
|
||
const PROBE_LABEL = 'Joindre le serveur'
|
||
const WRITE_LABEL = 'Écrire un fichier de test'
|
||
const READ_LABEL = 'Relire et vérifier le contenu'
|
||
const LIST_LABEL = 'Lister le dossier'
|
||
const CLEANUP_LABEL = 'Supprimer le fichier de test'
|
||
|
||
// The failure already carries a French sentence and, when it exists, a piece of
|
||
// advice: the report line shows both.
|
||
function formatFailureDetail({ message, hint }) {
|
||
return hint ? `${message} ${hint}` : message
|
||
}
|
||
|
||
// -> { steps: [{ id, label, ok, detail }], ok }
|
||
export async function runWebdavCheck(client, folder) {
|
||
const steps = []
|
||
const checkPath = `${folder}/${CHECK_FILE_NAME}`
|
||
// The timestamp is the witness: reading it back proves we read our own write.
|
||
const payload = { tool: 'tofu', purpose: 'connection check', checkedAt: new Date().toISOString() }
|
||
|
||
function recordSuccess(id, label, detail) {
|
||
steps.push({ id, label, ok: true, detail })
|
||
}
|
||
|
||
function recordFailure(id, label, failure) {
|
||
steps.push({ id, label, ok: false, detail: formatFailureDetail(failure) })
|
||
}
|
||
|
||
const probe = await client.listFolder('')
|
||
if (!probe.ok) {
|
||
recordFailure('probe', PROBE_LABEL, probe.failure)
|
||
return { steps, ok: false }
|
||
}
|
||
recordSuccess('probe', PROBE_LABEL, `Serveur joint, ${probe.entries.length} élément(s) à la racine du compte.`)
|
||
|
||
const folderLabel = `Créer le dossier ${folder}`
|
||
const folderResult = await client.ensureFolder(folder)
|
||
if (!folderResult.ok) {
|
||
recordFailure('folder', folderLabel, folderResult.failure)
|
||
return { steps, ok: false }
|
||
}
|
||
recordSuccess('folder', folderLabel, `Dossier « ${folder} » disponible (créé, ou déjà présent).`)
|
||
|
||
const write = await client.writeJson(checkPath, payload)
|
||
if (!write.ok) {
|
||
recordFailure('write', WRITE_LABEL, write.failure)
|
||
return { steps, ok: false }
|
||
}
|
||
recordSuccess('write', WRITE_LABEL, `Fichier « ${checkPath} » écrit.`)
|
||
|
||
const read = await client.readJson(checkPath)
|
||
if (!read.ok) {
|
||
recordFailure('read', READ_LABEL, read.failure)
|
||
return { steps, ok: false }
|
||
}
|
||
if (read.data?.checkedAt !== payload.checkedAt) {
|
||
recordFailure('read', READ_LABEL, {
|
||
message: 'Le fichier relu ne contient pas ce qui vient d’être écrit.',
|
||
hint: 'Un cache, un proxy ou un autre outil écrit peut-être au même endroit.'
|
||
})
|
||
return { steps, ok: false }
|
||
}
|
||
recordSuccess('read', READ_LABEL, 'Contenu relu, identique à ce qui venait d’être écrit.')
|
||
|
||
const list = await client.listFolder(folder)
|
||
if (!list.ok) {
|
||
recordFailure('list', LIST_LABEL, list.failure)
|
||
return { steps, ok: false }
|
||
}
|
||
if (!list.entries.some((entry) => entry.name === CHECK_FILE_NAME)) {
|
||
recordFailure('list', LIST_LABEL, {
|
||
message: `Le dossier répond, mais « ${CHECK_FILE_NAME} » n’y figure pas.`,
|
||
hint: 'Le serveur renvoie peut-être une liste mise en cache.'
|
||
})
|
||
return { steps, ok: false }
|
||
}
|
||
recordSuccess('list', LIST_LABEL, `Dossier listé, ${list.entries.length} entrée(s), dont le fichier de test.`)
|
||
|
||
// The round trip is already proven at this point: a failed cleanup leaves a
|
||
// harmless file behind, it does not make the connection unusable.
|
||
const cleanup = await client.remove(checkPath)
|
||
if (!cleanup.ok) {
|
||
recordFailure('cleanup', CLEANUP_LABEL, {
|
||
message: cleanup.failure.message,
|
||
hint: `Le fichier « ${CHECK_FILE_NAME} » est resté sur le serveur ; cela n’invalide pas le test.`
|
||
})
|
||
return { steps, ok: true }
|
||
}
|
||
recordSuccess('cleanup', CLEANUP_LABEL, 'Fichier de test supprimé.')
|
||
|
||
return { steps, ok: true }
|
||
}
|