1
0
Fork 0

feat(intelligence): gate intelligence content behind the intelligence qualification

- Add hasIntelligenceQualification access helper
- Redirect non-qualified users away from /intelligence
- Hide mission and campaign widgets on the dashboard for non-qualified users
- Guard hasLogisticsQualification against a null user
This commit is contained in:
Jason Fraley 2026-08-11 23:25:27 -04:00
parent c81036bd82
commit caae76e6b2
4 changed files with 49 additions and 3 deletions

View file

@ -1,7 +1,10 @@
import config from "@payload-config";
import { getPayload } from "payload";
import { headers as nextHeaders } from "next/headers";
import { redirect } from "next/navigation";
import Link from "next/link";
import type { Campaign, Mission, Faction } from "@/payload-types";
import { hasIntelligenceQualification } from "@/utils/access-control/hasIntelligenceQualification";
import { CrosshairIcon, ArrowRightIcon } from "lucide-react";
import {
Item,
@ -18,6 +21,12 @@ export const metadata = {
export default async function IntelligenceOverviewPage() {
const payload = await getPayload({ config });
const headers = await nextHeaders();
const { user } = await payload.auth({ headers, canSetHeaders: false });
if (!user || !(await hasIntelligenceQualification(payload, user))) {
redirect("/");
}
const [campaignsRes, factionsRes] = await Promise.all([
payload

View file

@ -3,6 +3,7 @@ import { getPayload } from "payload";
import { headers as nextHeaders } from "next/headers";
import type { User, Rank, Media, Assignment, Campaign, Map, GameStructure } from "@/payload-types";
import { resolveLevel } from "@/utils/xp/resolveLevel";
import { hasIntelligenceQualification } from "@/utils/access-control/hasIntelligenceQualification";
import { ProfileSummary } from "@/components/frontend/dashboard/ProfileSummary";
import { MissionBriefing } from "@/components/frontend/dashboard/MissionBriefing";
import { RecentEvents } from "@/components/frontend/dashboard/RecentEvents";
@ -19,6 +20,8 @@ export default async function HomePage() {
const userId = user.id;
const hasIntelligence = await hasIntelligenceQualification(payload, user).catch(() => false);
const [profileRes, experienceRes, assignmentRes] = await Promise.all([
payload.find({
collection: "profiles",
@ -229,8 +232,8 @@ export default async function HomePage() {
{/* ── Right Sidebar (1/3) ─────────────────────────── */}
<div className="flex flex-col gap-4">
<UpcomingMissions missions={upcomingMissions} />
<ActiveCampaigns campaigns={activeCampaigns} />
{hasIntelligence && <UpcomingMissions missions={upcomingMissions} />}
{hasIntelligence && <ActiveCampaigns campaigns={activeCampaigns} />}
</div>
</div>
</div>

View file

@ -0,0 +1,32 @@
import type { Payload } from "payload";
export async function hasIntelligenceQualification(
payload: Payload,
user: { id: number | string; roles?: unknown } | null | undefined,
): Promise<boolean> {
if (!user) return false;
const roles = user.roles as string[] | undefined;
if (roles?.includes("developer") || roles?.includes("admin")) {
return true;
}
const profile = (await payload.find({
collection: "profiles",
where: { user: { equals: user.id as number } },
depth: 4,
limit: 1,
})) as unknown as { docs: Array<any> };
const userProfile = profile.docs[0];
if (!userProfile || !userProfile.progression || !userProfile.progression.qualifications) {
return false;
}
return userProfile.progression.qualifications.some((qualification: any) => {
return typeof qualification === "string"
? qualification.toLowerCase() === "intelligence"
: qualification?.name?.toLowerCase() === "intelligence";
});
}

View file

@ -9,6 +9,8 @@ export async function hasLogisticsQualification(
payload: Payload,
user: { id: number | string; roles?: unknown } | null | undefined,
): Promise<boolean> {
if (!user) return false;
const roles = user.roles as string[] | undefined;
if (roles?.includes("developer") || roles?.includes("admin")) {
return true;
@ -16,7 +18,7 @@ export async function hasLogisticsQualification(
const profileRes = await payload.find({
collection: "profiles",
where: { user: { equals: user.id } },
where: { user: { equals: user.id as number } },
limit: 1,
depth: 1,
select: {