feat: add backup recovery, setup wizard and user-view guards
Magent CI/CD / verify (push) Successful in 5m20s
Magent CI/CD / deploy-beta (push) Successful in 1m41s

This commit is contained in:
2026-09-18 17:23:03 +12:00
parent a6a4a9aa24
commit fd6671cf7e
44 changed files with 4650 additions and 114 deletions
+9 -6
View File
@@ -1,14 +1,14 @@
"use client";
import { useRouter } from "next/navigation";
import { type FormEvent, type KeyboardEvent, useCallback, useEffect, useState } from "react";
import { authFetch, clearToken, getApiBase, getToken } from "../lib/auth";
import { canAccess, type FeatureAccess } from "../lib/features";
import { useEffectiveRole } from "../lib/viewMode";
import PageHeading from "../ui/PageHeading";
import MonthlyRecapPreference from "./MonthlyRecapPreference";
import NewsletterPreference from "./NewsletterPreference";
import { useCallback, useEffect, useState, type FormEvent, type KeyboardEvent } from "react";
import { useRouter } from "next/navigation";
import { authFetch, clearToken, getApiBase, getToken } from "../lib/auth";
type ProfileInfo = {
features?: FeatureAccess;
username: string;
@@ -214,6 +214,7 @@ export default function ProfilePage() {
};
const user = data?.user;
const effectiveRole = useEffectiveRole(user?.role);
const passwordProvider = user?.password_provider ?? (user?.auth_provider === "jellyfin" ? "jellyfin" : "local");
const canChangePassword =
user?.password_change_supported ?? ["local", "jellyfin"].includes(user?.auth_provider ?? "");
@@ -239,7 +240,7 @@ export default function ProfilePage() {
</span>
<div>
<strong>{user.username}</strong>
<span>{user.role === "admin" ? "Administrator" : "Member"}</span>
<span>{effectiveRole === "admin" ? "Administrator" : "Member"}</span>
</div>
</div>
)
@@ -340,7 +341,9 @@ export default function ProfilePage() {
: "Signed in with your media account"}
</span>
</div>
{canAccess(user, "stats") && <MonthlyRecapPreference key={user.email || "no-email"} />}
{canAccess({ ...user, role: effectiveRole ?? undefined }, "stats") && (
<MonthlyRecapPreference key={user.email || "no-email"} />
)}
<NewsletterPreference key={`newsletter-${user.email || "no-email"}`} />
</section>