Skip to content

Commit

Permalink
Merge pull request #7 from fluentci-io/feat/setup-clerk
Browse files Browse the repository at this point in the history
feat: migrate from Firebase Auth to Clerk
  • Loading branch information
tsirysndr authored Jul 6, 2024
2 parents 45eec4f + 16c3b29 commit 092aade
Show file tree
Hide file tree
Showing 15 changed files with 244 additions and 165 deletions.
Binary file modified webui/bun.lockb
Binary file not shown.
13 changes: 8 additions & 5 deletions webui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
"scripts": {
"dev": "vite --config vite.dev.config.ts",
"local": "VITE_APP_API_URL=http://localhost:8787/graphql vite --config vite.dev.config.ts",
"prod": "VITE_APP_API_URL=https://api.fluentci.io/graphql vite --config vite.dev.config.ts",
"prod": "VITE_APP_API_URL=https://api.fluentci.io/graphql VITE_CLERK_PUBLISHABLE_KEY=pk_live_Y2xlcmsuZmx1ZW50Y2kuaW8k vite --config vite.dev.config.ts",
"start": "electron .",
"build:web": "vite build --config vite.dev.config.ts",
"build": "tsc && vite build && electron-builder",
"build:prod": "VITE_APP_API_URL=https://api.fluentci.io/graphql tsc && vite build --config vite.dev.config.ts",
"build:prod": "VITE_APP_API_URL=https://api.fluentci.io/graphql VITE_CLERK_PUBLISHABLE_KEY=pk_live_Y2xlcmsuZmx1ZW50Y2kuaW8k tsc && vite build --config vite.dev.config.ts",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
Expand All @@ -30,6 +30,7 @@
"@apollo/client": "^3.9.4",
"@apollo/react-components": "^4.0.0",
"@chakra-ui/react": "^2.8.2",
"@clerk/clerk-react": "^5.2.7",
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@fontsource/inconsolata": "^5.0.16",
Expand Down Expand Up @@ -60,14 +61,12 @@
"dayjs": "^1.11.10",
"electron-squirrel-startup": "^1.0.1",
"electron-updater": "^6.1.8",
"firebase": "^10.12.2",
"graphql": "15.7.2",
"nanoid": "^5.0.7",
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-content-loader": "^7.0.0",
"react-dom": "^18.2.0",
"react-firebase-hooks": "^5.1.1",
"react-hook-form": "^7.51.4",
"react-router-dom": "^6.22.0",
"react-use-websocket": "^4.8.1",
Expand Down Expand Up @@ -120,5 +119,9 @@
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5",
"vitest": "^1.6.0"
}
},
"trustedDependencies": [
"@clerk/shared",
"protobufjs"
]
}
97 changes: 59 additions & 38 deletions webui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,73 @@
import { HashRouter, BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./Containers/Home";
import Run from "./Containers/Run";
import Project from "./Containers/Project";
import Auth from "./Containers/Auth";
import AccessTokens from "./Containers/Settings/AccessTokens";
import Billing from "./Containers/Settings/Billing";
import Settings from "./Containers/Settings";
import { useEffect } from "react";
import { useGetMeLazyQuery } from "./Hooks/GraphQL";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth } from "./firebase";
import { useRecoilState } from "recoil";
import { AuthState } from "./Containers/Auth/AuthState";
import LinkProject from "./Containers/LinkProject";
import {
RouterProvider,
createBrowserRouter,
createHashRouter,
} from "react-router-dom";
import RootLayout from "./Layouts/Root";
import { AuthenticateWithRedirectCallback } from "@clerk/clerk-react";

function App() {
const Router = location.host ? BrowserRouter : HashRouter;
const [user, loading] = useAuthState(auth);
const [getMe] = useGetMeLazyQuery();
const setMe = useRecoilState(AuthState)[1];
const createRouter = location.host ? createBrowserRouter : createHashRouter;

const router = createRouter([
{
element: <RootLayout />,
children: [
{ path: "/", element: <Home /> },
{
path: "/auth",
element: <Auth />,
},

useEffect(() => {
if (loading || !user) {
return;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getMe().then((response: any) => setMe(response?.data?.me));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user, loading]);
{
path: "/auth/sso-callback",
element: <AuthenticateWithRedirectCallback />,
},
{
path: "/settings",
element: <Settings />,
},
{
path: "/settings/account",
element: <Settings />,
},
{
path: "/settings/billing",
element: <Billing />,
},
{
path: "/settings/tokens",
element: <AccessTokens />,
},
{
path: "/run/:id",
element: <Run />,
},
{
path: "/project/:id",
element: <Project />,
},
{
path: "/link-project/:id",
element: <LinkProject />,
},
{
path: "/:id",
element: <Home />,
},
],
},
]);

return (
<>
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/auth" element={<Auth />} />
<Route path="/settings" element={<Settings />} />
<Route path="/settings/account" element={<Settings />} />
<Route path="/settings/billing" element={<Billing />} />
<Route path="/settings/tokens" element={<AccessTokens />} />
<Route path="/run/:id" element={<Run />} />
<Route path="/project/:id" element={<Project />} />
<Route path="/link-project/:id" element={<LinkProject />} />
<Route path="/:id" element={<Home />} />
</Routes>
</Router>
</>
);
function App() {
return <RouterProvider router={router} />;
}

export default App;
15 changes: 14 additions & 1 deletion webui/src/Components/Navbar/Navbar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { render } from "@testing-library/react";
import Navbar from "./Navbar";
import { BrowserRouter } from "react-router-dom";
import { FC, ReactNode } from "react";
import { ClerkProvider } from "@clerk/clerk-react";

describe("Navbar", () => {
it("should render the component", () => {
const wrapper: FC<{ children: ReactNode }> = ({ children }) => (
<ClerkProvider
routerPush={vi.fn()}
routerReplace={vi.fn()}
publishableKey={
"pk_test_c3BsZW5kaWQtcmFiYml0LTMyLmNsZXJrLmFjY291bnRzLmRldiQ"
}
>
<BrowserRouter>{children}</BrowserRouter>
</ClerkProvider>
);
const { container } = render(<Navbar onSignOut={vi.fn()} />, {
wrapper: BrowserRouter,
wrapper,
});
expect(container).toMatchSnapshot();
});
Expand Down
44 changes: 20 additions & 24 deletions webui/src/Components/Navbar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,23 @@ import {
} from "./styles";
import Logo from "../../assets/fluentci-logo.png";
import { Discord } from "@styled-icons/bootstrap";
import { SignedIn, SignedOut } from "@clerk/clerk-react";

export type NavbarProps = {
user?: {
displayName?: string | null;
photoURL?: string | null;
fullName: string | null;
username?: string | null;
reloadUserInfo?: {
screenName?: string | null;
};
imageUrl?: string;
primaryEmailAddress?: {
emailAddress?: string;
} | null;
} | null;
onSignOut: () => Promise<void>;
showAccountMenu?: boolean;
showSignInButton?: boolean;
};

const Navbar: FC<NavbarProps> = ({
user,
onSignOut,
showAccountMenu,
showSignInButton,
}) => {
const Navbar: FC<NavbarProps> = ({ user, onSignOut, showSignInButton }) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_activeKey, setActiveKey] = useState({ current: 0 });
const navigate = useNavigate();
Expand Down Expand Up @@ -85,13 +81,13 @@ const Navbar: FC<NavbarProps> = ({
<Menu href="https://discord.gg/H7M28d9dRk" target="_blank">
<Discord size={21} />
</Menu>
{showAccountMenu && (
<SignedIn>
<StatefulPopover
content={({ close }) => (
<PopoverMenu>
<UserDetails>
<Avatar src={user?.photoURL || ""} alt="avatar" size={88} />
<Name>{user?.displayName}</Name>
<Avatar src={user?.imageUrl || ""} alt="avatar" size={88} />
<Name>{user?.fullName}</Name>

<div
style={{
Expand All @@ -102,9 +98,7 @@ const Navbar: FC<NavbarProps> = ({
}}
>
<Github size={15} color="#6b7280" />
<Username>
{user?.username || user?.reloadUserInfo?.screenName}
</Username>
<Username>{user?.username}</Username>
</div>
</UserDetails>
<Ul>
Expand Down Expand Up @@ -147,19 +141,21 @@ const Navbar: FC<NavbarProps> = ({
}}
>
<button style={{ border: "none", backgroundColor: "initial" }}>
{!user?.photoURL && (
{!user?.imageUrl && (
<NoAvatar>
<User size={21} />
</NoAvatar>
)}
{user?.photoURL && <Avatar src={user.photoURL} alt="avatar" />}
{user?.imageUrl && <Avatar src={user.imageUrl} alt="avatar" />}
</button>
</StatefulPopover>
)}
{!showAccountMenu && showSignInButton && (
<SignIn>
<SignInLink href="/auth">Sign In with GitHub</SignInLink>
</SignIn>
</SignedIn>
{showSignInButton && (
<SignedOut>
<SignIn>
<SignInLink href="/auth">Sign In</SignInLink>
</SignIn>
</SignedOut>
)}
</div>
</NavbarContainer>
Expand Down
32 changes: 15 additions & 17 deletions webui/src/Components/Navbar/NavbarWithData.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,45 @@
import { FC, useEffect } from "react";
import Navbar from "./Navbar";
import { signOut } from "firebase/auth";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth } from "../../firebase";
import { useNavigate } from "react-router-dom";
import { useRecoilValue } from "recoil";
import { useRecoilState, useRecoilValue } from "recoil";
import { AuthState } from "../../Containers/Auth/AuthState";
import { useAuth, useUser } from "@clerk/clerk-react";

const NavbarWithData: FC = () => {
const { getToken, isSignedIn, signOut } = useAuth();
const setMe = useRecoilState(AuthState)[1];
const { user } = useUser();
const me = useRecoilValue(AuthState);
const [user, loading] = useAuthState(auth);
const navigate = useNavigate();

const onSignOut = async () => {
await signOut();
localStorage.setItem("logout", "true");
localStorage.removeItem("idToken");
await signOut(auth);
window.location.href = "https://fluentci.io";
localStorage.removeItem("token");
setMe(null);
};

useEffect(() => {
if (loading) {
return;
}

if (localStorage.getItem("logout") === "true") {
localStorage.removeItem("logout");
return;
}

if (!user && location.host === "app.fluentci.io") {
if (isSignedIn === false /*&& location.host === "app.fluentci.io"*/) {
if (
location.pathname.startsWith("/settings") ||
location.pathname.startsWith("/link-project")
) {
navigate("/auth");
return;
}
return;
}
getToken().then((token) => {
localStorage.setItem("token", token!);
});

user &&
user.getIdToken().then((token) => localStorage.setItem("idToken", token));
}, [user, loading, navigate]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSignedIn]);

return (
<Navbar
Expand Down
3 changes: 2 additions & 1 deletion webui/src/Components/Navbar/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,14 @@ export const SignIn = styled.div`
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
border: 1px solid #7392b161;
padding-left: 18px;
padding-right: 18px;
border-radius: 26px;
background-color: #06e0b021;
height: 42px;
width: 146.95px;
width: 80px;
`;

export const SignInLink = styled.a`
Expand Down
Loading

0 comments on commit 092aade

Please sign in to comment.