diff --git a/frontend/web/package.json b/frontend/web/package.json index 3d96a57..7fc9868 100644 --- a/frontend/web/package.json +++ b/frontend/web/package.json @@ -17,6 +17,7 @@ "copy-to-clipboard": "^3.3.3", "dayjs": "^1.11.10", "i18next": "^23.7.6", + "js-cookie": "^3.0.5", "lodash-es": "^4.17.21", "lucide-react": "^0.292.0", "nice-grpc-web": "^3.3.2", @@ -33,6 +34,7 @@ "devDependencies": { "@bufbuild/buf": "^1.28.1", "@trivago/prettier-plugin-sort-imports": "^4.3.0", + "@types/js-cookie": "^3.0.6", "@types/lodash-es": "^4.17.11", "@types/react": "^18.2.38", "@types/react-dom": "^18.2.16", diff --git a/frontend/web/pnpm-lock.yaml b/frontend/web/pnpm-lock.yaml index 1268bb7..79a8f6e 100644 --- a/frontend/web/pnpm-lock.yaml +++ b/frontend/web/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: i18next: specifier: ^23.7.6 version: 23.7.6 + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -73,6 +76,9 @@ devDependencies: '@trivago/prettier-plugin-sort-imports': specifier: ^4.3.0 version: 4.3.0(prettier@2.6.2) + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 '@types/lodash-es': specifier: ^4.17.11 version: 4.17.11 @@ -1145,6 +1151,10 @@ packages: resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} dev: false + /@types/js-cookie@3.0.6: + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + dev: true + /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} dev: true @@ -2570,6 +2580,11 @@ packages: resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} dev: false + /js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} diff --git a/frontend/web/src/components/Header.tsx b/frontend/web/src/components/Header.tsx index 680c0a3..d66940c 100644 --- a/frontend/web/src/components/Header.tsx +++ b/frontend/web/src/components/Header.tsx @@ -6,6 +6,7 @@ import { authServiceClient } from "@/grpcweb"; import useWorkspaceStore from "@/stores/v1/workspace"; import { PlanType } from "@/types/proto/api/v2/subscription_service"; import { Role } from "@/types/proto/api/v2/user_service"; +import { removeAccessToken } from "@/utils/auth"; import useUserStore from "../stores/v1/user"; import AboutDialog from "./AboutDialog"; import Icon from "./Icon"; @@ -23,7 +24,7 @@ const Header: React.FC = () => { const handleSignOutButtonClick = async () => { await authServiceClient.signOut({}); - document.cookie = "slash.access-token=; path=/;"; + removeAccessToken(); localStorage.removeItem("userId"); window.location.href = "/auth"; }; diff --git a/frontend/web/src/pages/SignIn.tsx b/frontend/web/src/pages/SignIn.tsx index 742fcd2..8a5d156 100644 --- a/frontend/web/src/pages/SignIn.tsx +++ b/frontend/web/src/pages/SignIn.tsx @@ -7,6 +7,7 @@ import { authServiceClient } from "@/grpcweb"; import useNavigateTo from "@/hooks/useNavigateTo"; import useUserStore from "@/stores/v1/user"; import useWorkspaceStore from "@/stores/v1/workspace"; +import { setAccessToken } from "@/utils/auth"; import useLoading from "../hooks/useLoading"; const SignIn: React.FC = () => { @@ -47,7 +48,7 @@ const SignIn: React.FC = () => { const { user, accessToken } = await authServiceClient.signIn({ email, password }); if (user) { userStore.setCurrentUserId(user.id); - document.cookie = `slash.access-token=${accessToken}; path=/;`; + setAccessToken(accessToken); await userStore.fetchCurrentUser(); navigateTo("/"); } else { diff --git a/frontend/web/src/pages/SignUp.tsx b/frontend/web/src/pages/SignUp.tsx index 99c30e5..1cce71d 100644 --- a/frontend/web/src/pages/SignUp.tsx +++ b/frontend/web/src/pages/SignUp.tsx @@ -7,6 +7,7 @@ import { authServiceClient } from "@/grpcweb"; import useNavigateTo from "@/hooks/useNavigateTo"; import useUserStore from "@/stores/v1/user"; import useWorkspaceStore from "@/stores/v1/workspace"; +import { setAccessToken } from "@/utils/auth"; import useLoading from "../hooks/useLoading"; const SignUp: React.FC = () => { @@ -58,7 +59,7 @@ const SignUp: React.FC = () => { }); if (user) { userStore.setCurrentUserId(user.id); - document.cookie = `slash.access-token=${accessToken}; path=/;`; + setAccessToken(accessToken); await userStore.fetchCurrentUser(); navigateTo("/"); } else { diff --git a/frontend/web/src/utils/auth.ts b/frontend/web/src/utils/auth.ts new file mode 100644 index 0000000..7cfa3dd --- /dev/null +++ b/frontend/web/src/utils/auth.ts @@ -0,0 +1,9 @@ +import Cookies from "js-cookie"; + +export const setAccessToken = (token: string) => { + Cookies.set("slash.access-token", token, { path: "/", expires: 365 }); +}; + +export const removeAccessToken = () => { + Cookies.remove("slash.access-token", { path: "/", expires: 365 }); +};