fix security 1
This commit is contained in:
+5
-4
@@ -5,6 +5,7 @@ import { bindIdentityDialog, handleAccountConfirmationToken, handleResetToken, l
|
||||
import { getAuthToken, setAccessToken } from "@rustpad/session";
|
||||
import { api } from "@rustpad/api";
|
||||
import { copyText } from "@rustpad/clipboard";
|
||||
import { safeAppUrl } from "@rustpad/security";
|
||||
|
||||
function slugify(value, fallback) {
|
||||
return value.toLowerCase().normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || fallback;
|
||||
@@ -52,7 +53,7 @@ document.querySelector("#pad-form").addEventListener("submit", async (event) =>
|
||||
if (password.value) payload.password = password.value;
|
||||
const result = await api("/api/pads", { method: "POST", headers: authHeaders(), body: JSON.stringify(payload) });
|
||||
if (password.value) { const grant = await api("/api/access-token", { method: "POST", body: JSON.stringify({ kind: "pad", slug: result.slug, password: password.value }) }); setAccessToken("pad", result.slug, grant.access_token); }
|
||||
window.location.assign(`${result.url}?view=split&mode=markdown`);
|
||||
window.location.assign(safeAppUrl(`${result.url}?view=split&mode=markdown`));
|
||||
} catch (requestError) {
|
||||
error.textContent = requestError.message;
|
||||
} finally {
|
||||
@@ -73,7 +74,7 @@ document.querySelector("#workspace-form").addEventListener("submit", async (even
|
||||
if (password.value) payload.password = password.value;
|
||||
const result = await api("/api/workspaces", { method: "POST", headers: authHeaders(), body: JSON.stringify(payload) });
|
||||
if (password.value) { const grant = await api("/api/access-token", { method: "POST", body: JSON.stringify({ kind: "workspace", slug: result.slug, password: password.value }) }); setAccessToken("workspace", result.slug, grant.access_token); }
|
||||
window.location.assign(result.url);
|
||||
window.location.assign(safeAppUrl(result.url));
|
||||
} catch (requestError) {
|
||||
error.textContent = requestError.message;
|
||||
} finally {
|
||||
@@ -110,7 +111,7 @@ async function loadResources() {
|
||||
const sharedLabel = !item.owned ? `<span class="resource-shared-badge">Shared by ${escapeHtml(item.shared_by || "another user")}</span>` : "";
|
||||
const permissionLabel = item.permission === "rw" ? "Read and write" : "Read only";
|
||||
row.classList.toggle("resource-row--shared", !Boolean(item.owned));
|
||||
row.innerHTML = `<div class="resource-main"><div class="resource-copy"><div class="resource-title-line"><a href="${item.url}">${escapeHtml(item.title)}</a>${sharedLabel}</div><small>${item.kind === "workspace" ? "Workspace" : "Note"}${item.private ? " · private" : ""}${!item.owned ? ` · ${permissionLabel}` : item.protected ? " · password protected" : ""}</small></div><div class="resource-actions">${item.owned ? `<button class="action-button action-button--secondary compact-button" type="button" data-privacy>${item.private ? "Make public" : "Make private"}</button><button class="action-button action-button--primary compact-button" type="button" data-share>Share</button><button class="action-button action-button--secondary compact-button" type="button" data-password>Change password</button><button class="action-button action-button--danger compact-button" type="button" data-delete>Delete</button>` : ""}</div></div><div class="resource-inline" data-inline hidden></div>`;
|
||||
row.innerHTML = `<div class="resource-main"><div class="resource-copy"><div class="resource-title-line"><a href="${escapeHtml(safeAppUrl(item.url))}">${escapeHtml(item.title)}</a>${sharedLabel}</div><small>${item.kind === "workspace" ? "Workspace" : "Note"}${item.private ? " · private" : ""}${!item.owned ? ` · ${permissionLabel}` : item.protected ? " · password protected" : ""}</small></div><div class="resource-actions">${item.owned ? `<button class="action-button action-button--secondary compact-button" type="button" data-privacy>${item.private ? "Make public" : "Make private"}</button><button class="action-button action-button--primary compact-button" type="button" data-share>Share</button><button class="action-button action-button--secondary compact-button" type="button" data-password>Change password</button><button class="action-button action-button--danger compact-button" type="button" data-delete>Delete</button>` : ""}</div></div><div class="resource-inline" data-inline hidden></div>`;
|
||||
|
||||
const inline = row.querySelector("[data-inline]");
|
||||
const closeInline = () => { inline.hidden = true; inline.innerHTML = ""; };
|
||||
@@ -210,7 +211,7 @@ async function loadResources() {
|
||||
|
||||
row.querySelector("[data-delete]")?.addEventListener("click", () => {
|
||||
inline.hidden = false;
|
||||
inline.innerHTML = `<div class="resource-delete-confirm"><p>Delete “${item.title}” permanently?</p><p class="form-message resource-inline-message" data-inline-message role="status"></p><div class="resource-inline-actions"><button class="danger-button" type="button" data-confirm-delete>Delete</button><button class="secondary-button" type="button" data-cancel>Cancel</button></div></div>`;
|
||||
inline.innerHTML = `<div class="resource-delete-confirm"><p>Delete “${escapeHtml(item.title)}” permanently?</p><p class="form-message resource-inline-message" data-inline-message role="status"></p><div class="resource-inline-actions"><button class="danger-button" type="button" data-confirm-delete>Delete</button><button class="secondary-button" type="button" data-cancel>Cancel</button></div></div>`;
|
||||
inline.querySelector("[data-cancel]").addEventListener("click", closeInline);
|
||||
inline.querySelector("[data-confirm-delete]").addEventListener("click", async event => {
|
||||
event.currentTarget.disabled = true;
|
||||
|
||||
Reference in New Issue
Block a user