From cd46072c00693d4a14f8b8dd972c2843027ba2b5 Mon Sep 17 00:00:00 2001
From: "Lucian I. Last"
Date: Fri, 15 Mar 2024 17:55:41 +0100
Subject: [PATCH] Fix cookies once and for all
---
.../react/components/ChainsList.tsx | 9 +++--
.../components/react/pages/AdminDashboard.tsx | 3 --
frontend/src/stores/auth.ts | 2 +-
frontend/src/stores/browser_storage.ts | 34 ++++++++++++++++---
server/internal/app/auth/cookie.go | 10 +++---
server/internal/server.go | 17 ++++++++++
6 files changed, 57 insertions(+), 18 deletions(-)
diff --git a/frontend/src/components/react/components/ChainsList.tsx b/frontend/src/components/react/components/ChainsList.tsx
index 9a110c4b2..00147ac34 100644
--- a/frontend/src/components/react/components/ChainsList.tsx
+++ b/frontend/src/components/react/components/ChainsList.tsx
@@ -6,8 +6,6 @@ import {
type SetStateAction,
} from "react";
-import Cookies from "js-cookie";
-
import { $authUser, authUserRefresh } from "../../../stores/auth";
import {
chainGet,
@@ -23,6 +21,7 @@ import useToClipboard from "../util/to-clipboard.hooks";
import { useStore } from "@nanostores/react";
import { useTranslation } from "react-i18next";
import useLocalizePath from "../util/localize_path.hooks";
+import { cookiePoke } from "../../../stores/browser_storage";
const PUBLIC_BASE_URL = import.meta.env.PUBLIC_BASE_URL;
@@ -69,7 +68,7 @@ export default function ChainsList({ chains, setChains }: Props) {
addToastError(GinParseErrors(t, err), err.status);
}
- setIsPokeable(!(Cookies.get("poke") === authUser.uid));
+ setIsPokeable(!(cookiePoke.get() === authUser.uid));
}
}
@@ -80,14 +79,14 @@ export default function ChainsList({ chains, setChains }: Props) {
chainPoke(chainUID)
.then(() => {
addToast({ type: "success", message: t("reminderEmailSent") });
- Cookies.set("poke", authUser.uid, { expires: 7 });
+ cookiePoke.set(authUser.uid, 7);
setIsPokeable(false);
})
.catch((err) => {
addToastError(GinParseErrors(t, err), err.status);
if (err.status === 429) {
// hide for a day
- Cookies.set("poke", authUser.uid, { expires: 1 });
+ cookiePoke.set(authUser.uid, 1);
setIsPokeable(false);
}
});
diff --git a/frontend/src/components/react/pages/AdminDashboard.tsx b/frontend/src/components/react/pages/AdminDashboard.tsx
index bd8494c48..4a42da357 100644
--- a/frontend/src/components/react/pages/AdminDashboard.tsx
+++ b/frontend/src/components/react/pages/AdminDashboard.tsx
@@ -1,7 +1,6 @@
import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useStore } from "@nanostores/react";
-import Cookies from "js-cookie";
import { userPurge } from "../../../api/user";
import ChainsList from "../components/ChainsList";
@@ -61,8 +60,6 @@ export default function AdminDashboard() {
type: "error",
fn: () => {
userPurge(authUser!.uid).then(() => {
- // Remove legacy cookies
- Cookies.remove("user_uid");
window.location.href = localizePath("/users/logout");
});
},
diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts
index f7e8384fc..1a9579423 100644
--- a/frontend/src/stores/auth.ts
+++ b/frontend/src/stores/auth.ts
@@ -62,8 +62,8 @@ export function authUserRefresh(force = false): Promise {
const hasLoginSession = !!user;
if (hasLoginSession) console.info("has session storage");
- console.info("retrieve user uid from cookie");
let userUID = cookieUserUID.get();
+ if (userUID) console.info("retrieved user uid from cookie");
if (!userUID) {
$authUser.set(null);
diff --git a/frontend/src/stores/browser_storage.ts b/frontend/src/stores/browser_storage.ts
index 4962a7eca..8829c1a0c 100644
--- a/frontend/src/stores/browser_storage.ts
+++ b/frontend/src/stores/browser_storage.ts
@@ -1,8 +1,19 @@
import Cookies from "js-cookie";
import type { User } from "../api/types";
+const IS_PRODUCTION =
+ import.meta.env.PUBLIC_BASE_URL === "https://www.clothingloop.org";
+const IS_ACCEPTANCE =
+ import.meta.env.PUBLIC_BASE_URL === "https://acc.clothingloop.org";
+
const IS_DEV_MODE = import.meta.env.DEV;
+function cookiePostfix(name: string): string {
+ if (IS_PRODUCTION) return name;
+ if (IS_ACCEPTANCE) return name + "_acc";
+ return name + "_dev";
+}
+
type BrowserAtom = {
get: () => T | undefined | null;
set: (v: T | undefined | null) => void;
@@ -17,9 +28,12 @@ const cookieOptions: Cookies.CookieAttributes = {
sameSite: "strict",
};
-const KEY_C_USER_UID = "user_uid";
+const KEY_C_USER_UID = cookiePostfix("user_uid");
export const cookieUserUID: BrowserAtom = {
- get: () => Cookies.get(KEY_C_USER_UID),
+ get: () => {
+ console.log(KEY_C_USER_UID);
+ return Cookies.get(KEY_C_USER_UID);
+ },
set: (uid) => {
if (!uid) {
Cookies.remove(KEY_C_USER_UID, cookieOptions);
@@ -29,10 +43,22 @@ export const cookieUserUID: BrowserAtom = {
},
};
+const KEY_C_POKE = cookiePostfix("poke");
+export const cookiePoke = {
+ get: () => Cookies.get(KEY_C_POKE),
+ set: (uid: string, days: number) => {
+ if (!uid) {
+ Cookies.remove(KEY_C_POKE);
+ return;
+ }
+ Cookies.set(KEY_C_POKE, uid, { expires: days });
+ },
+};
+
// Localstorage
// ----------------------------------------------------------------
-const KEY_L_ROUTE_MAP_LINE = "route_map_line";
+const KEY_L_ROUTE_MAP_LINE = cookiePostfix("route_map_line");
export const localRouteMapLine: BrowserAtom = {
get: () => getS(window.localStorage, KEY_L_ROUTE_MAP_LINE),
set: (v) => setS(window.localStorage, KEY_L_ROUTE_MAP_LINE)(v),
@@ -41,7 +67,7 @@ export const localRouteMapLine: BrowserAtom = {
// Sessionstorage
// ----------------------------------------------------------------
-const KEY_S_AUTH_USER = "auth_user";
+const KEY_S_AUTH_USER = cookiePostfix("auth_user");
export const sessionAuthUser: BrowserAtom = {
get: () => {
diff --git a/server/internal/app/auth/cookie.go b/server/internal/app/auth/cookie.go
index 815dfa8b2..e7b0f41ed 100644
--- a/server/internal/app/auth/cookie.go
+++ b/server/internal/app/auth/cookie.go
@@ -11,14 +11,14 @@ import (
const cookieMaxAge = 3600 * 24 * 365
func cookieRead(c *gin.Context) (string, bool) {
- token, err := c.Cookie("token")
+ token, err := c.Cookie(c.GetString("cookie_token"))
return token, err == nil
}
func CookieRemove(c *gin.Context) {
http.SetCookie(c.Writer, &http.Cookie{
- Name: "token",
+ Name: c.GetString("cookie_token"),
Value: "",
MaxAge: -1,
Path: "/",
@@ -29,7 +29,7 @@ func CookieRemove(c *gin.Context) {
})
http.SetCookie(c.Writer, &http.Cookie{
- Name: "user_uid",
+ Name: c.GetString("cookie_user"),
Value: "",
MaxAge: -1,
Path: "/",
@@ -42,7 +42,7 @@ func CookieRemove(c *gin.Context) {
func CookieSet(c *gin.Context, userUID, token string) {
http.SetCookie(c.Writer, &http.Cookie{
- Name: "token",
+ Name: c.GetString("cookie_token"),
Value: token,
MaxAge: cookieMaxAge,
Path: "/",
@@ -53,7 +53,7 @@ func CookieSet(c *gin.Context, userUID, token string) {
})
http.SetCookie(c.Writer, &http.Cookie{
- Name: "user_uid",
+ Name: c.GetString("cookie_user"),
Value: userUID,
MaxAge: cookieMaxAge,
Path: "/",
diff --git a/server/internal/server.go b/server/internal/server.go
index b1ca256e7..db177fda7 100644
--- a/server/internal/server.go
+++ b/server/internal/server.go
@@ -77,6 +77,23 @@ func Routes() *gin.Engine {
)
r.Use(controllers.MiddlewareSetDB(db))
+ r.Use(func(c *gin.Context) {
+ var cookieToken = "token"
+ var cookieUser = "user_uid"
+
+ switch app.Config.ENV {
+ case app.EnvEnumProduction:
+ case app.EnvEnumAcceptance:
+ cookieToken += "_acc"
+ cookieUser += "_acc"
+ default:
+ cookieToken += "_dev"
+ cookieUser += "_dev"
+ }
+ c.Set("cookie_token", cookieToken)
+ c.Set("cookie_user", cookieUser)
+ })
+
thr := throttle.Policy(&throttle.Quota{
Limit: 30,
Within: 2 * time.Hour,