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:
parent
c81036bd82
commit
caae76e6b2
4 changed files with 49 additions and 3 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
32
src/utils/access-control/hasIntelligenceQualification.ts
Normal file
32
src/utils/access-control/hasIntelligenceQualification.ts
Normal 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";
|
||||
});
|
||||
}
|
||||
|
|
@ -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: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue