mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
Merge branch 'fix/v1474-auth' into release/v1.47.4
# Conflicts: # src/__tests__/baselines/version-stamp-comments.json
This commit is contained in:
commit
212ff9ee55
33 files changed
+1177
-151
No files matched your search
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Production files over 800 lines and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 84,
|
||||
"total": 94047,
|
||||
"total": 94006,
|
||||
"entries": {
|
||||
"app/medications/page-client.tsx": 839,
|
||||
"components/charts/mood-chart.tsx": 1166,
|
||||
@@ -12,7 +12,7 @@
|
||||
"components/insights/derived/vitals-dashboard.tsx": 1033,
|
||||
"components/insights/health-score-card.tsx": 1023,
|
||||
"components/insights/insights-tab-strip.tsx": 1087,
|
||||
"components/measurements/measurement-form.tsx": 815,
|
||||
"components/measurements/measurement-form.tsx": 812,
|
||||
"components/medications/detail/medication-detail-tabs.tsx": 1157,
|
||||
"components/medications/medication-table.tsx": 853,
|
||||
"components/medications/wizard/wizard-payload.ts": 1414,
|
||||
@@ -82,7 +82,7 @@
|
||||
"lib/search/search-records.ts": 996,
|
||||
"lib/sharing/grants.ts": 806,
|
||||
"lib/support/report.ts": 903,
|
||||
"lib/telegram-webhook-handlers.ts": 1341,
|
||||
"lib/telegram-webhook-handlers.ts": 1335,
|
||||
"lib/validations/inbound-documents.ts": 1018,
|
||||
"lib/withings/sync-sleep.ts": 884,
|
||||
"lib/withings/sync.ts": 933,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Production functions over 200 lines, keyed \"file :: name\", and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 344,
|
||||
"total": 111495,
|
||||
"count": 343,
|
||||
"total": 111120,
|
||||
"entries": {
|
||||
"app/achievements/page.tsx :: AchievementsPage": 206,
|
||||
"app/api/admin/backups/upload/route.ts :: apiHandler(arg)": 275,
|
||||
@@ -17,7 +17,7 @@
|
||||
"app/api/devices/route.ts :: apiHandler(arg)": 226,
|
||||
"app/api/encounters/[id]/route.ts :: apiHandler(arg) #2": 269,
|
||||
"app/api/environment/route.ts :: apiHandler(arg)": 201,
|
||||
"app/api/export/health-record/route.ts :: apiHandler(arg)": 241,
|
||||
"app/api/export/health-record/route.ts :: apiHandler(arg)": 240,
|
||||
"app/api/ingest/medication/route.ts :: apiHandler(arg)": 259,
|
||||
"app/api/insights/cards/route.ts :: apiHandler(arg)": 211,
|
||||
"app/api/integrations/status/route.ts :: apiHandler(arg)": 476,
|
||||
@@ -38,8 +38,8 @@
|
||||
"app/api/record-settings/[family]/route.ts :: apiHandler(arg) #2": 262,
|
||||
"app/api/user/ai-provider/route.ts :: apiHandler(arg) #2": 248,
|
||||
"app/api/withings/callback/route.ts :: apiHandler(arg)": 247,
|
||||
"app/auth/login/page.tsx :: LoginPage": 569,
|
||||
"app/auth/register/page.tsx :: RegisterPage": 285,
|
||||
"app/auth/login/page.tsx :: LoginPage": 561,
|
||||
"app/auth/register/page.tsx :: RegisterPage": 283,
|
||||
"app/coach/conversations/page.tsx :: CoachConversationsBody": 249,
|
||||
"app/coach/plans/page.tsx :: CoachPlansBody": 216,
|
||||
"app/insights/catalog/page.tsx :: MetricCatalogPage": 204,
|
||||
@@ -64,7 +64,7 @@
|
||||
"components/admin/user-management-section.tsx :: UserManagementSection": 622,
|
||||
"components/admin/web-push-vapid-section.tsx :: WebPushVapidSection": 217,
|
||||
"components/auth/claim-profile.tsx :: ClaimProfile": 429,
|
||||
"components/auth/mfa-login-step.tsx :: MfaLoginStep": 217,
|
||||
"components/auth/mfa-login-step.tsx :: MfaLoginStep": 215,
|
||||
"components/charts/compliance-heatmap.tsx :: ComplianceHeatmap": 325,
|
||||
"components/charts/health-chart.tsx :: HealthChart": 470,
|
||||
"components/charts/medication-compliance-chart.tsx :: MedicationComplianceChart": 543,
|
||||
@@ -73,7 +73,7 @@
|
||||
"components/charts/trend-card.tsx :: TrendCard": 365,
|
||||
"components/clinician/clinician-view.tsx :: ClinicianView": 223,
|
||||
"components/command-palette/command-palette.tsx :: PaletteBody": 333,
|
||||
"components/custom-metrics/custom-metric-chart.tsx :: CustomMetricChart": 231,
|
||||
"components/custom-metrics/custom-metric-chart.tsx :: CustomMetricChart": 228,
|
||||
"components/custom-metrics/custom-metric-detail.tsx :: CustomMetricDetail": 277,
|
||||
"components/custom-metrics/custom-metric-form.tsx :: CustomMetricForm": 214,
|
||||
"components/custom-metrics/custom-metric-history-list.tsx :: CustomMetricHistoryList": 302,
|
||||
@@ -138,7 +138,7 @@
|
||||
"components/labs/lab-history-list.tsx :: LabHistoryList": 534,
|
||||
"components/labs/ocr-review-dialog.tsx :: OcrReviewDialog": 359,
|
||||
"components/labs/ocr-row-editor.tsx :: OcrRowEditor": 378,
|
||||
"components/layout/auth-shell.tsx :: AuthShell": 518,
|
||||
"components/layout/auth-shell.tsx :: AuthShell": 483,
|
||||
"components/layout/bottom-nav.tsx :: BottomNav": 262,
|
||||
"components/layout/capture-picker.tsx :: CapturePicker": 235,
|
||||
"components/layout/sidebar-nav.tsx :: SidebarNav": 356,
|
||||
@@ -146,7 +146,7 @@
|
||||
"components/links/entity-link-picker.tsx :: EntityLinkPicker": 392,
|
||||
"components/measurement-reminders/vorsorge-dashboard-card.tsx :: VorsorgeDashboardCard": 215,
|
||||
"components/measurement-reminders/vorsorge-section.tsx :: VorsorgeSection": 352,
|
||||
"components/measurements/measurement-form.tsx :: MeasurementForm": 500,
|
||||
"components/measurements/measurement-form.tsx :: MeasurementForm": 493,
|
||||
"components/medications/detail/efficacy/efficacy-chart.tsx :: EfficacyChart": 361,
|
||||
"components/medications/detail/medication-detail-tabs.tsx :: MedicationDetailTabs": 767,
|
||||
"components/medications/dose-history-add-dialog.tsx :: LedgerAddDialog": 223,
|
||||
@@ -161,7 +161,7 @@
|
||||
"components/medications/medication-table.tsx :: MedicationTableRowItem": 377,
|
||||
"components/medications/scheduling/natural-language-extractor.tsx :: NaturalLanguageExtractor": 214,
|
||||
"components/medications/scheduling/schedule-history-timeline.tsx :: EraDialog": 219,
|
||||
"components/medications/scheduling/schedule-history-timeline.tsx :: ScheduleHistoryTimeline": 256,
|
||||
"components/medications/scheduling/schedule-history-timeline.tsx :: ScheduleHistoryTimeline": 254,
|
||||
"components/medications/sections/api-tokens-row.tsx :: ApiTokensRow": 296,
|
||||
"components/medications/sections/composition-section.tsx :: CompositionEditor": 362,
|
||||
"components/medications/sections/inventory-dialogs.tsx :: AddInventoryDialog": 238,
|
||||
@@ -232,7 +232,7 @@
|
||||
"components/timeline/life-event-form.tsx :: LifeEventForm": 281,
|
||||
"components/timeline/timeline-chart.tsx :: ChartBody": 236,
|
||||
"components/timeline/timeline-chronicle.tsx :: TimelineChronicle": 246,
|
||||
"components/timeline/timeline-view.tsx :: TimelineView": 486,
|
||||
"components/timeline/timeline-view.tsx :: TimelineView": 478,
|
||||
"components/ui/responsive-sheet.tsx :: ResponsiveSheet": 239,
|
||||
"components/vaccinations/catalog-picker.tsx :: CatalogPicker": 221,
|
||||
"components/vaccinations/custom-vaccine-sheet.tsx :: CustomVaccineSheet": 246,
|
||||
@@ -284,8 +284,8 @@
|
||||
"lib/google-health/data-points.ts :: forEachDataPointPage > walk": 223,
|
||||
"lib/google-health/sync-core.ts :: upsertGoogleHealthMeasurements": 452,
|
||||
"lib/illness/correlation.ts :: computeIllnessCorrelation": 233,
|
||||
"lib/import/labs-csv.ts :: importLabsCsv": 307,
|
||||
"lib/import/labs-csv.ts :: importLabsCsv > flush": 229,
|
||||
"lib/import/labs-csv.ts :: importLabsCsv": 305,
|
||||
"lib/import/labs-csv.ts :: importLabsCsv > flush": 227,
|
||||
"lib/insights/comprehensive-aggregator.ts :: buildFromRollups": 217,
|
||||
"lib/insights/comprehensive-generate.ts :: generateComprehensiveInsight": 876,
|
||||
"lib/insights/features.ts :: extractFeatures": 796,
|
||||
@@ -329,7 +329,7 @@
|
||||
"lib/medications/list-read.ts :: buildMedicationsList": 308,
|
||||
"lib/medications/scheduling/dose-history.ts :: reconstructDoseHistory": 218,
|
||||
"lib/multipart/stream-to-disk.ts :: streamMultipartToDisk": 272,
|
||||
"lib/notifications/dispatcher.ts :: dispatchNotification": 378,
|
||||
"lib/notifications/dispatcher.ts :: dispatchNotification": 368,
|
||||
"lib/notifications/senders/apns.ts :: sendViaApns": 299,
|
||||
"lib/notifications/senders/web-push.ts :: sendViaWebPush": 255,
|
||||
"lib/personal-records/pr-detection-worker.ts :: detectPersonalRecordsForUser": 239,
|
||||
@@ -339,12 +339,12 @@
|
||||
"lib/support/report.ts :: collectSupportReportFacts": 332,
|
||||
"lib/targets/build-response.ts :: buildTargetsResponse": 330,
|
||||
"lib/targets/vitals-builder.ts :: buildVitalTargets": 324,
|
||||
"lib/telegram-webhook-handlers.ts :: handleCallback": 599,
|
||||
"lib/telegram-webhook-handlers.ts :: handleCallback": 590,
|
||||
"lib/telegram-webhook-handlers.ts :: handleTextMessage": 337,
|
||||
"lib/withings/sync-activity.ts :: syncUserActivity": 377,
|
||||
"lib/withings/sync-ecg.ts :: syncUserEcg": 202,
|
||||
"lib/withings/sync-sleep.ts :: syncUserSleep": 414,
|
||||
"lib/withings/sync.ts :: syncUserMeasurements": 337,
|
||||
"proxy.ts :: proxy": 471
|
||||
"proxy.ts :: proxy": 467
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Comment lines that open with a release version, per file under src/. Maintained by src/__tests__/version-stamp-ratchet.test.ts.",
|
||||
"count": 2885,
|
||||
"total": 9198,
|
||||
"total": 9193,
|
||||
"entries": {
|
||||
"__tests__/account-payload-consumer-guard.test.ts": 2,
|
||||
"__tests__/acting-account-boundary-guard.test.ts": 7,
|
||||
@@ -136,7 +136,7 @@
|
||||
"app/api/auth/codex/device-start/route.ts": 1,
|
||||
"app/api/auth/login/__tests__/native-token.test.ts": 2,
|
||||
"app/api/auth/login/__tests__/route.test.ts": 1,
|
||||
"app/api/auth/login/route.ts": 5,
|
||||
"app/api/auth/login/route.ts": 4,
|
||||
"app/api/auth/me/coach-prefs/route.ts": 7,
|
||||
"app/api/auth/me/cycle-prefs/route.ts": 1,
|
||||
"app/api/auth/me/devices/[id]/route.ts": 3,
|
||||
@@ -556,7 +556,7 @@
|
||||
"app/api/workouts/route.ts": 2,
|
||||
"app/auth/claim/page.tsx": 1,
|
||||
"app/auth/login/page.tsx": 5,
|
||||
"app/auth/register/page.tsx": 4,
|
||||
"app/auth/register/page.tsx": 3,
|
||||
"app/c/[token]/__tests__/page.test.tsx": 2,
|
||||
"app/c/[token]/d/[id]/__tests__/route.test.ts": 1,
|
||||
"app/c/[token]/d/[id]/route.ts": 1,
|
||||
@@ -1094,7 +1094,7 @@
|
||||
"components/layout/__tests__/shared-record-chrome.test.tsx": 1,
|
||||
"components/layout/__tests__/sidebar-nav.test.tsx": 3,
|
||||
"components/layout/account-switcher-menu.tsx": 1,
|
||||
"components/layout/auth-shell.tsx": 14,
|
||||
"components/layout/auth-shell.tsx": 13,
|
||||
"components/layout/bottom-nav.tsx": 8,
|
||||
"components/layout/capture-picker.tsx": 5,
|
||||
"components/layout/nav-model.ts": 17,
|
||||
@@ -2885,7 +2885,7 @@
|
||||
"lib/withings/sync.ts": 6,
|
||||
"lib/withings/webhook-handler.ts": 3,
|
||||
"lib/workouts/list-read.ts": 1,
|
||||
"proxy.ts": 27,
|
||||
"proxy.ts": 25,
|
||||
"types/analytics.ts": 8,
|
||||
"types/backups.ts": 1
|
||||
}
|
||||
|
||||
@@ -161,6 +161,25 @@ describe("proxy.ts DEMO_MODE mutation allowlist", () => {
|
||||
expect(proxy(makeRequest("/api/search", "DELETE")).status).toBe(403);
|
||||
});
|
||||
|
||||
it("lets a visitor sign out, report page timings and pick a language", () => {
|
||||
// Each touches only this visitor: their own session, a log line, their
|
||||
// own language cookie (the locale route leaves the shared account's row
|
||||
// alone under DEMO_MODE). Refused, sign-out stayed signed in and every
|
||||
// page load sent the refused locale write and the timings again.
|
||||
for (const [path, method] of [
|
||||
["/api/auth/logout", "POST"],
|
||||
["/api/internal/web-vitals", "POST"],
|
||||
["/api/auth/me/locale", "PUT"],
|
||||
] as const) {
|
||||
expect(
|
||||
proxy(makeRequest(path, method)).status,
|
||||
`${method} ${path} is blocked in the demo`,
|
||||
).not.toBe(403);
|
||||
}
|
||||
// The rest of the account's settings stay closed.
|
||||
expect(proxy(makeRequest("/api/auth/me/timezone", "PUT")).status).toBe(403);
|
||||
});
|
||||
|
||||
it("still blocks a health-data mutation (POST /api/measurements)", () => {
|
||||
const res = proxy(makeRequest("/api/measurements", "POST"));
|
||||
expect(res.status).toBe(403);
|
||||
|
||||
@@ -87,7 +87,7 @@ describe("proxy early exits carry the baseline security headers", () => {
|
||||
|
||||
it("unauthenticated page redirect to /auth/login", () => {
|
||||
const res = proxy(makeRequest("/dashboard"));
|
||||
expect(res.headers.get("location")).toMatch(/\/auth\/login$/);
|
||||
expect(res.headers.get("location")).toMatch(/\/auth\/login(\?|$)/);
|
||||
expectBaselineHeaders(res);
|
||||
});
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ describe("proxy.ts onboarding redirect (v1.4.22 C4)", () => {
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get("location")).toBeNull();
|
||||
const anonymous = proxy(makeRequest("/insights"));
|
||||
expect(anonymous.headers.get("location")).toMatch(/\/auth\/login$/);
|
||||
expect(anonymous.headers.get("location")).toMatch(/\/auth\/login(\?|$)/);
|
||||
});
|
||||
|
||||
it("passes through when hl_onboarding cookie is absent (completed users)", () => {
|
||||
@@ -123,7 +123,7 @@ describe("proxy.ts onboarding redirect (v1.4.22 C4)", () => {
|
||||
// were still in place it would short-circuit through public-path
|
||||
// handling and 200 instead.
|
||||
expect([307, 308]).toContain(res.status);
|
||||
expect(res.headers.get("location")).toMatch(/\/auth\/login$/);
|
||||
expect(res.headers.get("location")).toMatch(/\/auth\/login(\?|$)/);
|
||||
});
|
||||
|
||||
it("still treats subroutes /onboarding/<x> as the onboarding surface", () => {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* The edge sends a visitor without a session to the sign-in page with the
|
||||
* page they asked for in `next`, so a home-screen shortcut or a notification
|
||||
* tap still arrives there after signing in. The sign-in page re-checks the
|
||||
* value (`sanitizeSameOriginPath`); the proxy only ever puts in the
|
||||
* request's own path and query.
|
||||
*/
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
vi.mock("@/lib/process-type", () => ({
|
||||
shouldRunWeb: () => true,
|
||||
}));
|
||||
|
||||
import { proxy } from "../proxy";
|
||||
|
||||
function signInRedirect(pathAndQuery: string): URL {
|
||||
const res = proxy(new NextRequest(`http://localhost${pathAndQuery}`));
|
||||
expect([307, 308]).toContain(res.status);
|
||||
return new URL(res.headers.get("location")!, "http://localhost");
|
||||
}
|
||||
|
||||
describe("proxy.ts sign-in redirect", () => {
|
||||
it.each([
|
||||
"/measurements?add=WEIGHT&source=shortcut",
|
||||
"/mood?add=1",
|
||||
"/medications",
|
||||
"/?source=pwa",
|
||||
])("carries %s to the sign-in page", (target) => {
|
||||
const location = signInRedirect(target);
|
||||
expect(location.pathname).toBe("/auth/login");
|
||||
expect(location.searchParams.get("next")).toBe(target);
|
||||
});
|
||||
|
||||
it("sends the bare start page to a bare sign-in page", () => {
|
||||
const location = signInRedirect("/");
|
||||
expect(location.pathname).toBe("/auth/login");
|
||||
expect(location.search).toBe("");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user