generated from pascalmartineau/wp-skeleton
refactor: auth stuff
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const props = defineProps<{ showLabels: boolean }>();
|
const props = defineProps<{ showLabels: boolean }>();
|
||||||
const { loggedIn } = useUserSession();
|
const { loggedIn } = useUserSession();
|
||||||
const label = computed(() => props.showLabels ? (loggedIn ? "Déconnexion" : "Connexion") : undefined);
|
const label = computed(() => props.showLabels ? (loggedIn.value ? "Déconnexion" : "Connexion") : undefined);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { ThePage, TheArticle, TheEvent, TheLocation, TheMembership, TheProject,
|
|||||||
|
|
||||||
export async function useNodeByUri(uri: string) {
|
export async function useNodeByUri(uri: string) {
|
||||||
const { data, error } = await useAsyncGraphqlQuery("nodeByUri", { uri }, { graphqlCaching: { client: true } });
|
const { data, error } = await useAsyncGraphqlQuery("nodeByUri", { uri }, { graphqlCaching: { client: true } });
|
||||||
if (error.value) {
|
if (error.value || data.value?.errors.length) {
|
||||||
throw createError({ statusCode: 500, statusMessage: "Erreur serveur", message: error.value.message });
|
throw createError({ statusCode: 500, statusMessage: "Erreur serveur", message: "Une erreur est survenue." });
|
||||||
}
|
}
|
||||||
const node = data.value?.data.nodeByUri;
|
const node = data.value?.data.nodeByUri;
|
||||||
const breadcrumbs = node?.breadcrumbs?.map(({ label, to }) => ({ label, to: to || undefined })) || [];
|
const breadcrumbs = node?.breadcrumbs?.map(({ label, to }) => ({ label, to: to || undefined })) || [];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export function useUserSwitching() {
|
|||||||
const { fetch: refreshUserSession } = useUserSession();
|
const { fetch: refreshUserSession } = useUserSession();
|
||||||
const { session } = useUserSession();
|
const { session } = useUserSession();
|
||||||
|
|
||||||
const isUserSwitched = computed(() => Boolean(session.value?.switchedBy));
|
const isUserSwitched = computed(() => Boolean(session.value?.isSwitchedTo));
|
||||||
|
|
||||||
async function userSwitchTo(userId: string | number) {
|
async function userSwitchTo(userId: string | number) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"@nuxtjs/robots": "5.5.0",
|
"@nuxtjs/robots": "5.5.0",
|
||||||
"@nuxtjs/sitemap": "7.4.3",
|
"@nuxtjs/sitemap": "7.4.3",
|
||||||
"@vueuse/nuxt": "13.7.0",
|
"@vueuse/nuxt": "13.7.0",
|
||||||
|
"es-toolkit": "^1.39.10",
|
||||||
"nuxt": "^4.1.2",
|
"nuxt": "^4.1.2",
|
||||||
"nuxt-auth-utils": "0.5.23",
|
"nuxt-auth-utils": "0.5.23",
|
||||||
"nuxt-graphql-middleware": "5.2.0",
|
"nuxt-graphql-middleware": "5.2.0",
|
||||||
|
|||||||
8
wp-content/themes/ccat/pnpm-lock.yaml
generated
8
wp-content/themes/ccat/pnpm-lock.yaml
generated
@@ -35,6 +35,9 @@ importers:
|
|||||||
'@vueuse/nuxt':
|
'@vueuse/nuxt':
|
||||||
specifier: 13.7.0
|
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))
|
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:
|
nuxt:
|
||||||
specifier: ^4.1.2
|
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)
|
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==}
|
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
es-toolkit@1.39.10:
|
||||||
|
resolution: {integrity: sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==}
|
||||||
|
|
||||||
esbuild@0.25.4:
|
esbuild@0.25.4:
|
||||||
resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==}
|
resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -9767,6 +9773,8 @@ snapshots:
|
|||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
es-toolkit@1.39.10: {}
|
||||||
|
|
||||||
esbuild@0.25.4:
|
esbuild@0.25.4:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@esbuild/aix-ppc64': 0.25.4
|
'@esbuild/aix-ppc64': 0.25.4
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import { defineEventHandler } from "h3";
|
|||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
// TODO: Switch back to the previous user.
|
await handleSwitchBack(event);
|
||||||
await clearUserSession(event);
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
|
|||||||
@@ -32,44 +32,15 @@ export default defineGraphqlServerOptions({
|
|||||||
return { headers: { ...headers, Authorization: `Bearer ${session.secure.authToken}` } };
|
return { headers: { ...headers, Authorization: `Bearer ${session.secure.authToken}` } };
|
||||||
},
|
},
|
||||||
|
|
||||||
onServerResponse(event, response, _operation, operationName) {
|
async onServerResponse(event, response, _operation, operationName) {
|
||||||
// Handle login mutation
|
switch (operationName) {
|
||||||
if (operationName === "login") {
|
case "login":
|
||||||
const loginData = response._data as LoginRootMutation;
|
await handleLogin(event, response._data!.data as LoginRootMutation);
|
||||||
if (loginData?.login) {
|
break;
|
||||||
const { authToken, refreshToken, user } = loginData.login;
|
case "userSwitchTo":
|
||||||
setUserSession(event, {
|
await handleSwitchTo(event, response._data!.data as UserSwitchToRootMutation);
|
||||||
user: {
|
break;
|
||||||
id: user?.id,
|
|
||||||
email: user?.email,
|
|
||||||
},
|
|
||||||
secure: {
|
|
||||||
authToken,
|
|
||||||
refreshToken,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 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!;
|
return response._data!;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
65
wp-content/themes/ccat/server/utils/auth.ts
Normal file
65
wp-content/themes/ccat/server/utils/auth.ts
Normal file
@@ -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,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -7,12 +7,17 @@ declare module "#auth-utils" {
|
|||||||
|
|
||||||
interface UserSession {
|
interface UserSession {
|
||||||
loggedInAt: string;
|
loggedInAt: string;
|
||||||
switchedBy?: number;
|
isSwitchedTo: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SecureSessionData {
|
interface SecureSessionData {
|
||||||
authToken: string;
|
authToken: string;
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
|
previous?: {
|
||||||
|
user: User;
|
||||||
|
loggedInAt: string;
|
||||||
|
secure: Pick<SecureSessionData, ["authToken", "refreshToken"]>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user