fix: add credentials to all fetch calls for auth cookie support (#72)
* fix: add credentials to all fetch calls for auth cookie support - Add credentials: include to useMedications.ts fetch calls - Add credentials: include to MedicationsPage.tsx save function - Add credentials: include to useSettings.ts settings update - Add credentials: include to useShare.ts share generation - Add credentials: include to DashboardPage.tsx reminder email - Add credentials: include to PlannerPage.tsx usage calculation - Make create-release workflow skip if release already exists * fix: default to ntfy-style notifications for HTTP URLs - Change notification logic to use plain text format by default - Only use JSON format for known webhook services (Discord, Slack, Telegram, Gotify) - This fixes ntfy URLs not being recognized when hostname doesn't contain 'ntfy' * feat: highlight medication being edited - Add blue border and background to the medication row being edited - Show medication avatar and name in the edit form header - Makes it easy to identify which medication is being edited when there are many * fix: use proper URL parsing for webhook detection (CodeQL security fix) Replace vulnerable .includes() URL checks with proper URL hostname parsing to prevent bypass attacks (e.g., evil.com?hooks.slack.com). Fixes CodeQL alerts #33 and #34 (js/incomplete-url-substring-sanitization)
This commit is contained in:
@@ -217,6 +217,7 @@ export function DashboardPage() {
|
||||
const res = await fetch("/api/reminder/send-email", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
body: JSON.stringify({
|
||||
email: settings.notificationEmail,
|
||||
lowStock: coverage.low,
|
||||
|
||||
@@ -192,6 +192,7 @@ export function MedicationsPage() {
|
||||
method,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(body),
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
@@ -308,7 +309,7 @@ export function MedicationsPage() {
|
||||
</div>
|
||||
<div className="med-list">
|
||||
{meds.map((med) => (
|
||||
<div key={med.id} className="med-row">
|
||||
<div key={med.id} className={`med-row${editingId === med.id ? " editing" : ""}`}>
|
||||
<div className="med-header">
|
||||
<div className="med-info">
|
||||
<div className="med-name-row">
|
||||
@@ -358,7 +359,20 @@ export function MedicationsPage() {
|
||||
|
||||
<article className="card form desktop-only">
|
||||
<div className="card-head">
|
||||
<h2>{editingId ? t("form.editEntry") : t("form.newEntry")}</h2>
|
||||
{editingId ? (
|
||||
<div className="edit-header">
|
||||
<MedicationAvatar
|
||||
name={meds.find((m) => m.id === editingId)?.name || ""}
|
||||
imageUrl={meds.find((m) => m.id === editingId)?.imageUrl}
|
||||
size="md"
|
||||
/>
|
||||
<h2>
|
||||
{t("form.editEntry")}: {meds.find((m) => m.id === editingId)?.name}
|
||||
</h2>
|
||||
</div>
|
||||
) : (
|
||||
<h2>{t("form.newEntry")}</h2>
|
||||
)}
|
||||
</div>
|
||||
<form className="form-grid" onSubmit={saveMedication}>
|
||||
<label className={fieldErrors.name ? "has-error" : ""}>
|
||||
|
||||
@@ -82,6 +82,7 @@ export function PlannerPage() {
|
||||
const rows = (await fetch("/api/medications/usage", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
.then((res) => res.json())
|
||||
@@ -113,6 +114,7 @@ export function PlannerPage() {
|
||||
const res = await fetch("/api/planner/send-email", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "include",
|
||||
body: JSON.stringify({
|
||||
email: settings.notificationEmail,
|
||||
from: range.start,
|
||||
|
||||
Reference in New Issue
Block a user