Skip to content

Commit 1337e59

Browse files
authored
[dashboard] handle context resolution errors9 (#17159)
1 parent b98b5e7 commit 1337e59

File tree

8 files changed

+199
-143
lines changed

8 files changed

+199
-143
lines changed

components/dashboard/src/Login.tsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { getURLHash } from "./utils";
2424
import ErrorMessage from "./components/ErrorMessage";
2525
import { Heading1, Heading2, Subheading } from "./components/typography/headings";
2626
import { SSOLoginForm } from "./login/SSOLoginForm";
27+
import { useAuthProviders } from "./data/auth-providers/auth-provider-query";
2728

2829
function Item(props: { icon: string; iconSize?: string; text: string }) {
2930
const iconSize = props.iconSize || 28;
@@ -55,9 +56,8 @@ export const Login: FC<LoginProps> = ({ onLoggedIn }) => {
5556

5657
const urlHash = useMemo(() => getURLHash(), []);
5758

58-
const [authProviders, setAuthProviders] = useState<AuthProviderInfo[]>([]);
59+
const authProviders = useAuthProviders();
5960
const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined);
60-
const [providerFromContext, setProviderFromContext] = useState<AuthProviderInfo>();
6161
const [hostFromContext, setHostFromContext] = useState<string | undefined>();
6262
const [repoPathname, setRepoPathname] = useState<string | undefined>();
6363

@@ -73,18 +73,10 @@ export const Login: FC<LoginProps> = ({ onLoggedIn }) => {
7373
}
7474
}, [urlHash]);
7575

76-
useEffect(() => {
77-
(async () => {
78-
setAuthProviders(await getGitpodService().server.getAuthProviders());
79-
})();
80-
}, []);
81-
82-
useEffect(() => {
83-
if (hostFromContext && authProviders) {
84-
const providerFromContext = authProviders.find((provider) => provider.host === hostFromContext);
85-
setProviderFromContext(providerFromContext);
86-
}
87-
}, [hostFromContext, authProviders]);
76+
let providerFromContext: AuthProviderInfo | undefined;
77+
if (hostFromContext && authProviders.data) {
78+
providerFromContext = authProviders.data.find((provider) => provider.host === hostFromContext);
79+
}
8880

8981
const showWelcome = !hasLoggedInBefore() && !hasVisitedMarketingWebsiteBefore() && !urlHash.startsWith("https://");
9082

@@ -214,15 +206,15 @@ export const Login: FC<LoginProps> = ({ onLoggedIn }) => {
214206
<button
215207
key={"button" + providerFromContext.host}
216208
className="btn-login flex-none w-56 h-10 p-0 inline-flex"
217-
onClick={() => openLogin(providerFromContext.host)}
209+
onClick={() => openLogin(providerFromContext!.host)}
218210
>
219211
{iconForAuthProvider(providerFromContext.authProviderType)}
220212
<span className="pt-2 pb-2 mr-3 text-sm my-auto font-medium truncate overflow-ellipsis">
221213
Continue with {simplifyProviderName(providerFromContext.host)}
222214
</span>
223215
</button>
224216
) : (
225-
authProviders.map((ap) => (
217+
authProviders.data?.map((ap) => (
226218
<button
227219
key={"button" + ap.host}
228220
className="btn-login flex-none w-56 h-10 p-0 inline-flex"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { AuthProviderInfo } from "@gitpod/gitpod-protocol";
8+
import { useQuery } from "@tanstack/react-query";
9+
import { getGitpodService } from "../../service/service";
10+
11+
export const useAuthProviders = () => {
12+
return useQuery<AuthProviderInfo[]>({
13+
queryKey: ["auth-providers"],
14+
queryFn: async () => {
15+
return await getGitpodService().server.getAuthProviders();
16+
},
17+
});
18+
};

components/dashboard/src/data/workspaces/resolve-context-query.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ import { useQuery } from "@tanstack/react-query";
99
import { getGitpodService } from "../../service/service";
1010

1111
export function useWorkspaceContext(contextUrl?: string) {
12-
const query = useQuery<WorkspaceContext | null, Error>(["workspace-context", contextUrl], () => {
13-
if (!contextUrl) {
14-
return null;
15-
}
16-
return getGitpodService().server.resolveContext(contextUrl);
17-
});
12+
const query = useQuery<WorkspaceContext | null, Error>(
13+
["workspace-context", contextUrl],
14+
() => {
15+
if (!contextUrl) {
16+
return null;
17+
}
18+
return getGitpodService().server.resolveContext(contextUrl);
19+
},
20+
{
21+
retry: false,
22+
},
23+
);
1824
return query;
1925
}

components/dashboard/src/projects/NewProject.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { getGitpodService, gitpodHostUrl } from "../service/service";
2323
import { UserContext } from "../user-context";
2424
import { projectsPathNew } from "./projects.routes";
2525
import { Heading1, Subheading } from "../components/typography/headings";
26+
import { useAuthProviders } from "../data/auth-providers/auth-provider-query";
2627

2728
export default function NewProject() {
2829
const currentTeam = useCurrentOrg()?.data;
@@ -39,24 +40,25 @@ export default function NewProject() {
3940

4041
const [project, setProject] = useState<Project | undefined>();
4142

42-
const [authProviders, setAuthProviders] = useState<AuthProviderInfo[]>([]);
43+
const authProviders = useAuthProviders();
4344
const [isGitHubAppEnabled, setIsGitHubAppEnabled] = useState<boolean>();
4445
const [isGitHubWebhooksUnauthorized, setIsGitHubWebhooksUnauthorized] = useState<boolean>();
4546

4647
useEffect(() => {
4748
const { server } = getGitpodService();
48-
Promise.all([
49-
server.getAuthProviders().then((v) => () => setAuthProviders(v)),
50-
server.isGitHubAppEnabled().then((v) => () => setIsGitHubAppEnabled(v)),
51-
]).then((setters) => setters.forEach((s) => s()));
49+
Promise.all([server.isGitHubAppEnabled().then((v) => () => setIsGitHubAppEnabled(v))]).then((setters) =>
50+
setters.forEach((s) => s()),
51+
);
5252
}, []);
5353

5454
useEffect(() => {
55-
if (user && authProviders && selectedProviderHost === undefined) {
55+
if (user && authProviders.data && selectedProviderHost === undefined) {
5656
for (let i = user.identities.length - 1; i >= 0; i--) {
5757
const candidate = user.identities[i];
5858
if (candidate) {
59-
const authProvider = authProviders.find((ap) => ap.authProviderId === candidate.authProviderId);
59+
const authProvider = authProviders.data.find(
60+
(ap) => ap.authProviderId === candidate.authProviderId,
61+
);
6062
const host = authProvider?.host;
6163
if (host) {
6264
setSelectedProviderHost(host);
@@ -72,7 +74,7 @@ export default function NewProject() {
7274
if (!authProviders || !selectedProviderHost || isGitHubAppEnabled) {
7375
return;
7476
}
75-
const ap = authProviders.find((ap) => ap.host === selectedProviderHost);
77+
const ap = authProviders.data?.find((ap) => ap.host === selectedProviderHost);
7678
if (!ap || ap.authProviderType !== "GitHub") {
7779
return;
7880
}
@@ -164,7 +166,7 @@ export default function NewProject() {
164166
};
165167

166168
const authorize = () => {
167-
const ap = authProviders.find((ap) => ap.host === selectedProviderHost);
169+
const ap = authProviders.data?.find((ap) => ap.host === selectedProviderHost);
168170
if (!ap) {
169171
return;
170172
}
@@ -487,7 +489,7 @@ export default function NewProject() {
487489
}
488490

489491
if (showGitProviders) {
490-
return <GitProviders onHostSelected={onGitProviderSeleted} authProviders={authProviders} />;
492+
return <GitProviders onHostSelected={onGitProviderSeleted} authProviders={authProviders.data || []} />;
491493
}
492494

493495
return renderRepos();

components/dashboard/src/start/CreateWorkspace.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { UsageLimitReachedModal } from "../components/UsageLimitReachedModal";
3030
import { StartWorkspaceOptions } from "./start-workspace-options";
3131
import { useLocation } from "react-router";
3232
import { useCurrentOrg } from "../data/organizations/orgs-query";
33+
import { useAuthProviders } from "../data/auth-providers/auth-provider-query";
3334

3435
export interface CreateWorkspaceProps {
3536
contextUrl: string;
@@ -382,6 +383,7 @@ export function LimitReachedOutOfHours() {
382383

383384
export function RepositoryNotFoundView(p: { error: StartWorkspaceError }) {
384385
const [statusMessage, setStatusMessage] = useState<React.ReactNode>();
386+
const authProviders = useAuthProviders();
385387
const { host, owner, repoName, userIsOwner, userScopes, lastUpdate } = p.error.data;
386388
const repoFullName = owner && repoName ? `${owner}/${repoName}` : "";
387389

@@ -394,7 +396,7 @@ export function RepositoryNotFoundView(p: { error: StartWorkspaceError }) {
394396
console.log("userScopes", userScopes);
395397
console.log("lastUpdate", lastUpdate);
396398

397-
const authProvider = (await getGitpodService().server.getAuthProviders()).find((p) => p.host === host);
399+
const authProvider = authProviders.data?.find((p) => p.host === host);
398400
if (!authProvider) {
399401
return;
400402
}

components/dashboard/src/user-settings/Integrations.tsx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { AuthEntryItem } from "./AuthEntryItem";
2929
import { IntegrationEntryItem } from "./IntegrationItemEntry";
3030
import { PageWithSettingsSubMenu } from "./PageWithSettingsSubMenu";
3131
import { SelectAccountModal } from "./SelectAccountModal";
32+
import { useAuthProviders } from "../data/auth-providers/auth-provider-query";
3233

3334
export default function Integrations() {
3435
return (
@@ -45,7 +46,7 @@ export default function Integrations() {
4546
function GitProviders() {
4647
const { user, setUser } = useContext(UserContext);
4748

48-
const [authProviders, setAuthProviders] = useState<AuthProviderInfo[]>([]);
49+
const authProviders = useAuthProviders();
4950
const [allScopes, setAllScopes] = useState<Map<string, string[]>>(new Map());
5051
const [disconnectModal, setDisconnectModal] = useState<{ provider: AuthProviderInfo } | undefined>(undefined);
5152
const [editModal, setEditModal] = useState<
@@ -54,20 +55,11 @@ function GitProviders() {
5455
const [selectAccountModal, setSelectAccountModal] = useState<SelectAccountPayload | undefined>(undefined);
5556
const [errorMessage, setErrorMessage] = useState<string | undefined>();
5657

57-
useEffect(() => {
58-
updateAuthProviders();
59-
// eslint-disable-next-line react-hooks/exhaustive-deps
60-
}, []);
61-
62-
const updateAuthProviders = useCallback(async () => {
63-
setAuthProviders(await getGitpodService().server.getAuthProviders());
64-
}, []);
65-
6658
const updateCurrentScopes = useCallback(async () => {
6759
if (user) {
6860
const scopesByProvider = new Map<string, string[]>();
6961
const connectedProviders = user.identities.map((i) =>
70-
authProviders.find((ap) => ap.authProviderId === i.authProviderId),
62+
authProviders.data?.find((ap) => ap.authProviderId === i.authProviderId),
7163
);
7264
for (let provider of connectedProviders) {
7365
if (!provider) {
@@ -106,7 +98,7 @@ function GitProviders() {
10698
separator: true,
10799
});
108100
}
109-
const connectedWithSecondProvider = authProviders.some(
101+
const connectedWithSecondProvider = authProviders.data?.some(
110102
(p) => p.authProviderId !== provider.authProviderId && isConnected(p.authProviderId),
111103
);
112104
if (connectedWithSecondProvider) {
@@ -340,8 +332,8 @@ function GitProviders() {
340332
</a>
341333
</Subheading>
342334
<ItemsList className="pt-6">
343-
{authProviders &&
344-
authProviders.map((ap) => (
335+
{authProviders.data &&
336+
authProviders.data.map((ap) => (
345337
<AuthEntryItem
346338
key={ap.authProviderId}
347339
isConnected={isConnected}

0 commit comments

Comments
 (0)