This commit is contained in:
48
assets/scripts/api-auth.js
Normal file
48
assets/scripts/api-auth.js
Normal 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
0
assets/scripts/bigger-picture.min.js
vendored
Executable file → Normal 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({
|
||||
|
||||
@@ -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
0
assets/scripts/gallery-init.js
Executable file → Normal file
0
assets/scripts/lunr.js
Executable file → Normal file
0
assets/scripts/lunr.js
Executable file → Normal file
0
assets/scripts/mermaid.min.js
vendored
Executable file → Normal file
0
assets/scripts/mermaid.min.js
vendored
Executable file → Normal 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
0
assets/scripts/script.js
Executable file → Normal file
0
assets/scripts/search.js
Executable file → Normal file
0
assets/scripts/search.js
Executable file → Normal file
0
assets/scripts/sitemap-interactive.js
Executable file → Normal file
0
assets/scripts/sitemap-interactive.js
Executable file → Normal file
0
assets/scripts/svg-pan-zoom.min.js
vendored
Executable file → Normal file
0
assets/scripts/svg-pan-zoom.min.js
vendored
Executable file → Normal 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
0
assets/scripts/zhd.js
Executable file → Normal file
Reference in New Issue
Block a user