-
Notifications
You must be signed in to change notification settings - Fork 258
Expand file tree
/
Copy pathlayout.tsx
More file actions
138 lines (127 loc) · 5.22 KB
/
layout.tsx
File metadata and controls
138 lines (127 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { prisma } from "@/prisma";
import { auth } from "@/auth";
import { getOrgFromDomain } from "@/data/org";
import { isServiceError } from "@/lib/utils";
import { OnboardGuard } from "./components/onboardGuard";
import { UpgradeGuard } from "./components/upgradeGuard";
import { cookies, headers } from "next/headers";
import { getSelectorsByUserAgent } from "react-device-detect";
import { MobileUnsupportedSplashScreen } from "./components/mobileUnsupportedSplashScreen";
import { MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME } from "@/lib/constants";
import { SyntaxReferenceGuide } from "./components/syntaxReferenceGuide";
import { SyntaxGuideProvider } from "./components/syntaxGuideProvider";
import { IS_BILLING_ENABLED } from "@/ee/features/billing/stripe";
import { notFound, redirect } from "next/navigation";
import { getSubscriptionInfo } from "@/ee/features/billing/actions";
import { PendingApprovalCard } from "./components/pendingApproval";
import { SubmitJoinRequest } from "./components/submitJoinRequest";
import { hasEntitlement } from "@sourcebot/shared";
import { env } from "@/env.mjs";
import { GcpIapAuth } from "./components/gcpIapAuth";
import { getAnonymousAccessStatus, getMemberApprovalRequired } from "@/actions";
import { JoinOrganizationCard } from "@/app/components/joinOrganizationCard";
import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch";
interface LayoutProps {
children: React.ReactNode,
params: { domain: string }
}
export default async function Layout({
children,
params: { domain },
}: LayoutProps) {
const org = await getOrgFromDomain(domain);
if (!org) {
return notFound();
}
const session = await auth();
const anonymousAccessEnabled = hasEntitlement("anonymous-access") && await getAnonymousAccessStatus(domain);
// If the user is authenticated, we must check if they're a member of the org
if (session) {
const membership = await prisma.userToOrg.findUnique({
where: {
orgId_userId: {
orgId: org.id,
userId: session.user.id
}
},
include: {
user: true
}
});
// There's two reasons why a user might not be a member of an org:
// 1. The org doesn't require member approval, but the org was at max capacity when the user registered. In this case, we show them
// the join organization card to allow them to join the org if seat capacity is freed up. This card handles checking if the org has available seats.
// 2. The org requires member approval, and they haven't been approved yet. In this case, we allow them to submit a request to join the org.
if (!membership) {
const memberApprovalRequired = await getMemberApprovalRequired(domain);
if (!memberApprovalRequired) {
return (
<div className="min-h-screen flex items-center justify-center p-6">
<LogoutEscapeHatch className="absolute top-0 right-0 p-6" />
<JoinOrganizationCard />
</div>
)
} else {
const hasPendingApproval = await prisma.accountRequest.findFirst({
where: {
orgId: org.id,
requestedById: session.user.id
}
});
if (hasPendingApproval) {
return <PendingApprovalCard />
} else {
return <SubmitJoinRequest domain={domain} />
}
}
}
} else {
// If the user isn't authenticated and anonymous access isn't enabled, we need to redirect them to the login page.
if (!anonymousAccessEnabled) {
const ssoEntitlement = await hasEntitlement("sso");
if (ssoEntitlement && env.AUTH_EE_GCP_IAP_ENABLED && env.AUTH_EE_GCP_IAP_AUDIENCE) {
return <GcpIapAuth callbackUrl={`/${domain}`} />;
} else {
redirect('/login');
}
}
}
if (!org.isOnboarded) {
return (
<OnboardGuard>
{children}
</OnboardGuard>
)
}
if (IS_BILLING_ENABLED) {
const subscription = await getSubscriptionInfo(domain);
if (
subscription &&
(
isServiceError(subscription) ||
(subscription.status !== "active" && subscription.status !== "trialing")
)
) {
return (
<UpgradeGuard>
{children}
</UpgradeGuard>
)
}
}
const headersList = await headers();
const cookieStore = await cookies()
const userAgent = headersList.get('user-agent');
const { isMobile } = getSelectorsByUserAgent(userAgent ?? '');
if (isMobile && !cookieStore.has(MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME)) {
return (
<MobileUnsupportedSplashScreen />
)
}
return (
<SyntaxGuideProvider>
{children}
<SyntaxReferenceGuide />
</SyntaxGuideProvider>
)
}