Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit 90b3e43

Browse files
committed
chore: improve github auth flow
1 parent c50f2ca commit 90b3e43

File tree

3 files changed

+76
-63
lines changed

3 files changed

+76
-63
lines changed

src/pages/apps/new/github/NewGithubApp.spec.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ describe("~/pages/apps/new/github/NewGithubApp.tsx", () => {
6565
});
6666
});
6767

68-
describe("empty data", () => {
68+
describe("no authentication", () => {
6969
beforeEach(() => {
7070
mockFetchInstallations({
71+
status: 401,
7172
response: {
7273
accounts: [],
7374
},
@@ -78,7 +79,9 @@ describe("~/pages/apps/new/github/NewGithubApp.tsx", () => {
7879

7980
it("no connected accounts should display a warning", async () => {
8081
await waitFor(() => {
81-
expect(wrapper.getByText("No connected accounts found")).toBeTruthy();
82+
expect(
83+
wrapper.getByRole("button", { name: "Authenticate" })
84+
).toBeTruthy();
8285
});
8386
});
8487
});

src/pages/apps/new/github/NewGithubApp.tsx

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,41 @@ import Box from "@mui/material/Box";
55
import Link from "@mui/material/Link";
66
import Typography from "@mui/material/Typography";
77
import ArrowBack from "@mui/icons-material/ArrowBack";
8+
import Button from "@mui/material/Button";
89
import Card from "~/components/Card";
910
import CardHeader from "~/components/CardHeader";
1011
import RepoList from "../_components/RepoList";
1112
import Accounts from "../_components/Accounts";
1213
import { useFetchAccounts, useFetchRepos } from "./actions";
1314
import ConnectMoreRepos from "./ConnectMoreRepos";
1415

16+
function NeedsAuth() {
17+
const { loginOauth } = useContext(AuthContext);
18+
19+
return (
20+
<Typography
21+
sx={{
22+
display: "flex",
23+
justifyContent: "space-between",
24+
alignItems: "center",
25+
gap: 1,
26+
}}
27+
>
28+
<Box sx={{ flexGrow: 1 }} component="span">
29+
You need to authenticate to proceed.
30+
</Box>
31+
<Button
32+
variant="contained"
33+
color="secondary"
34+
type="button"
35+
onClick={() => loginOauth?.("github")}
36+
>
37+
Authenticate
38+
</Button>
39+
</Typography>
40+
);
41+
}
42+
1543
export default function NewGithubApp() {
1644
const { user } = useContext(AuthContext);
1745
const { details, loading: detailsLoading } = useContext(RootContext);
@@ -28,6 +56,7 @@ export default function NewGithubApp() {
2856
accounts,
2957
error: faError,
3058
loading: faLoading,
59+
needsAuth,
3160
} = useFetchAccounts({ refreshToken });
3261

3362
const {
@@ -60,57 +89,36 @@ export default function NewGithubApp() {
6089
}
6190
}, [accounts, user?.displayName]);
6291

63-
const loading = faLoading || frLoading;
6492
const hasAnyAccount = accounts && accounts.length > 0;
93+
const showNoRepo = frLoading === false && !repos?.length;
6594

6695
return (
6796
<Box maxWidth="md" sx={{ width: "100%", margin: "0 auto" }}>
6897
<Card
6998
sx={{ width: "100%", mb: 4 }}
7099
loading={faLoading}
71100
info={
72-
!hasAnyAccount ? (
73-
<>
74-
<Typography>No connected accounts found</Typography>
75-
<Typography>
76-
Click on "Connect More Repositories" to import from GitHub
77-
</Typography>
78-
</>
101+
needsAuth ? (
102+
<NeedsAuth />
79103
) : (
80-
repos?.length === 0 &&
81-
!loading && (
104+
showNoRepo && (
82105
<Typography>
83106
No repositories found. Try connecting more repositories.
84107
</Typography>
85108
)
86109
)
87110
}
88-
error={
89-
!hasAnyAccount ? undefined : !githubAccount && !detailsLoading ? (
90-
<>
91-
You don't seem to have a{" "}
92-
<Box component="code">GITHUB_APP_NAME</Box> configured.{" "}
93-
<Link
94-
href="https://www.stormkit.io/docs/self-hosting/authentication"
95-
rel="noreferrer noopener"
96-
target="_blank"
97-
>
98-
Learn more
99-
</Link>
100-
.
101-
</>
102-
) : (
103-
faError || frError
104-
)
105-
}
111+
error={!hasAnyAccount ? undefined : faError || frError}
106112
>
107113
<CardHeader
108114
actions={
109-
<ConnectMoreRepos
110-
setInstallationId={setInstallationId}
111-
setRefreshToken={setRefreshToken}
112-
openPopupURL={openPopupURL}
113-
/>
115+
!needsAuth && (
116+
<ConnectMoreRepos
117+
setInstallationId={setInstallationId}
118+
setRefreshToken={setRefreshToken}
119+
openPopupURL={openPopupURL}
120+
/>
121+
)
114122
}
115123
>
116124
<Typography>
@@ -124,7 +132,7 @@ export default function NewGithubApp() {
124132
</Typography>
125133
</CardHeader>
126134
<Box>
127-
{accounts?.length > 0 && (
135+
{!needsAuth && accounts?.length > 0 && (
128136
<Box>
129137
<Accounts
130138
accounts={accounts}
@@ -138,20 +146,26 @@ export default function NewGithubApp() {
138146
</Box>
139147
)}
140148

141-
<Box sx={{ mb: !githubAccount ? 4 : 0 }}>
142-
<RepoList
143-
repositories={repos}
144-
provider="github"
145-
isLoadingList={loading}
146-
isLoadingMore={isLoadingMore}
147-
hasNextPage={hasNextPage}
148-
onNextPage={() => setPage(page + 1)}
149-
onSearch={term => {
150-
setSearch(term);
151-
setRepos([]);
149+
{!needsAuth && (
150+
<Box
151+
sx={{
152+
mb: !githubAccount ? 4 : 0,
152153
}}
153-
/>
154-
</Box>
154+
>
155+
<RepoList
156+
repositories={repos}
157+
provider="github"
158+
isLoadingList={frLoading === true}
159+
isLoadingMore={isLoadingMore}
160+
hasNextPage={hasNextPage}
161+
onNextPage={() => setPage(page + 1)}
162+
onSearch={term => {
163+
setSearch(term);
164+
setRepos([]);
165+
}}
166+
/>
167+
</Box>
168+
)}
155169
</Box>
156170
</Card>
157171
</Box>

src/pages/apps/new/github/actions.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@ export const useFetchRepos = ({
1717
search = "",
1818
page = 1,
1919
}: UseFetchRepoProps) => {
20-
const [loading, setLoading] = useState(true);
20+
const [loading, setLoading] = useState<boolean | null>(null);
2121
const [isLoadingMore, setIsLoadingMore] = useState(true);
2222
const [error, setError] = useState<string>();
2323
const [repos, setRepos] = useState<Repo[]>([]);
2424
const [hasNextPage, setHasNextPage] = useState<boolean>();
2525

2626
useEffect(() => {
2727
if (!installationId) {
28-
setLoading(false);
2928
return;
3029
}
3130

@@ -67,22 +66,15 @@ export const useFetchRepos = ({
6766
};
6867
};
6968

70-
interface FetchAccountsReturnValue {
71-
error?: string;
72-
loading: boolean;
73-
accounts: Account[];
74-
}
75-
7669
interface FetchAccountProps {
7770
refreshToken?: number;
7871
}
7972

80-
export const useFetchAccounts = ({
81-
refreshToken,
82-
}: FetchAccountProps): FetchAccountsReturnValue => {
73+
export const useFetchAccounts = ({ refreshToken }: FetchAccountProps) => {
8374
const [error, setError] = useState<string>();
8475
const [loading, setLoading] = useState(true);
8576
const [accounts, setAccounts] = useState<Account[]>([]);
77+
const [needsAuth, setNeedsAuth] = useState(false);
8678

8779
useEffect(() => {
8880
setLoading(true);
@@ -92,14 +84,18 @@ export const useFetchAccounts = ({
9284
.then(({ accounts }) => {
9385
setAccounts(accounts);
9486
})
95-
.catch(e => {
96-
console.log(e);
87+
.catch(res => {
88+
if (res.status === 401) {
89+
setNeedsAuth(true);
90+
return;
91+
}
92+
9793
setError(errorMessage);
9894
})
9995
.finally(() => {
10096
setLoading(false);
10197
});
10298
}, [refreshToken]);
10399

104-
return { error, loading, accounts };
100+
return { error, loading, accounts, needsAuth };
105101
};

0 commit comments

Comments
 (0)