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 { PaperlessClient, PaperlessError } from "./lib/client.js";
|
||||||
import {
|
import {
|
||||||
ladeEinstellungen, vollstaendig, sichererName, versionslabel,
|
ladeEinstellungen, vollstaendig, sichererName, versionslabel,
|
||||||
titelAusBetreff, t
|
titelAusBetreff, zugriffsmuster, t
|
||||||
} from "./lib/settings.js";
|
} from "./lib/settings.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,6 +90,12 @@ function alsDatum(wert) {
|
|||||||
return Number.isNaN(d.getTime()) ? undefined : d.toISOString().slice(0, 10);
|
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.
|
// Offene Dialoge, damit sie ihre Aufgabe abholen können.
|
||||||
const auftraege = new Map();
|
const auftraege = new Map();
|
||||||
let naechsteAuftragsnummer = 1;
|
let naechsteAuftragsnummer = 1;
|
||||||
@@ -322,7 +328,7 @@ async function client() {
|
|||||||
// Fehlersuche beim Netzwerk.
|
// Fehlersuche beim Netzwerk.
|
||||||
let origin;
|
let origin;
|
||||||
try {
|
try {
|
||||||
origin = new URL(s.baseUrl).origin + "/*";
|
origin = zugriffsmuster(s.baseUrl);
|
||||||
} catch {
|
} catch {
|
||||||
throw new PaperlessError(t("errBadUrl"));
|
throw new PaperlessError(t("errBadUrl"));
|
||||||
}
|
}
|
||||||
@@ -333,7 +339,7 @@ async function client() {
|
|||||||
+ `In den Einstellungen erneut auf Speichern klicken - die Abfrage `
|
+ `In den Einstellungen erneut auf Speichern klicken - die Abfrage `
|
||||||
+ `kann nur aus einer Benutzeraktion heraus erscheinen.`);
|
+ `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() {
|
async function berechtigungPruefen() {
|
||||||
const s = await ladeEinstellungen();
|
const s = await ladeEinstellungen();
|
||||||
if (!vollstaendig(s)) return { noetig: false, erteilt: false };
|
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] });
|
const erteilt = await browser.permissions.contains({ origins: [muster] });
|
||||||
return { noetig: true, erteilt, muster };
|
return { noetig: true, erteilt, muster };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const TASK_POLL = 1500;
|
|||||||
export class PaperlessError extends Error {}
|
export class PaperlessError extends Error {}
|
||||||
|
|
||||||
export class PaperlessClient {
|
export class PaperlessClient {
|
||||||
constructor(baseUrl, token) {
|
constructor(baseUrl, token, shareBaseUrl = "") {
|
||||||
let parsed;
|
let parsed;
|
||||||
try {
|
try {
|
||||||
parsed = new URL(String(baseUrl || "").trim());
|
parsed = new URL(String(baseUrl || "").trim());
|
||||||
@@ -48,6 +48,13 @@ export class PaperlessClient {
|
|||||||
}
|
}
|
||||||
this.base = String(baseUrl).trim().replace(/\/+$/, "");
|
this.base = String(baseUrl).trim().replace(/\/+$/, "");
|
||||||
this.token = String(token || "").trim();
|
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() {
|
get origin() {
|
||||||
@@ -313,7 +320,7 @@ export class PaperlessClient {
|
|||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify(payload)
|
body: JSON.stringify(payload)
|
||||||
});
|
});
|
||||||
if (res?.slug) return `${this.base}/share/${res.slug}`;
|
if (res?.slug) return `${this.shareBase}/share/${res.slug}`;
|
||||||
return null;
|
return null;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
last = err;
|
last = err;
|
||||||
|
|||||||
@@ -10,9 +10,23 @@
|
|||||||
const VORGABEN = {
|
const VORGABEN = {
|
||||||
baseUrl: "",
|
baseUrl: "",
|
||||||
token: "",
|
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}",
|
versionLabel: "Thunderbird {datum}",
|
||||||
shareDays: 7,
|
shareDays: 7,
|
||||||
shareTag: "Sharelink",
|
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
|
// Anhänge, die üblicherweise keine Dokumente sind. Sie werden im
|
||||||
// Auswahldialog vorab abgewählt, lassen sich aber anhaken.
|
// Auswahldialog vorab abgewählt, lassen sich aber anhaken.
|
||||||
ignorierteTypen: ["image/gif", "image/png", "image/jpeg", "text/vcard",
|
ignorierteTypen: ["image/gif", "image/png", "image/jpeg", "text/vcard",
|
||||||
@@ -34,6 +48,21 @@ export function vollstaendig(s) {
|
|||||||
return Boolean(s?.baseUrl) && Boolean(s?.token);
|
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.
|
* Beliebige Zeichenkette in einen unbedenklichen Dateinamen überführen.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "__MSG_extName__",
|
"name": "__MSG_extName__",
|
||||||
"description": "__MSG_extDescription__",
|
"description": "__MSG_extDescription__",
|
||||||
"version": "1.5.1",
|
"version": "1.6.1",
|
||||||
"author": "Marco Morath",
|
"author": "Name des Herausgebers",
|
||||||
"homepage_url": "https://gitea.cloud.mmorath.de/marco.morath/thunderbird-paperless-connector",
|
"homepage_url": "https://example.org/paperless-thunderbird",
|
||||||
"default_locale": "de",
|
"default_locale": "de",
|
||||||
"browser_specific_settings": {
|
"browser_specific_settings": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "webmaster@mmorath.de",
|
"id": "paperless@example.org",
|
||||||
"strict_min_version": "128.0"
|
"strict_min_version": "128.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,9 +2,33 @@
|
|||||||
* gemeinsam.js - Hilfsmittel für alle Dialogseiten.
|
* 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 = {}) {
|
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) {
|
if (!antwort?.ok) {
|
||||||
throw new Error(antwort?.fehler || `Aufruf ${befehl} fehlgeschlagen`);
|
throw new Error(antwort?.fehler || `Aufruf ${befehl} fehlgeschlagen`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,17 @@
|
|||||||
Ohne abschließenden Schrägstrich. Nur http und https.
|
Ohne abschließenden Schrägstrich. Nur http und https.
|
||||||
</div>
|
</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>
|
<label for="token" data-i18n="fieldToken">API-Token</label>
|
||||||
<input type="password" id="token">
|
<input type="password" id="token">
|
||||||
<div class="hinweis" data-i18n="optionsHintToken">
|
<div class="hinweis" data-i18n="optionsHintToken">
|
||||||
@@ -54,6 +65,10 @@
|
|||||||
<input type="text" id="shareTag" style="width:160px">
|
<input type="text" id="shareTag" style="width:160px">
|
||||||
</div>
|
</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"
|
<label for="ignorierteKleiner" style="margin-top:8px"
|
||||||
data-i18n="fieldIgnoreSmaller">
|
data-i18n="fieldIgnoreSmaller">
|
||||||
Anhänge vorab abwählen unter … Bytes
|
Anhänge vorab abwählen unter … Bytes
|
||||||
|
|||||||
@@ -7,13 +7,14 @@
|
|||||||
* darf, ist eine unnötig grosse Angriffsfläche.
|
* 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 }
|
import { uebersetzeSeite, ruf, fehlerAnzeigen, meldungAnzeigen }
|
||||||
from "./gemeinsam.js";
|
from "./gemeinsam.js";
|
||||||
|
|
||||||
const $ = (id) => document.getElementById(id);
|
const $ = (id) => document.getElementById(id);
|
||||||
const FELDER = ["baseUrl", "token", "versionLabel", "shareDays", "shareTag",
|
const FELDER = ["baseUrl", "shareBaseUrl", "token", "versionLabel",
|
||||||
"ignorierteKleiner"];
|
"shareDays", "shareTag", "ignorierteKleiner"];
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
uebersetzeSeite();
|
uebersetzeSeite();
|
||||||
@@ -42,7 +43,7 @@ async function rechtAnzeigen() {
|
|||||||
}
|
}
|
||||||
let origin;
|
let origin;
|
||||||
try {
|
try {
|
||||||
origin = new URL(url).origin + "/*";
|
origin = zugriffsmuster(url);
|
||||||
} catch {
|
} catch {
|
||||||
ziel.className = "fehler";
|
ziel.className = "fehler";
|
||||||
ziel.textContent = browser.i18n.getMessage("errBadUrl") || "Ungültige Adresse.";
|
ziel.textContent = browser.i18n.getMessage("errBadUrl") || "Ungültige Adresse.";
|
||||||
@@ -58,6 +59,7 @@ async function rechtAnzeigen() {
|
|||||||
function gelesen() {
|
function gelesen() {
|
||||||
return {
|
return {
|
||||||
baseUrl: $("baseUrl").value.trim().replace(/\/+$/, ""),
|
baseUrl: $("baseUrl").value.trim().replace(/\/+$/, ""),
|
||||||
|
shareBaseUrl: ($("shareBaseUrl")?.value || "").trim().replace(/\/+$/, ""),
|
||||||
token: $("token").value.trim(),
|
token: $("token").value.trim(),
|
||||||
versionLabel: $("versionLabel").value.trim() || "Thunderbird {datum}",
|
versionLabel: $("versionLabel").value.trim() || "Thunderbird {datum}",
|
||||||
shareDays: Number($("shareDays").value || 0),
|
shareDays: Number($("shareDays").value || 0),
|
||||||
@@ -83,7 +85,7 @@ function speichern() {
|
|||||||
|
|
||||||
let origin;
|
let origin;
|
||||||
try {
|
try {
|
||||||
origin = new URL(werte.baseUrl).origin + "/*";
|
origin = zugriffsmuster(werte.baseUrl);
|
||||||
} catch {
|
} catch {
|
||||||
fehlerAnzeigen(browser.i18n.getMessage("errBadUrl")
|
fehlerAnzeigen(browser.i18n.getMessage("errBadUrl")
|
||||||
|| "Ungültige Adresse. Erwartet wird https://rechner oder http://rechner.");
|
|| "Ungültige Adresse. Erwartet wird https://rechner oder http://rechner.");
|
||||||
|
|||||||
Reference in New Issue
Block a user