auth
All checks were successful
Build Org Website / build (push) Successful in 49s

This commit is contained in:
2026-05-09 00:26:04 +01:00
parent a504eb9179
commit a18debbf21
327 changed files with 66 additions and 16 deletions

View File

@@ -0,0 +1,48 @@
(function () {
"use strict";
const STORAGE_KEY = "orgBackendApiKey";
const HEADER = "X-Org-Api-Key";
function getStoredKey() {
return window.localStorage.getItem(STORAGE_KEY) || "";
}
function requestKey() {
const key = window.prompt("API key");
if (key && key.trim()) {
window.localStorage.setItem(STORAGE_KEY, key.trim());
return key.trim();
}
return "";
}
function authHeaders(existingHeaders = {}, options = {}) {
const headers = new Headers(existingHeaders);
let key = getStoredKey();
if (!key && options.prompt !== false) {
key = requestKey();
}
if (key) headers.set(HEADER, key);
return headers;
}
async function authFetch(input, options = {}) {
const headers = authHeaders(options.headers, options);
const response = await fetch(input, { ...options, headers });
if (response.status !== 401) return response;
window.localStorage.removeItem(STORAGE_KEY);
if (options.retry === false) return response;
const retryHeaders = authHeaders(options.headers, options);
if (!retryHeaders.has(HEADER)) return response;
return fetch(input, { ...options, headers: retryHeaders, retry: false });
}
window.orgAuth = {
fetch: authFetch,
headers: authHeaders,
clear: () => window.localStorage.removeItem(STORAGE_KEY),
};
})();

0
assets/scripts/bigger-picture.min.js vendored Executable file → Normal file
View File

View File

@@ -130,7 +130,7 @@ async function fetchComments() {
}
async function postComment(author, content, parentId = null) {
const res = await fetch("/api/comments", {
const res = await window.orgAuth.fetch("/api/comments", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({

View File

@@ -118,7 +118,7 @@ if (moveConfirmBtn) {
return;
}
const res = await fetch(`/api/competencies/items/${itemId}/state`, {
const res = await window.orgAuth.fetch(`/api/competencies/items/${itemId}/state`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ state: to }),
@@ -192,7 +192,7 @@ function createColumn(state, items, counts) {
list.addEventListener("drop", async () => {
if (!draggedItemId) return;
const res = await fetch(`/api/competencies/items/${draggedItemId}/state`, {
const res = await window.orgAuth.fetch(`/api/competencies/items/${draggedItemId}/state`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ state: state.key }),
@@ -228,7 +228,7 @@ function renderBoard(items) {
}
async function loadBoard() {
const res = await fetch(`/api/competencies/items?group=${currentLevel}`);
const res = await window.orgAuth.fetch(`/api/competencies/items?group=${currentLevel}`);
const items = await res.json();
updateProgress(items);

0
assets/scripts/gallery-init.js Executable file → Normal file
View File

0
assets/scripts/lunr.js Executable file → Normal file
View File

0
assets/scripts/mermaid.min.js vendored Executable file → Normal file
View File

View File

@@ -38,7 +38,7 @@
wall.innerHTML = "<p>Loading notes…</p>";
try {
const res = await fetch("/api/notes");
const res = await window.orgAuth.fetch("/api/notes");
if (!res.ok) throw new Error("Failed to fetch notes");
const notes = await res.json();
@@ -69,7 +69,7 @@
form.querySelector("button").disabled = true;
try {
const res = await fetch("/api/notes", {
const res = await window.orgAuth.fetch("/api/notes", {
method: "POST",
headers: {
"Content-Type": "application/json",

0
assets/scripts/script.js Executable file → Normal file
View File

0
assets/scripts/search.js Executable file → Normal file
View File

0
assets/scripts/sitemap-interactive.js Executable file → Normal file
View File

0
assets/scripts/svg-pan-zoom.min.js vendored Executable file → Normal file
View File

View File

@@ -96,8 +96,8 @@
async function loadMotalah() {
try {
const [mRes, bRes] = await Promise.all([
fetch(MOTALAH_API),
fetch(CALIBRE_API),
window.orgAuth.fetch(MOTALAH_API),
window.orgAuth.fetch(CALIBRE_API),
]);
if (mRes.ok) motalahEntries = await mRes.json();
if (bRes.ok) calibreBooks = await bRes.json();
@@ -301,7 +301,7 @@
notes: motalahNotesEl.value.trim() || null,
};
try {
const r = await fetch(MOTALAH_API, {
const r = await window.orgAuth.fetch(MOTALAH_API, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
@@ -350,7 +350,7 @@
async function loadAll() {
try {
const r = await fetch(`${API}/entries`);
const r = await window.orgAuth.fetch(`${API}/entries`);
if (!r.ok) throw new Error(r.status);
allEntries = await r.json();
buildTodayMap();
@@ -383,7 +383,7 @@
}
async function postEntry(payload) {
const r = await fetch(`${API}/entries`, {
const r = await window.orgAuth.fetch(`${API}/entries`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
@@ -393,7 +393,7 @@
}
async function deleteEntry(id) {
const r = await fetch(`${API}/entries/${id}`, { method: "DELETE" });
const r = await window.orgAuth.fetch(`${API}/entries/${id}`, { method: "DELETE" });
if (!r.ok) throw new Error(await r.text());
}

0
assets/scripts/zhd.js Executable file → Normal file
View File