diff --git a/src/App.tsx b/src/App.tsx
index 1ba71bc5..945850dd 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,8 +3,10 @@ import AppRouter from "AppRouter";
import Onboarding from "modules/onboarding/components/Onboarding";
import { useEffect } from "react";
import Modal from "react-modal";
+import { ToastContainer } from "react-toastify";
import { isIP, isBrowserEnv, isDesktopEnv } from "shared/helpers/utils";
+import Login from "./modules/onboarding/components/Login";
import useSettingStore, { getBackendUrl } from "./shared/store/setting";
Modal.setAppElement("#root");
@@ -58,11 +60,12 @@ function App() {
})();
}, [isSettingStoreHydrated]);
- if (!isBrowser) {
- return } />;
- }
-
- return ;
+ return (
+ <>
+ {isBrowser ? } /> : } />}
+
+ >
+ );
}
export default App;
diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx
index d302daea..45260e3b 100644
--- a/src/AppRouter.tsx
+++ b/src/AppRouter.tsx
@@ -8,7 +8,6 @@ import Service from "modules/service/components/Service";
import ServiceDetail from "modules/service-detail/components/ServiceDetail";
import Settings from "modules/settings/components/Settings";
import { Route, BrowserRouter as Router, Routes } from "react-router-dom";
-import { ToastContainer } from "react-toastify";
import NotFound from "shared/components/NotFound";
import "react-toastify/dist/ReactToastify.css";
@@ -36,7 +35,6 @@ const AppRouter = () => {
} />
-
>
);
};
diff --git a/src/modules/onboarding/components/Login.tsx b/src/modules/onboarding/components/Login.tsx
new file mode 100644
index 00000000..1ec4aa86
--- /dev/null
+++ b/src/modules/onboarding/components/Login.tsx
@@ -0,0 +1,58 @@
+import type { FormEvent, ReactElement } from "react";
+import { useState } from "react";
+import { toast } from "react-toastify";
+
+import apiAuthd from "../../../shared/api/authd";
+import PrimaryButton from "../../../shared/components/PrimaryButton";
+import useSettingStore from "../../../shared/store/setting";
+
+const Login = ({ redirectTo }: { redirectTo: ReactElement }) => {
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
+ const setApiKey = useSettingStore((state) => state.setApiKey);
+
+ const onSubmit = async (e: FormEvent) => {
+ e.preventDefault();
+ const target = e.target as HTMLFormElement & {
+ user: { value: string };
+ password: { value: string };
+ };
+ try {
+ const user = target.user.value;
+ const password = target.password.value;
+ await apiAuthd()
+ .get(`/login?user=${user}&pass=${password}`)
+ .then((res) => {
+ console.log("res", res);
+ setIsAuthenticated(true);
+ setApiKey(res.data);
+ });
+ } catch (error: any) {
+ toast.error(error.message, { toastId: "login-error" });
+ } finally {
+ target.reset();
+ }
+ };
+
+ if (isAuthenticated) {
+ return redirectTo;
+ }
+
+ return (
+
+ );
+};
+
+export default Login;
diff --git a/src/shared/api/authd.ts b/src/shared/api/authd.ts
new file mode 100644
index 00000000..e96e3a3c
--- /dev/null
+++ b/src/shared/api/authd.ts
@@ -0,0 +1,23 @@
+import axios from "axios";
+
+import { isProxyEnabled } from "../helpers/utils";
+import useSettingStore from "../store/setting";
+
+const apiAuthd = () => {
+ const isIP = useSettingStore.getState().isIP;
+ const headers = { "Content-Type": "application/json" };
+ let baseURL;
+ if (isProxyEnabled()) {
+ if (isIP) {
+ baseURL = `${useSettingStore.getState().backendUrl}authd/auth`;
+ } else {
+ baseURL = `${window.location.protocol}//authd.${window.location.host}/auth`;
+ }
+ }
+ return axios.create({
+ baseURL,
+ headers,
+ });
+};
+
+export default apiAuthd;
diff --git a/src/shared/store/setting.ts b/src/shared/store/setting.ts
index fa8cb5c8..e580659a 100644
--- a/src/shared/store/setting.ts
+++ b/src/shared/store/setting.ts
@@ -93,6 +93,8 @@ const useSettingStore = create()(
swarmInfo: null,
setSwarmInfo: (swarmInfo: SwarmInfo | null) =>
set(() => ({ swarmInfo }), false, "setSwarmInfo"),
+ apiKey: null,
+ setApiKey: (apiKey: string) => set(() => ({ apiKey }), false, "setApiKey"),
environmentDeletion: EnvironmentDeletion.Completed,
setEnvironmentDeletion: (environmentDeletion: EnvironmentDeletion) =>
set(() => ({ environmentDeletion }), false, "setEnvironmentDeletion"),
diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts
index 5355f14b..f7a90dea 100644
--- a/src/shared/types/index.ts
+++ b/src/shared/types/index.ts
@@ -126,6 +126,8 @@ export type SettingStore = {
environmentDeletion: EnvironmentDeletion | null;
setEnvironmentDeletion: (environmentDeletion: EnvironmentDeletion) => void;
resetSwarm: () => void;
+ apiKey: string | null;
+ setApiKey: (apiKey: string) => void;
};
export type HeaderProps = {