1
0
Fork 0
polaris-task-force/src/app/(frontend)/locker/page.tsx
Z8MB1E c0d00fc113 fix(auth): reject MCP API-key sessions in user auth paths
With the MCP plugin enabled, payload.auth() can return a
payload-mcp-api-keys doc instead of a User. Add an isPayloadUser
type guard and use it in every server action, page, and route that
treats the auth result as a real user, so API-key sessions can no
longer pass user auth checks. hasRoles now explicitly requires a
users-collection doc.
2026-08-25 12:27:35 -04:00

79 lines
2.5 KiB
TypeScript

import config from "@payload-config";
import { isPayloadUser } from "@/utils/access-control/isPayloadUser";
import { getPayload } from "payload";
import { headers as nextHeaders } from "next/headers";
import type { Asset, Loadout, LockerStorage } from "@/payload-types";
import { LockKeyholeIcon } from "lucide-react";
import { ensureLockerStorage, getLockerGridDimensions } from "@/lib/locker";
import { LockerView } from "@/components/frontend/locker/LockerView";
import { hasPermission } from "@/utils/access-control/hasPermission";
export const metadata = {
title: "Locker — Polaris Task Force",
};
export default async function LockerPage() {
const payload = await getPayload({ config });
const { user: authUser } = await payload.auth({
headers: await nextHeaders(),
canSetHeaders: false,
});
const user = isPayloadUser(authUser) ? authUser : null;
const userId = user?.id as number;
const locker = await ensureLockerStorage(payload, userId);
const lockerFull = (await payload.findByID({
collection: "locker-storages",
id: locker.id,
depth: 2,
overrideAccess: true,
})) as unknown as LockerStorage;
const loadoutsRes = await payload.find({
collection: "loadouts",
where: { ownerUser: { equals: userId } },
sort: "name",
limit: 100,
depth: 1,
});
const loadouts = loadoutsRes.docs as unknown as Loadout[];
const isManager = user ? (await hasPermission(payload, user, "locker-storages:update")) : false;
let assetsCatalog: Asset[] = [];
if (isManager) {
const assetsRes = await payload.find({
collection: "assets",
sort: "name",
limit: 500,
depth: 0,
});
assetsCatalog = assetsRes.docs as unknown as Asset[];
}
const grid = await getLockerGridDimensions(payload);
return (
<div className="p-5 flex flex-col gap-6">
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2">
<LockKeyholeIcon className="size-5 text-muted-foreground" />
<h1 className="text-lg font-semibold">Personal Locker</h1>
</div>
<p className="text-sm text-muted-foreground">
Store, organize, and equip your personal gear and loadouts.
</p>
</div>
<LockerView
locker={lockerFull}
gridWidth={grid.width}
gridHeight={grid.height}
loadouts={loadouts}
assetsCatalog={assetsCatalog}
isManager={isManager}
userName={user?.username ?? "Member"}
/>
</div>
);
}