From 5c63e04ba0bab63eeb00d7bcc397b5de6be12487 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 23 Apr 2024 15:20:08 +0200 Subject: [PATCH 1/2] :sparkles: installing hotjar --- package-lock.json | 21 +++++++++++++++------ package.json | 4 ++++ src/middleware.ts | 7 +++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7988639e..bac7e9b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,13 +28,16 @@ "prettier": "^2.8.7", "react": "18.2.0", "react-dom": "18.2.0", + "react-gtm-module": "^2.0.11", "react-select": "^5.7.2", "react-toastify": "^9.1.3", "sass": "^1.59.2", "sharp": "^0.32.1", - "ts-pattern": "^4.3.0", "typescript": "4.9.5", "uuidv4": "^6.2.13" + }, + "devDependencies": { + "@types/react-gtm-module": "^2.0.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -963,6 +966,12 @@ "@types/react": "*" } }, + "node_modules/@types/react-gtm-module": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/react-gtm-module/-/react-gtm-module-2.0.3.tgz", + "integrity": "sha512-fL2zKdDFN5LckSsVBXEhhm9M4tFTM9oHJfGcfZJzktQkzpOTGtDM8oXIP9d9UBDxO4xLNZhS22dlgRVv6wgK9w==", + "dev": true + }, "node_modules/@types/react-transition-group": { "version": "4.4.10", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", @@ -4220,6 +4229,11 @@ "react": "^18.2.0" } }, + "node_modules/react-gtm-module": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", + "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -4911,11 +4925,6 @@ "node": ">=8.0" } }, - "node_modules/ts-pattern": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-4.3.0.tgz", - "integrity": "sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg==" - }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", diff --git a/package.json b/package.json index 5ae85dcc..f8735b20 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,15 @@ "prettier": "^2.8.7", "react": "18.2.0", "react-dom": "18.2.0", + "react-gtm-module": "^2.0.11", "react-select": "^5.7.2", "react-toastify": "^9.1.3", "sass": "^1.59.2", "sharp": "^0.32.1", "typescript": "4.9.5", "uuidv4": "^6.2.13" + }, + "devDependencies": { + "@types/react-gtm-module": "^2.0.3" } } diff --git a/src/middleware.ts b/src/middleware.ts index 1af4a2af..2dd79c03 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -2,6 +2,13 @@ import { ICustomerJwtPayload, IUserJwtPayload } from "@Front/Services/JwtService import jwt_decode from "jwt-decode"; import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; +import TagManager from "react-gtm-module"; + +const tagManagerArgs = { + gtmId: "GTM-5GLJN86P", +}; + +TagManager.initialize(tagManagerArgs); export async function middleware(request: NextRequest) { // Get the JWT from the cookies From 2851c5834d1f62a1292624bc42c1ec87bb612aec Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Wed, 24 Apr 2024 10:41:18 +0200 Subject: [PATCH 2/2] :sparkles: Force refresh token at the end of subscription --- src/front/Api/BaseApiService.ts | 5 +- .../SubscriptionSuccess/index.tsx | 13 ++++- src/front/Services/JwtService/JwtService.ts | 48 +++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/front/Api/BaseApiService.ts b/src/front/Api/BaseApiService.ts index 330551a4..01ad7443 100644 --- a/src/front/Api/BaseApiService.ts +++ b/src/front/Api/BaseApiService.ts @@ -135,9 +135,8 @@ export default abstract class BaseApiService { private async checkJwtToken() { const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken"); - if (!accessToken) { - return; - } + if (!accessToken) return; + const userDecodedToken = jwt_decode(accessToken) as IUserJwtPayload; const customerDecodedToken = jwt_decode(accessToken) as ICustomerJwtPayload; diff --git a/src/front/Components/Layouts/Subscription/SubscriptionSuccess/index.tsx b/src/front/Components/Layouts/Subscription/SubscriptionSuccess/index.tsx index 6ec13f3f..ad4c8bd7 100644 --- a/src/front/Components/Layouts/Subscription/SubscriptionSuccess/index.tsx +++ b/src/front/Components/Layouts/Subscription/SubscriptionSuccess/index.tsx @@ -13,6 +13,7 @@ import Subscriptions from "@Front/Api/LeCoffreApi/Admin/Subscriptions/Subscripti import JwtService from "@Front/Services/JwtService/JwtService"; import { Subscription } from "le-coffre-resources/dist/Admin"; import Stripe from "@Front/Api/LeCoffreApi/Admin/Stripe/Stripe"; +import CookieService from "@Front/Services/CookieService/CookieService"; export default function SubscriptionSuccess() { const [subscription, setSubscription] = useState(null); @@ -27,6 +28,14 @@ export default function SubscriptionSuccess() { setCustomer(customer); }, []); + const refreshToken = useCallback(async () => { + CookieService.getInstance().deleteCookie("leCoffreAccessToken"); + const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken"); + if (!refreshToken) return; + await JwtService.getInstance().forceRefreshToken(refreshToken); + await loadSubscription(); + }, [loadSubscription]); + const getFrequency = useCallback(() => { if (!subscription) return; const start = new Date(subscription.start_date); @@ -38,8 +47,8 @@ export default function SubscriptionSuccess() { }, [subscription]); useEffect(() => { - loadSubscription(); - }, [loadSubscription]); + refreshToken(); + }, [refreshToken]); return ( diff --git a/src/front/Services/JwtService/JwtService.ts b/src/front/Services/JwtService/JwtService.ts index 38693eab..e53789ad 100644 --- a/src/front/Services/JwtService/JwtService.ts +++ b/src/front/Services/JwtService/JwtService.ts @@ -112,6 +112,54 @@ export default class JwtService { return false; } + public async forceRefreshToken(refreshToken: string): Promise { + const userToken = jwt_decode(refreshToken) as IUserJwtPayload; + const customerToken = jwt_decode(refreshToken) as ICustomerJwtPayload; + + const variables = FrontendVariables.getInstance(); + if (userToken?.userId) { + try { + const headers = new Headers(); + headers.append("Authorization", `Bearer ${refreshToken}`); + const response = await fetch( + `${ + variables.BACK_API_PROTOCOL + variables.BACK_API_HOST + variables.BACK_API_ROOT_URL + variables.BACK_API_VERSION + }/idnot/user/auth/refresh-token`, + { method: "POST", headers: headers }, + ); + const newAccessToken: { accessToken: string } = await response.json(); + if (newAccessToken) { + await UserStore.instance.connect(newAccessToken.accessToken, refreshToken); + return true; + } + } catch (err) { + console.error(err); + return false; + } + } else if (customerToken?.customerId) { + try { + const headers = new Headers(); + headers.append("Authorization", `Bearer ${refreshToken}`); + const response = await fetch( + `${ + variables.BACK_API_PROTOCOL + variables.BACK_API_HOST + variables.BACK_API_ROOT_URL + variables.BACK_API_VERSION + }/id360/customers/refresh-token`, + { method: "POST", headers: headers }, + ); + const newAccessToken: { accessToken: string } = await response.json(); + if (newAccessToken) { + await CustomerStore.instance.connect(newAccessToken.accessToken, refreshToken); + return true; + } + } catch (err) { + console.error(err); + return false; + } + } + + return false; + } + public hasRule(name: string, action: string) { const token = this.decodeJwt(); if (!token) return false;