Skip to content

Commit fb55c84

Browse files
authored
Merge pull request #7601 from sagemathinc/sso-login-homepage-7557
"allow email signup" = false → list all SSO options on home page
2 parents 6e6eded + b1104e5 commit fb55c84

File tree

10 files changed

+108
-65
lines changed

10 files changed

+108
-65
lines changed

src/packages/database/settings/customize.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export interface Customize {
4949
sandboxProjectsEnabled?: boolean;
5050
sandboxProjectId?: string;
5151
verifyEmailAddresses?: boolean;
52-
strategies: Strategy[];
52+
strategies?: Strategy[];
5353
openaiEnabled?: boolean;
5454
googleVertexaiEnabled?: boolean;
5555
mistralEnabled?: boolean;

src/packages/database/settings/get-sso-strategies.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import getPool from "@cocalc/database/pool";
7-
import { Strategy } from "@cocalc/util/types/sso";
7+
import type { Strategy } from "@cocalc/util/types/sso";
88
import { ssoDispayedName } from "@cocalc/util/auth";
99

1010
/** Returns an array of public info about strategies.

src/packages/next/components/account/config/account/sso.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
44
*/
55

6+
import { useRouter } from "next/router";
7+
import { ReactNode, useState } from "react";
8+
69
import { Icon } from "@cocalc/frontend/components/icon";
710
import { len } from "@cocalc/util/misc";
811
import { COLORS } from "@cocalc/util/theme";
@@ -16,8 +19,6 @@ import SiteName from "components/share/site-name";
1619
import apiPost from "lib/api/post";
1720
import useAPI from "lib/hooks/api";
1821
import useEditTable from "lib/hooks/edit-table";
19-
import { useRouter } from "next/router";
20-
import { ReactNode, useState } from "react";
2122
import register from "../register";
2223

2324
interface Data {
@@ -36,7 +37,7 @@ register({
3637
{
3738
accounts: { passports: null },
3839
},
39-
{ noSave: true }
40+
{ noSave: true },
4041
);
4142

4243
const hasPassword = useAPI("auth/has-password");
@@ -75,7 +76,7 @@ register({
7576

7677
const passports = edited.passports ?? {};
7778
const linkedNames = Object.keys(passports).map(
78-
(name) => name.split("-")[0]
79+
(name) => name.split("-")[0],
7980
);
8081

8182
return (
@@ -106,7 +107,7 @@ register({
106107
or{" "}
107108
<A href="/config/account/delete">delete your account</A>
108109
.
109-
</>
110+
</>,
110111
);
111112
return;
112113
}
@@ -169,7 +170,7 @@ function Unlink({
169170
key={name}
170171
strategy={strategy}
171172
onUnlink={() => onUnlink(name, strategy)}
172-
/>
173+
/>,
173174
);
174175
break;
175176
}

src/packages/next/components/auth/sso.tsx

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
44
*/
55

6-
import { Alert, Avatar, Tooltip, Typography } from "antd";
6+
import { Alert, Avatar, Space, Tooltip, Typography } from "antd";
77
import { useRouter } from "next/router";
88
import { join } from "path";
99
import { CSSProperties, ReactNode, useMemo } from "react";
@@ -24,6 +24,8 @@ interface SSOProps {
2424
size?: number;
2525
style?: CSSProperties;
2626
header?: ReactNode;
27+
showAll?: boolean;
28+
showName?: boolean;
2729
}
2830

2931
export function getLink(strategy: string, target?: string): string {
@@ -39,12 +41,12 @@ export function getLink(strategy: string, target?: string): string {
3941
}
4042

4143
export default function SSO(props: SSOProps) {
42-
const { size, style, header } = props;
44+
const { size = 60, style, header, showAll = false, showName = false } = props;
4345
const { strategies } = useCustomize();
4446
const ssoHREF = useSSOHref("sso");
4547

4648
const havePrivateSSO: boolean = useMemo(() => {
47-
return strategies?.some((s) => !s.public) ?? false;
49+
return showAll ? false : strategies?.some((s) => !s.public) ?? false;
4850
}, [strategies]);
4951

5052
if (strategies == null) {
@@ -68,35 +70,43 @@ export default function SSO(props: SSOProps) {
6870
};
6971

7072
return (
71-
<a href={ssoHREF}>
72-
{"Institutional Single Sign-On: "}
73-
<StrategyAvatar key={"sso"} strategy={sso} size={size ?? 60} />
74-
</a>
73+
<div style={{ marginLeft: "-5px", marginTop: "10px" }}>
74+
<a href={ssoHREF}>
75+
{"Institutional Single Sign-On: "}
76+
<StrategyAvatar key={"sso"} strategy={sso} size={size} />
77+
</a>
78+
</div>
7579
);
7680
}
7781

7882
function renderStrategies() {
7983
if (strategies == null) return;
80-
return strategies
81-
.filter((s) => s.public || s.doNotHide)
82-
.map((strategy) => (
83-
<StrategyAvatar
84-
key={strategy.name}
85-
strategy={strategy}
86-
size={size ?? 60}
87-
/>
88-
));
84+
const s = strategies
85+
.filter((s) => showAll || s.public || s.doNotHide)
86+
.map((strategy) => {
87+
return (
88+
<StrategyAvatar
89+
key={strategy.name}
90+
strategy={strategy}
91+
size={size}
92+
showName={showName}
93+
/>
94+
);
95+
});
96+
return (
97+
<div style={{ marginLeft: "-5px", textAlign: "center" }}>
98+
{showName ? <Space wrap>{s}</Space> : s}
99+
</div>
100+
);
89101
}
90102

91103
// The -5px is to offset the initial avatar image, since they
92104
// all have a left margin.
93105
return (
94106
<div style={{ ...style }}>
95107
{header}
96-
<div style={{ marginLeft: "-5px" }}>{renderStrategies()}</div>
97-
<div style={{ marginLeft: "-5px", marginTop: "10px" }}>
98-
{renderPrivateSSO()}
99-
</div>
108+
{renderStrategies()}
109+
{renderPrivateSSO()}
100110
</div>
101111
);
102112
}

src/packages/next/components/landing/cocalc-com-features.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import { Button, Col, Grid, Row } from "antd";
77
import { join } from "path";
88
import { useEffect, useState } from "react";
9+
910
import { SOFTWARE_ENVIRONMENT_ICON } from "@cocalc/frontend/project/settings/software-consts";
11+
import { DOC_AI } from "@cocalc/util/consts/ui";
1012
import { COLORS } from "@cocalc/util/theme";
1113
import Path from "components/app/path";
1214
import DemoCell from "components/demo-cell";
@@ -26,7 +28,6 @@ import assignments from "public/features/cocalc-course-assignments-2019.png";
2628
import RTC from "public/features/cocalc-real-time-jupyter.png";
2729
import ComputeServers from "./compute-servers";
2830
import { LANDING_HEADER_LEVEL } from "./constants";
29-
import { DOC_AI } from "@cocalc/util/consts/ui";
3031

3132
// NOTE: This component is only rendered if the onCoCalcCom customization variable is "true"
3233
export function CoCalcComFeatures() {

src/packages/next/components/landing/sign-in.tsx

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
*/
55

66
import { Button } from "antd";
7+
import { useRouter } from "next/router";
78
import { join } from "path";
89
import { CSSProperties, ReactNode } from "react";
10+
11+
import SSO from "components/auth/sso";
912
import { Paragraph } from "components/misc";
1013
import basePath from "lib/base-path";
1114
import { useCustomize } from "lib/customize";
12-
import { useRouter } from "next/router";
1315

1416
interface Props {
1517
startup?: ReactNode; // customize the button, e.g. "Start Jupyter Now".
@@ -24,9 +26,10 @@ const STYLE: CSSProperties = {
2426
} as const;
2527

2628
export default function SignIn({ startup, hideFree, style }: Props) {
27-
const { anonymousSignup, siteName, account } = useCustomize();
29+
const { anonymousSignup, siteName, account, emailSignup } = useCustomize();
2830
style = { ...STYLE, ...style };
2931
const router = useRouter();
32+
3033
if (account != null) {
3134
return (
3235
<Paragraph style={style}>
@@ -41,6 +44,47 @@ export default function SignIn({ startup, hideFree, style }: Props) {
4144
</Paragraph>
4245
);
4346
}
47+
48+
// if email signup is not allowed, we show all SSO options -- #7557
49+
function renderAccountRegistration() {
50+
if (emailSignup) {
51+
return (
52+
<>
53+
<Button
54+
size="large"
55+
style={{ margin: "10px" }}
56+
title={"Create a new account."}
57+
onClick={() => router.push("/auth/sign-up")}
58+
>
59+
Sign Up
60+
</Button>
61+
<Button
62+
size="large"
63+
style={{ margin: "10px" }}
64+
title={
65+
"Either create a new account or sign into an existing account."
66+
}
67+
onClick={() => router.push("/auth/sign-in")}
68+
>
69+
Sign In
70+
</Button>
71+
</>
72+
);
73+
} else {
74+
return (
75+
<SSO
76+
header={
77+
<Paragraph style={{ fontSize: "18px", fontWeight: "bold" }}>
78+
Sign in
79+
</Paragraph>
80+
}
81+
showAll={true}
82+
showName={true}
83+
/>
84+
);
85+
}
86+
}
87+
4488
return (
4589
<Paragraph style={style}>
4690
{anonymousSignup && (
@@ -54,27 +98,12 @@ export default function SignIn({ startup, hideFree, style }: Props) {
5498
Try&nbsp;{startup ?? siteName}&nbsp;Now
5599
</Button>
56100
)}
57-
<Button
58-
size="large"
59-
style={{ margin: "10px" }}
60-
title={"Create a new account."}
61-
onClick={() => router.push("/auth/sign-up")}
62-
>
63-
Sign Up
64-
</Button>
65-
<Button
66-
size="large"
67-
style={{ margin: "10px" }}
68-
title={"Either create a new account or sign into an existing account."}
69-
onClick={() => router.push("/auth/sign-in")}
70-
>
71-
Sign In
72-
</Button>
73-
{!hideFree && (
101+
{renderAccountRegistration()}
102+
{!hideFree ? (
74103
<div style={{ padding: "15px 0 0 0" }}>
75104
Start free today. Upgrade later.
76105
</div>
77-
)}
106+
) : undefined}
78107
</Paragraph>
79108
);
80109
}

src/packages/next/components/videos.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import { Carousel } from "antd";
2-
import { Paragraph } from "components/misc";
32
import { useState } from "react";
4-
import A from "components/misc/A";
3+
54
import { Icon } from "@cocalc/frontend/components/icon";
5+
import { Paragraph } from "components/misc";
6+
import A from "components/misc/A";
67

7-
interface Video {
8+
export interface Video {
89
id: string;
910
title: string;
1011
}
1112

12-
export default function Videos({ videos }: { videos: Video[] }) {
13+
export default function Videos({ videos }: { videos: Readonly<Video[]> }) {
1314
const [current, setCurrent] = useState<number>(0);
1415
let n = -1;
1516
return (

src/packages/next/lib/customize.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import { createContext, useContext } from "react";
7+
78
import type { Customize as ServerCustomize } from "@cocalc/database/settings/customize";
89

910
interface EnabledPageBranch {
@@ -12,12 +13,12 @@ interface EnabledPageBranch {
1213

1314
interface EnabledPageTree extends EnabledPageBranch {
1415
auth: {
15-
try: boolean | undefined,
16+
try: boolean | undefined;
1617
};
1718
about: {
18-
index: boolean | undefined,
19-
events: boolean | undefined,
20-
team: boolean | undefined,
19+
index: boolean | undefined;
20+
events: boolean | undefined;
21+
team: boolean | undefined;
2122
};
2223
compute: boolean | undefined;
2324
contact: boolean | undefined;
@@ -31,7 +32,7 @@ interface EnabledPageTree extends EnabledPageBranch {
3132
policies: {
3233
index: boolean | undefined;
3334
imprint: boolean | undefined;
34-
}
35+
};
3536
pricing: boolean | undefined;
3637
share: boolean | undefined;
3738
software: boolean | undefined;
@@ -64,7 +65,6 @@ interface Customize extends ServerCustomize {
6465
serverTime?: number; // the time on the server, in milliseconds since the epoch
6566
openaiEnabled?: boolean; // backend is configured to provide openai integration.
6667
googleVertexaiEnabled?: boolean; // if enabled, e.g. Google Gemini is available
67-
6868
jupyterApiEnabled?: boolean; // backend configured to use a pool of projects for sandboxed ephemeral jupyter code execution
6969
computeServersEnabled?: boolean; // backend configured to run on external compute servers
7070
enabledPages?: EnabledPageTree; // tree structure which specifies supported routes for this install

src/packages/next/lib/with-customize.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export default async function withCustomize(
2727
revalidate?: number;
2828
context: any;
2929
},
30-
options: Options = {}
30+
options: Options = {},
3131
) {
3232
let customize: CustomizeType;
3333
try {

0 commit comments

Comments
 (0)