mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
feat(modules): gate achievements behind the achievements module flag
When an account turns the achievements module off the whole gamification surface disappears. The route enforces the gate after auth and returns the 403 module.disabled envelope, so no badge evaluation, unlock persistence, or payload is produced. The achievements page, the dashboard recent-unlocks tile, and the unlock notifier read the resolved module map from GET /api/auth/me and render nothing / disable their query when the module is off. Default-on: an absent key reads as enabled, a stale /me payload coerces to an empty map so no surface vanishes on a partial-deploy rollback.
This commit is contained in:
1 parent
3264dd2e86
commit
70402ea95a
10 files changed
+361
-5
No files matched your search
@@ -80,6 +80,17 @@ export interface AuthUser {
|
||||
* stale /me payload (older server image without the field) in `fetchMe`.
|
||||
*/
|
||||
cycleTrackingEnabled: boolean;
|
||||
/**
|
||||
* v1.18.0 — per-user module enable/disable map resolved server-side
|
||||
* (`resolveModuleMap`). A `false` entry hides every surface that module
|
||||
* owns; an absent key reads as enabled (default-on, fail-open), matching
|
||||
* the gate's disabled-allowlist semantics. A stale /me payload without
|
||||
* the field coerces to an empty map in `fetchMe`, so every surface stays
|
||||
* visible rather than vanishing on a partial-deploy rollback. Optional
|
||||
* so existing `AuthUser` test fixtures stay valid; `fetchMe` always
|
||||
* populates it (empty map when absent), so live code reads a real map.
|
||||
*/
|
||||
modules?: Record<string, boolean>;
|
||||
}
|
||||
|
||||
async function fetchMe(): Promise<AuthUser> {
|
||||
@@ -117,6 +128,11 @@ async function fetchMe(): Promise<AuthUser> {
|
||||
// v1.15.0 — coerce against a stale /me payload so the cycle nav entry
|
||||
// stays hidden by default when the field is absent.
|
||||
cycleTrackingEnabled: data.cycleTrackingEnabled === true,
|
||||
// v1.18.0 — coerce against a stale /me payload so module gates default
|
||||
// to enabled (empty map ⇒ every key reads on) rather than hiding a
|
||||
// surface on an older server image without the field.
|
||||
modules:
|
||||
data.modules && typeof data.modules === "object" ? data.modules : {},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user