diff --git a/wp-content/themes/ccat/app/components/site/SiteHeaderTopAuth.vue b/wp-content/themes/ccat/app/components/site/SiteHeaderTopAuth.vue
index b6af890..94f7847 100644
--- a/wp-content/themes/ccat/app/components/site/SiteHeaderTopAuth.vue
+++ b/wp-content/themes/ccat/app/components/site/SiteHeaderTopAuth.vue
@@ -1,7 +1,7 @@
diff --git a/wp-content/themes/ccat/app/composables/useNodeByUri.ts b/wp-content/themes/ccat/app/composables/useNodeByUri.ts
index c21910a..70cb958 100644
--- a/wp-content/themes/ccat/app/composables/useNodeByUri.ts
+++ b/wp-content/themes/ccat/app/composables/useNodeByUri.ts
@@ -3,8 +3,8 @@ import { ThePage, TheArticle, TheEvent, TheLocation, TheMembership, TheProject,
export async function useNodeByUri(uri: string) {
const { data, error } = await useAsyncGraphqlQuery("nodeByUri", { uri }, { graphqlCaching: { client: true } });
- if (error.value) {
- throw createError({ statusCode: 500, statusMessage: "Erreur serveur", message: error.value.message });
+ if (error.value || data.value?.errors.length) {
+ throw createError({ statusCode: 500, statusMessage: "Erreur serveur", message: "Une erreur est survenue." });
}
const node = data.value?.data.nodeByUri;
const breadcrumbs = node?.breadcrumbs?.map(({ label, to }) => ({ label, to: to || undefined })) || [];
diff --git a/wp-content/themes/ccat/app/composables/useUserSwitching.ts b/wp-content/themes/ccat/app/composables/useUserSwitching.ts
index 739e8b1..ab2164c 100644
--- a/wp-content/themes/ccat/app/composables/useUserSwitching.ts
+++ b/wp-content/themes/ccat/app/composables/useUserSwitching.ts
@@ -3,7 +3,7 @@ export function useUserSwitching() {
const { fetch: refreshUserSession } = useUserSession();
const { session } = useUserSession();
- const isUserSwitched = computed(() => Boolean(session.value?.switchedBy));
+ const isUserSwitched = computed(() => Boolean(session.value?.isSwitchedTo));
async function userSwitchTo(userId: string | number) {
try {
diff --git a/wp-content/themes/ccat/package.json b/wp-content/themes/ccat/package.json
index 43886bc..2bb76a1 100644
--- a/wp-content/themes/ccat/package.json
+++ b/wp-content/themes/ccat/package.json
@@ -25,6 +25,7 @@
"@nuxtjs/robots": "5.5.0",
"@nuxtjs/sitemap": "7.4.3",
"@vueuse/nuxt": "13.7.0",
+ "es-toolkit": "^1.39.10",
"nuxt": "^4.1.2",
"nuxt-auth-utils": "0.5.23",
"nuxt-graphql-middleware": "5.2.0",
diff --git a/wp-content/themes/ccat/pnpm-lock.yaml b/wp-content/themes/ccat/pnpm-lock.yaml
index 8502540..fb212bd 100644
--- a/wp-content/themes/ccat/pnpm-lock.yaml
+++ b/wp-content/themes/ccat/pnpm-lock.yaml
@@ -35,6 +35,9 @@ importers:
'@vueuse/nuxt':
specifier: 13.7.0
version: 13.7.0(magicast@0.3.5)(nuxt@4.1.2(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.4.0)(@vue/compiler-sfc@3.5.21)(db0@0.3.2)(eslint@9.35.0(jiti@2.5.1))(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.50.2)(terser@5.44.0)(typescript@5.9.2)(vite@7.1.5(@types/node@24.4.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue-tsc@3.0.7(typescript@5.9.2))(yaml@2.8.1))(vue@3.5.21(typescript@5.9.2))
+ es-toolkit:
+ specifier: ^1.39.10
+ version: 1.39.10
nuxt:
specifier: ^4.1.2
version: 4.1.2(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.4.0)(@vue/compiler-sfc@3.5.21)(db0@0.3.2)(eslint@9.35.0(jiti@2.5.1))(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.50.2)(terser@5.44.0)(typescript@5.9.2)(vite@7.1.5(@types/node@24.4.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue-tsc@3.0.7(typescript@5.9.2))(yaml@2.8.1)
@@ -3305,6 +3308,9 @@ packages:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
+ es-toolkit@1.39.10:
+ resolution: {integrity: sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==}
+
esbuild@0.25.4:
resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==}
engines: {node: '>=18'}
@@ -9767,6 +9773,8 @@ snapshots:
es-errors: 1.3.0
optional: true
+ es-toolkit@1.39.10: {}
+
esbuild@0.25.4:
optionalDependencies:
'@esbuild/aix-ppc64': 0.25.4
diff --git a/wp-content/themes/ccat/server/api/switch-back.post.ts b/wp-content/themes/ccat/server/api/switch-back.post.ts
index e88e221..ff017f4 100644
--- a/wp-content/themes/ccat/server/api/switch-back.post.ts
+++ b/wp-content/themes/ccat/server/api/switch-back.post.ts
@@ -2,8 +2,7 @@ import { defineEventHandler } from "h3";
export default defineEventHandler(async (event) => {
try {
- // TODO: Switch back to the previous user.
- await clearUserSession(event);
+ await handleSwitchBack(event);
return { success: true };
}
catch (error) {
diff --git a/wp-content/themes/ccat/server/graphqlMiddleware.serverOptions.ts b/wp-content/themes/ccat/server/graphqlMiddleware.serverOptions.ts
index c753f4d..c24893b 100644
--- a/wp-content/themes/ccat/server/graphqlMiddleware.serverOptions.ts
+++ b/wp-content/themes/ccat/server/graphqlMiddleware.serverOptions.ts
@@ -32,44 +32,15 @@ export default defineGraphqlServerOptions({
return { headers: { ...headers, Authorization: `Bearer ${session.secure.authToken}` } };
},
- onServerResponse(event, response, _operation, operationName) {
- // Handle login mutation
- if (operationName === "login") {
- const loginData = response._data as LoginRootMutation;
- if (loginData?.login) {
- const { authToken, refreshToken, user } = loginData.login;
- setUserSession(event, {
- user: {
- id: user?.id,
- email: user?.email,
- },
- secure: {
- authToken,
- refreshToken,
- },
- });
- }
+ async onServerResponse(event, response, _operation, operationName) {
+ switch (operationName) {
+ case "login":
+ await handleLogin(event, response._data!.data as LoginRootMutation);
+ break;
+ case "userSwitchTo":
+ await handleSwitchTo(event, response._data!.data as UserSwitchToRootMutation);
+ break;
}
-
- // Handle user switch mutations
- if (operationName === "userSwitchTo") {
- const switchData = response._data as UserSwitchToRootMutation;
- if (switchData?.userSwitchTo?.authToken) {
- const { authToken, refreshToken, user } = switchData.userSwitchTo;
- setUserSession(event, {
- user: {
- id: user?.id,
- email: user?.email,
- },
- secure: {
- authToken,
- refreshToken,
- },
- });
- }
- }
-
- // Return the original response data
return response._data!;
},
});
diff --git a/wp-content/themes/ccat/server/utils/auth.ts b/wp-content/themes/ccat/server/utils/auth.ts
new file mode 100644
index 0000000..9e950e5
--- /dev/null
+++ b/wp-content/themes/ccat/server/utils/auth.ts
@@ -0,0 +1,65 @@
+import type { LoginRootMutation, UserSwitchToRootMutation } from "#graphql-operations";
+import type { H3Event } from "h3";
+import { pick } from "es-toolkit/compat";
+
+export async function handleLogin(event: H3Event, loginData?: LoginRootMutation) {
+ if (!loginData?.login?.user) {
+ return;
+ }
+ const { authToken, refreshToken, user } = loginData.login;
+ await setUserSession(event, {
+ user: {
+ id: user.id,
+ email: user.email,
+ },
+ secure: {
+ authToken,
+ refreshToken,
+ },
+ loggedInAt: new Date().toISOString(),
+ isSwitchedTo: false,
+ });
+}
+
+export async function handleLogout(event: H3Event) {
+ await clearUserSession(event);
+}
+
+export async function handleSwitchTo(event: H3Event, data?: UserSwitchToRootMutation) {
+ if (!data?.userSwitchTo?.user) {
+ return;
+ }
+ const session = await getUserSession(event);
+ const { authToken, refreshToken, user } = data.userSwitchTo;
+ await setUserSession(event, {
+ user: {
+ id: user.id,
+ email: user.email,
+ },
+ secure: {
+ authToken,
+ refreshToken,
+ previous: {
+ user: session.user,
+ loggedInAt: session.loggedInAt,
+ secure: pick(session.secure, ["authToken", "refreshToken"]),
+ },
+ },
+ loggedInAt: new Date().toISOString(),
+ isSwitchedTo: true,
+ });
+}
+
+export async function handleSwitchBack(event: H3Event) {
+ const session = await getUserSession(event);
+ if (!session.secure?.previous) {
+ return;
+ }
+ const { user, loggedInAt, secure } = session.secure.previous;
+ await setUserSession(event, {
+ user,
+ secure,
+ loggedInAt,
+ isSwitchedTo: false,
+ });
+}
diff --git a/wp-content/themes/ccat/shared/types/auth.d.ts b/wp-content/themes/ccat/shared/types/auth.d.ts
index 852711f..7fadddd 100644
--- a/wp-content/themes/ccat/shared/types/auth.d.ts
+++ b/wp-content/themes/ccat/shared/types/auth.d.ts
@@ -7,12 +7,17 @@ declare module "#auth-utils" {
interface UserSession {
loggedInAt: string;
- switchedBy?: number;
+ isSwitchedTo: boolean;
}
interface SecureSessionData {
authToken: string;
refreshToken: string;
+ previous?: {
+ user: User;
+ loggedInAt: string;
+ secure: Pick;
+ };
}
}