Optional Domain mit Port und ohne für Sharelinks
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
import { PaperlessClient, PaperlessError } from "./lib/client.js";
|
||||
import {
|
||||
ladeEinstellungen, vollstaendig, sichererName, versionslabel,
|
||||
titelAusBetreff, t
|
||||
titelAusBetreff, zugriffsmuster, t
|
||||
} from "./lib/settings.js";
|
||||
|
||||
/**
|
||||
@@ -90,6 +90,12 @@ function alsDatum(wert) {
|
||||
return Number.isNaN(d.getTime()) ? undefined : d.toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
// Beim Laden eine Zeile ausgeben. Fehlt sie in der Konsole, ist das
|
||||
// Skript gar nicht erst gestartet - und dann kommt bei jedem Aufruf aus
|
||||
// einem Dialog nur "An unexpected error occurred".
|
||||
console.info("[paperless] Hintergrundskript geladen",
|
||||
browser.runtime.getManifest().version);
|
||||
|
||||
// Offene Dialoge, damit sie ihre Aufgabe abholen können.
|
||||
const auftraege = new Map();
|
||||
let naechsteAuftragsnummer = 1;
|
||||
@@ -322,7 +328,7 @@ async function client() {
|
||||
// Fehlersuche beim Netzwerk.
|
||||
let origin;
|
||||
try {
|
||||
origin = new URL(s.baseUrl).origin + "/*";
|
||||
origin = zugriffsmuster(s.baseUrl);
|
||||
} catch {
|
||||
throw new PaperlessError(t("errBadUrl"));
|
||||
}
|
||||
@@ -333,7 +339,7 @@ async function client() {
|
||||
+ `In den Einstellungen erneut auf Speichern klicken - die Abfrage `
|
||||
+ `kann nur aus einer Benutzeraktion heraus erscheinen.`);
|
||||
}
|
||||
return new PaperlessClient(s.baseUrl, s.token);
|
||||
return new PaperlessClient(s.baseUrl, s.token, s.shareBaseUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,7 +353,7 @@ async function client() {
|
||||
async function berechtigungPruefen() {
|
||||
const s = await ladeEinstellungen();
|
||||
if (!vollstaendig(s)) return { noetig: false, erteilt: false };
|
||||
const muster = new URL(s.baseUrl).origin + "/*";
|
||||
const muster = zugriffsmuster(s.baseUrl);
|
||||
const erteilt = await browser.permissions.contains({ origins: [muster] });
|
||||
return { noetig: true, erteilt, muster };
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ const TASK_POLL = 1500;
|
||||
export class PaperlessError extends Error {}
|
||||
|
||||
export class PaperlessClient {
|
||||
constructor(baseUrl, token) {
|
||||
constructor(baseUrl, token, shareBaseUrl = "") {
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(String(baseUrl || "").trim());
|
||||
@@ -48,6 +48,13 @@ export class PaperlessClient {
|
||||
}
|
||||
this.base = String(baseUrl).trim().replace(/\/+$/, "");
|
||||
this.token = String(token || "").trim();
|
||||
|
||||
// Adresse für Freigabelinks. Paperless liefert nur den Slug, die
|
||||
// vollständige Adresse wird hier zusammengesetzt. Führt der interne
|
||||
// Zugang über einen abweichenden Port, wäre ein daraus gebauter Link
|
||||
// für den Empfänger wertlos - deshalb getrennt konfigurierbar.
|
||||
this.shareBase = String(shareBaseUrl || "").trim().replace(/\/+$/, "")
|
||||
|| this.base;
|
||||
}
|
||||
|
||||
get origin() {
|
||||
@@ -313,7 +320,7 @@ export class PaperlessClient {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
if (res?.slug) return `${this.base}/share/${res.slug}`;
|
||||
if (res?.slug) return `${this.shareBase}/share/${res.slug}`;
|
||||
return null;
|
||||
} catch (err) {
|
||||
last = err;
|
||||
|
||||
@@ -10,9 +10,23 @@
|
||||
const VORGABEN = {
|
||||
baseUrl: "",
|
||||
token: "",
|
||||
// Adresse, unter der das Archiv von aussen erreichbar ist.
|
||||
//
|
||||
// Wird nur für Freigabelinks verwendet. Paperless liefert in der
|
||||
// Antwort lediglich den Slug; die vollständige Adresse setzt die
|
||||
// Erweiterung zusammen. Führt der interne Zugang über einen
|
||||
// abweichenden Port oder einen anderen Namen, wäre ein daraus gebauter
|
||||
// Link für den Empfänger wertlos.
|
||||
//
|
||||
// Leer = baseUrl verwenden.
|
||||
shareBaseUrl: "",
|
||||
versionLabel: "Thunderbird {datum}",
|
||||
shareDays: 7,
|
||||
shareTag: "Sharelink",
|
||||
// Beschriftung der eingefügten Linkblöcke. Leer lassen für keine
|
||||
// Nummerierung ist nicht vorgesehen - eine Nummer hilft beim Bezugnehmen
|
||||
// im Fließtext ("siehe Datei 2").
|
||||
linkBezeichner: "",
|
||||
// Anhänge, die üblicherweise keine Dokumente sind. Sie werden im
|
||||
// Auswahldialog vorab abgewählt, lassen sich aber anhaken.
|
||||
ignorierteTypen: ["image/gif", "image/png", "image/jpeg", "text/vcard",
|
||||
@@ -34,6 +48,21 @@ export function vollstaendig(s) {
|
||||
return Boolean(s?.baseUrl) && Boolean(s?.token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zugriffsmuster für browser.permissions aus einer Basisadresse.
|
||||
*
|
||||
* WICHTIG: Muster dürfen KEINEN Port enthalten. "https://rechner:8443/*"
|
||||
* ist ungültig, und permissions.request wirft dann eine Ausnahme mit
|
||||
* einer Meldung, die nichts über die Ursache verrät.
|
||||
*
|
||||
* Ein Zugriffsrecht gilt ohnehin für alle Ports desselben Rechners - die
|
||||
* Einschränkung kostet also nichts.
|
||||
*/
|
||||
export function zugriffsmuster(baseUrl) {
|
||||
const u = new URL(String(baseUrl).trim());
|
||||
return `${u.protocol}//${u.hostname}/*`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Beliebige Zeichenkette in einen unbedenklichen Dateinamen überführen.
|
||||
*
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
"manifest_version": 3,
|
||||
"name": "__MSG_extName__",
|
||||
"description": "__MSG_extDescription__",
|
||||
"version": "1.5.1",
|
||||
"author": "Marco Morath",
|
||||
"homepage_url": "https://gitea.cloud.mmorath.de/marco.morath/thunderbird-paperless-connector",
|
||||
"version": "1.6.1",
|
||||
"author": "Name des Herausgebers",
|
||||
"homepage_url": "https://example.org/paperless-thunderbird",
|
||||
"default_locale": "de",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "webmaster@mmorath.de",
|
||||
"id": "paperless@example.org",
|
||||
"strict_min_version": "128.0"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,9 +2,33 @@
|
||||
* gemeinsam.js - Hilfsmittel für alle Dialogseiten.
|
||||
*/
|
||||
|
||||
/** Ruft die Ereignisseite und wirft bei Fehlern eine Ausnahme. */
|
||||
/**
|
||||
* Ruft die Ereignisseite und wirft bei Fehlern eine Ausnahme.
|
||||
*
|
||||
* Unterscheidet zwei Fälle, die sonst dieselbe nichtssagende Meldung
|
||||
* ergeben ("An unexpected error occurred"):
|
||||
*
|
||||
* * Die Nachricht erreicht keinen Empfänger - das Hintergrundskript
|
||||
* ist nicht geladen oder abgestürzt.
|
||||
* * Der Empfänger meldet einen Fehler zurück.
|
||||
*/
|
||||
export async function ruf(befehl, daten = {}) {
|
||||
const antwort = await browser.runtime.sendMessage({ befehl, ...daten });
|
||||
let antwort;
|
||||
try {
|
||||
antwort = await browser.runtime.sendMessage({ befehl, ...daten });
|
||||
} catch (err) {
|
||||
console.error("[paperless] sendMessage", befehl, err);
|
||||
throw new Error(
|
||||
`Das Hintergrundskript antwortet nicht (${befehl}).\n`
|
||||
+ `Ursprüngliche Meldung: ${err?.message || err}\n\n`
|
||||
+ `Einzelheiten in der Konsole: Extras -> Entwicklerwerkzeuge -> `
|
||||
+ `Debuggen von Add-ons -> Inspizieren.`);
|
||||
}
|
||||
if (antwort === undefined) {
|
||||
throw new Error(
|
||||
`Keine Antwort auf ${befehl}. Das Hintergrundskript ist `
|
||||
+ `vermutlich nicht geladen.`);
|
||||
}
|
||||
if (!antwort?.ok) {
|
||||
throw new Error(antwort?.fehler || `Aufruf ${befehl} fehlgeschlagen`);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,17 @@
|
||||
Ohne abschließenden Schrägstrich. Nur http und https.
|
||||
</div>
|
||||
|
||||
<label for="shareBaseUrl" data-i18n="fieldShareBaseUrl">
|
||||
Adresse für Freigabelinks (optional)
|
||||
</label>
|
||||
<input type="text" id="shareBaseUrl"
|
||||
placeholder="https://dms.example.org">
|
||||
<div class="hinweis" data-i18n="optionsHintShareUrl">
|
||||
Nur nötig, wenn der interne Zugang über einen abweichenden Port oder
|
||||
Namen läuft. Freigabelinks werden dann unter dieser Adresse gebaut,
|
||||
damit sie auch von außen funktionieren. Leer = Basisadresse.
|
||||
</div>
|
||||
|
||||
<label for="token" data-i18n="fieldToken">API-Token</label>
|
||||
<input type="password" id="token">
|
||||
<div class="hinweis" data-i18n="optionsHintToken">
|
||||
@@ -54,6 +65,10 @@
|
||||
<input type="text" id="shareTag" style="width:160px">
|
||||
</div>
|
||||
|
||||
<div class="hinweis" data-i18n="optionsHintTag">
|
||||
Tag beim Teilen leer lassen, um keine Kennzeichnung zu setzen.
|
||||
</div>
|
||||
|
||||
<label for="ignorierteKleiner" style="margin-top:8px"
|
||||
data-i18n="fieldIgnoreSmaller">
|
||||
Anhänge vorab abwählen unter … Bytes
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
* darf, ist eine unnötig grosse Angriffsfläche.
|
||||
*/
|
||||
|
||||
import { ladeEinstellungen, speichereEinstellungen } from "../lib/settings.js";
|
||||
import { ladeEinstellungen, speichereEinstellungen, zugriffsmuster }
|
||||
from "../lib/settings.js";
|
||||
import { uebersetzeSeite, ruf, fehlerAnzeigen, meldungAnzeigen }
|
||||
from "./gemeinsam.js";
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const FELDER = ["baseUrl", "token", "versionLabel", "shareDays", "shareTag",
|
||||
"ignorierteKleiner"];
|
||||
const FELDER = ["baseUrl", "shareBaseUrl", "token", "versionLabel",
|
||||
"shareDays", "shareTag", "ignorierteKleiner"];
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
uebersetzeSeite();
|
||||
@@ -42,7 +43,7 @@ async function rechtAnzeigen() {
|
||||
}
|
||||
let origin;
|
||||
try {
|
||||
origin = new URL(url).origin + "/*";
|
||||
origin = zugriffsmuster(url);
|
||||
} catch {
|
||||
ziel.className = "fehler";
|
||||
ziel.textContent = browser.i18n.getMessage("errBadUrl") || "Ungültige Adresse.";
|
||||
@@ -58,6 +59,7 @@ async function rechtAnzeigen() {
|
||||
function gelesen() {
|
||||
return {
|
||||
baseUrl: $("baseUrl").value.trim().replace(/\/+$/, ""),
|
||||
shareBaseUrl: ($("shareBaseUrl")?.value || "").trim().replace(/\/+$/, ""),
|
||||
token: $("token").value.trim(),
|
||||
versionLabel: $("versionLabel").value.trim() || "Thunderbird {datum}",
|
||||
shareDays: Number($("shareDays").value || 0),
|
||||
@@ -83,7 +85,7 @@ function speichern() {
|
||||
|
||||
let origin;
|
||||
try {
|
||||
origin = new URL(werte.baseUrl).origin + "/*";
|
||||
origin = zugriffsmuster(werte.baseUrl);
|
||||
} catch {
|
||||
fehlerAnzeigen(browser.i18n.getMessage("errBadUrl")
|
||||
|| "Ungültige Adresse. Erwartet wird https://rechner oder http://rechner.");
|
||||
|
||||
Reference in New Issue
Block a user