Skip to content

Commit 8cf810f

Browse files
author
Rajat
committed
feat: reduced SSO providers to one, fixed SSO UI, stricter SSO SAML settings
1 parent 78e0a93 commit 8cf810f

File tree

21 files changed

+565
-361
lines changed

21 files changed

+565
-361
lines changed

apps/web/app/(with-contexts)/(with-layout)/login/login-form.tsx

Lines changed: 136 additions & 124 deletions
Large diffs are not rendered by default.

apps/web/app/(with-contexts)/(with-layout)/login/page.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import LoginForm from "./login-form";
44
import { headers } from "next/headers";
55
import { getAddressFromHeaders } from "@/app/actions";
66
import { FetchBuilder } from "@courselit/utils";
7+
import { error } from "@/services/logger";
78

89
export default async function LoginPage({
910
searchParams,
@@ -25,23 +26,23 @@ export default async function LoginPage({
2526
return (
2627
<LoginForm
2728
redirectTo={redirectTo}
28-
ssoProviders={await getSSOProviders(address)}
29+
ssoProvider={await getSSOProvider(address)}
2930
/>
3031
);
3132
}
3233

33-
export const getSSOProviders = async (
34+
export const getSSOProvider = async (
3435
backend: string,
3536
): Promise<
3637
| {
3738
providerId: string;
3839
domain: string;
39-
}[]
40+
}
4041
| undefined
4142
> => {
4243
const query = `
4344
query {
44-
ssoProviders: getSSOProviders {
45+
ssoProvider: getSSOProvider {
4546
providerId
4647
domain
4748
}
@@ -55,9 +56,10 @@ export const getSSOProviders = async (
5556

5657
try {
5758
const response = await fetch.exec();
58-
return response.ssoProviders;
59+
return response.ssoProvider;
5960
} catch (e: any) {
60-
console.log("getSSOProviders", e.message); // eslint-disable-line no-console
61-
return undefined;
61+
error(`Error in fetching SSO provider`, {
62+
stack: e.stack,
63+
});
6264
}
6365
};

apps/web/app/(with-contexts)/dashboard/(sidebar)/settings/apikeys/new/page.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,25 @@ import { checkPermission } from "@courselit/utils";
66
import { AddressContext, ProfileContext } from "@components/contexts";
77
import { UIConstants } from "@courselit/common-models";
88
import DashboardContent from "@components/admin/dashboard-content";
9-
import { SITE_SETTINGS_PAGE_HEADING } from "@ui-config/strings";
9+
import {
10+
APIKEY_NEW_HEADER,
11+
SITE_MISCELLANEOUS_SETTING_HEADER,
12+
SITE_SETTINGS_PAGE_HEADING,
13+
} from "@ui-config/strings";
1014
import dynamic from "next/dynamic";
1115
const { permissions } = UIConstants;
1216

1317
const ApikeyNew = dynamic(
1418
() => import("@/components/admin/settings/apikey/new"),
1519
);
1620

17-
const breadcrumbs = [{ label: SITE_SETTINGS_PAGE_HEADING, href: "#" }];
21+
const breadcrumbs = [
22+
{
23+
label: SITE_SETTINGS_PAGE_HEADING,
24+
href: `/dashboard/settings?tab=${SITE_MISCELLANEOUS_SETTING_HEADER}`,
25+
},
26+
{ label: APIKEY_NEW_HEADER, href: "#" },
27+
];
1828

1929
export default function Page() {
2030
const address = useContext(AddressContext);

apps/web/app/(with-contexts)/dashboard/(sidebar)/settings/sso/new/layout.tsx renamed to apps/web/app/(with-contexts)/dashboard/(sidebar)/settings/login-provider/sso/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { APIKEY_NEW_HEADER } from "@ui-config/strings";
1+
import { SSO_PROVIDER_HEADER } from "@ui-config/strings";
22
import type { Metadata, ResolvingMetadata } from "next";
33
import { ReactNode } from "react";
44

@@ -7,7 +7,7 @@ export async function generateMetadata(
77
parent: ResolvingMetadata,
88
): Promise<Metadata> {
99
return {
10-
title: `${APIKEY_NEW_HEADER} | ${(await parent)?.title?.absolute}`,
10+
title: `${SSO_PROVIDER_HEADER} | ${(await parent)?.title?.absolute}`,
1111
};
1212
}
1313

apps/web/app/(with-contexts)/dashboard/(sidebar)/settings/sso/new/page.tsx renamed to apps/web/app/(with-contexts)/dashboard/(sidebar)/settings/login-provider/sso/page.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,42 @@
33
import { useContext } from "react";
44
import LoadingScreen from "@components/admin/loading-screen";
55
import { checkPermission } from "@courselit/utils";
6-
import { AddressContext, ProfileContext } from "@components/contexts";
7-
import { UIConstants } from "@courselit/common-models";
6+
import {
7+
AddressContext,
8+
FeaturesContext,
9+
ProfileContext,
10+
} from "@components/contexts";
11+
import { Constants, UIConstants } from "@courselit/common-models";
812
import DashboardContent from "@components/admin/dashboard-content";
913
import {
1014
SITE_MISCELLANEOUS_SETTING_HEADER,
1115
SITE_SETTINGS_PAGE_HEADING,
12-
SSO_PROVIDER_NEW_HEADER,
16+
SSO_PROVIDER_HEADER,
1317
} from "@ui-config/strings";
1418
import dynamic from "next/dynamic";
19+
import { redirect } from "next/navigation";
1520
const { permissions } = UIConstants;
1621

17-
const SSOProviderNew = dynamic(
18-
() => import("@/components/admin/settings/sso/new"),
19-
);
22+
const SSOProvider = dynamic(() => import("@/components/admin/settings/sso"));
2023

2124
const breadcrumbs = [
2225
{
2326
label: SITE_SETTINGS_PAGE_HEADING,
2427
href: `/dashboard/settings?tab=${SITE_MISCELLANEOUS_SETTING_HEADER}`,
2528
},
26-
{ label: SSO_PROVIDER_NEW_HEADER, href: "#" },
29+
{ label: SSO_PROVIDER_HEADER, href: "#" },
2730
];
2831

2932
export default function Page() {
3033
const address = useContext(AddressContext);
3134
const { profile } = useContext(ProfileContext);
35+
const features = useContext(FeaturesContext);
36+
37+
if (!features.includes(Constants.Features.SSO)) {
38+
redirect(
39+
`/dashboard/settings?tab=${SITE_MISCELLANEOUS_SETTING_HEADER}`,
40+
);
41+
}
3242

3343
if (
3444
!profile ||
@@ -39,7 +49,7 @@ export default function Page() {
3949

4050
return (
4151
<DashboardContent breadcrumbs={breadcrumbs}>
42-
<SSOProviderNew address={address} />
52+
<SSOProvider address={address} />
4353
</DashboardContent>
4454
);
4555
}

apps/web/app/(with-contexts)/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,5 @@ const formatSiteInfo = (siteinfo?: SiteInfo) => ({
6262
razorpayKey: siteinfo?.razorpayKey || defaultState.siteinfo.razorpayKey,
6363
lemonsqueezyKey:
6464
siteinfo?.lemonsqueezyKey || defaultState.siteinfo.lemonsqueezyKey,
65+
logins: siteinfo?.logins || defaultState.siteinfo.logins,
6566
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { auth } from "@/auth";
2+
import { NextResponse } from "next/server";
3+
4+
export async function POST(req: Request) {
5+
return auth.handler(req);
6+
}
7+
8+
export async function GET(req: Request) {
9+
// Required: IdP-initiated flows redirect to this URL after POST
10+
return NextResponse.redirect(new URL("/", req.url));
11+
}

apps/web/auth.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ const config: any = {
7373
};
7474
}),
7575
sso({
76+
saml: {
77+
enableInResponseToValidation: true,
78+
requestTTL: 10 * 60 * 1000, // 10 minutes
79+
clockSkew: 5 * 60 * 1000, // 5 minutes
80+
requireTimestamps: true,
81+
},
7682
fields: {
7783
domain: "domain_string",
7884
},

apps/web/components/admin/dashboard-skeleton/nav-main.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
SidebarMenuSubItem,
1919
} from "@/components/ui/sidebar";
2020
import Link from "next/link";
21+
import { Chip } from "@courselit/components-library";
22+
import { BETA_LABEL } from "@ui-config/strings";
2123

2224
export function NavMain({
2325
items,
@@ -52,11 +54,7 @@ export function NavMain({
5254
<SidebarMenuButton tooltip={item.title}>
5355
{item.icon && <item.icon />}
5456
<span>{item.title}</span>
55-
{item.beta && (
56-
<span className="ml-2 rounded bg-gray-200 px-1 py-0.5 text-xs font-medium text-gray-700">
57-
Beta
58-
</span>
59-
)}
57+
{item.beta && <Chip>{BETA_LABEL}</Chip>}
6058
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
6159
</SidebarMenuButton>
6260
</CollapsibleTrigger>
@@ -94,11 +92,7 @@ export function NavMain({
9492
<Link href={item.url}>
9593
{item.icon && <item.icon />}
9694
<span>{item.title}</span>
97-
{item.beta && (
98-
<span className="ml-2 rounded bg-gray-200 px-1 py-0.5 text-xs font-medium text-gray-700">
99-
Beta
100-
</span>
101-
)}
95+
{item.beta && <Chip>{BETA_LABEL}</Chip>}
10296
</Link>
10397
</SidebarMenuButton>
10498
</SidebarMenuItem>

apps/web/components/admin/settings/apikey/new.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { Address } from "@courselit/common-models";
22
import {
3-
Button,
3+
// Button,
44
Form,
55
FormField,
6-
IconButton,
76
useToast,
87
} from "@courselit/components-library";
98
import { FetchBuilder } from "@courselit/utils";
@@ -22,6 +21,7 @@ import {
2221
import Link from "next/link";
2322
import { FormEvent, useState } from "react";
2423
import { Clipboard } from "@courselit/icons";
24+
import { Button } from "@components/ui/button";
2525

2626
interface NewApikeyProps {
2727
address: Address;
@@ -107,13 +107,14 @@ export default function NewApikey({
107107
</p>
108108
<div className="flex gap-2 mb-4">
109109
<FormField name="apikey" value={apikey} disabled />
110-
<IconButton
110+
<Button
111111
className="px-3"
112112
onClick={copyApikey}
113-
variant="soft"
113+
size="icon"
114+
variant="outline"
114115
>
115116
<Clipboard fontSize="small" />
116-
</IconButton>
117+
</Button>
117118
</div>
118119
<Link href={`/dashboard/settings?tab=API%20Keys`}>
119120
<Button>{BUTTON_DONE_TEXT}</Button>

0 commit comments

Comments
 (0)