mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
fix(cycle): gate the cycle ring tile and page redirect on the operator-aware module flag
The insights cycle ring tile and the /cycle page redirect gated on user.cycleTrackingEnabled, which /api/auth/me resolves without the operator availability layer — so with the Cycle module disabled server-wide the ring still rendered (and fired its calendar read) and a direct /cycle URL still loaded. Read user.modules.cycle instead, which the /me map already AND-s with the operator switch, so an operator-off instance suppresses both surfaces.
This commit is contained in:
1 parent
a73872435d
commit
e974cdb5ff
2 files changed
+17
-9
No files matched your search
+10
-7
@@ -10,18 +10,21 @@ import { CycleView } from "@/components/cycle/cycle-view";
|
||||
/**
|
||||
* v1.15.0 — the cycle vertical entry.
|
||||
*
|
||||
* Gated on `cycleTrackingEnabled` from `GET /api/auth/me` (resolved
|
||||
* server-side from gender + the per-user opt-in). An unauthenticated visitor
|
||||
* is bounced to login; an authenticated account without the feature enabled
|
||||
* is bounced home (the nav entry is already hidden for them, so this only
|
||||
* catches a direct URL hit). Every `/api/cycle/*` route also enforces the
|
||||
* gate server-side, so this is a UX redirect, not the security boundary.
|
||||
* Gated on the resolved `modules.cycle` flag from `GET /api/auth/me`
|
||||
* (v1.18.0 — the per-user toggle AND the operator server-wide kill-switch;
|
||||
* the operator-unaware `cycleTrackingEnabled` field is NOT used here so an
|
||||
* operator-disabled instance bounces a direct URL hit too). An
|
||||
* unauthenticated visitor is bounced to login; an authenticated account
|
||||
* without the module enabled is bounced home (the nav entry is already
|
||||
* hidden for them, so this only catches a direct URL hit). Every
|
||||
* `/api/cycle/*` route also enforces the gate server-side, so this is a UX
|
||||
* redirect, not the security boundary.
|
||||
*/
|
||||
export default function CyclePage() {
|
||||
const { user, isLoading, isAuthenticated } = useAuth();
|
||||
const router = useRouter();
|
||||
|
||||
const enabled = user?.cycleTrackingEnabled === true;
|
||||
const enabled = user?.modules?.cycle !== false;
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoading) return;
|
||||
|
||||
@@ -404,11 +404,16 @@ export default function InsightsPage() {
|
||||
// v1.15.3 — the cycle ring rides the scores strip as a gated sibling
|
||||
// tile, only for a cycle-tracking account, so its calendar read never
|
||||
// fires otherwise (the same `/api/auth/me` gate the sidebar nav uses).
|
||||
extraTile={user?.cycleTrackingEnabled ? <CycleRingTile /> : undefined}
|
||||
// v1.18.0 — gate on the resolved `modules.cycle` flag (per-user toggle
|
||||
// AND the operator server-wide kill-switch) so an operator-off
|
||||
// instance never renders the ring nor fires its calendar read.
|
||||
extraTile={
|
||||
user?.modules?.cycle === true ? <CycleRingTile /> : undefined
|
||||
}
|
||||
// v1.15.5 — when the cycle ring is shown it TAKES the Strain slot:
|
||||
// hide Strain so the strip stays compact instead of growing a sixth
|
||||
// tile. Strain stays visible for non-cycle accounts.
|
||||
hideStrain={user?.cycleTrackingEnabled === true}
|
||||
hideStrain={user?.modules?.cycle === true}
|
||||
/>
|
||||
),
|
||||
"daily-briefing": flags.briefing ? (
|
||||
|
||||
Reference in new issue
Block a user