Fix sessions, start profile UI and add middleware
This commit is contained in:
parent
b3fae0b5db
commit
a392841012
|
|
@ -3,9 +3,9 @@
|
|||
<AvatarImage class="h-full w-full object-cover" :src="src" asChild @loading-status-change="(status) => loading = status === 'loading'">
|
||||
<img :src="src" />
|
||||
</AvatarImage>
|
||||
<AvatarFallback :delay-ms="0" class="text-light-100 dark:text-dark-100 leading-1 flex h-full w-full items-center justify-center bg-light-25 dark:bg-dark-25 font-medium">
|
||||
<AvatarFallback :delay-ms="0" class="text-light-100 dark:text-dark-100 leading-1 flex h-full w-full p-4 items-center justify-center bg-light-25 dark:bg-dark-25 font-medium">
|
||||
<Loading v-if="loading" />
|
||||
<Icon v-else-if="!!icon" :icon="icon" class="w-8 h-8" />
|
||||
<Icon v-else-if="!!icon" :icon="icon" class="w-full h-full" />
|
||||
<span v-else-if="!!text">{{ text }}</span>
|
||||
</AvatarFallback>
|
||||
</AvatarRoot>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<HoverCardRoot :open-delay="delay">
|
||||
<HoverCardTrigger class="inline-block cursor-help outline-none" asChild>
|
||||
<HoverCardTrigger class="inline-block cursor-help outline-none">
|
||||
<slot></slot>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardPortal v-if="!disabled">
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import { Database } from "bun:sqlite";
|
||||
import { drizzle } from "drizzle-orm/bun-sqlite";
|
||||
import { BunSQLiteDatabase, drizzle } from "drizzle-orm/bun-sqlite";
|
||||
import * as schema from '../db/schema';
|
||||
|
||||
let instance: BunSQLiteDatabase<typeof schema>;
|
||||
export default function useDatabase()
|
||||
{
|
||||
if(!instance)
|
||||
{
|
||||
const sqlite = new Database(useRuntimeConfig().database);
|
||||
const db = drizzle({ client: sqlite, schema });
|
||||
instance = drizzle({ client: sqlite, schema });
|
||||
|
||||
db.run("PRAGMA journal_mode = WAL;");
|
||||
instance.run("PRAGMA journal_mode = WAL;");
|
||||
}
|
||||
|
||||
return db;
|
||||
return instance;
|
||||
}
|
||||
BIN
db.sqlite-shm
BIN
db.sqlite-shm
Binary file not shown.
BIN
db.sqlite-wal
BIN
db.sqlite-wal
Binary file not shown.
|
|
@ -12,8 +12,8 @@
|
|||
</div>
|
||||
<div class="flex items-center px-2">
|
||||
<Tooltip message="Changer de theme" side="left"><ThemeSwitch /></Tooltip>
|
||||
<Tooltip message="Se connecter" side="right">
|
||||
<NuxtLink class="" :to="{ path: '/user/login', force: true }">
|
||||
<Tooltip :message="loggedIn ? 'Mon profil' : 'Se connecter'" side="right">
|
||||
<NuxtLink class="" :to="{ path: '/user/profile', force: true }">
|
||||
<div class="hover:border-opacity-70 flex">
|
||||
<Icon icon="radix-icons:person" class="w-7 h-7 p-1" />
|
||||
</div>
|
||||
|
|
@ -31,8 +31,8 @@
|
|||
</NuxtLink>
|
||||
<div class="flex gap-4 items-center">
|
||||
<Tooltip message="Changer de theme" side="left"><ThemeSwitch /></Tooltip>
|
||||
<Tooltip message="Se connecter" side="right">
|
||||
<NuxtLink class="" :to="{ path: '/user/login', force: true }">
|
||||
<Tooltip :message="loggedIn ? 'Mon profil' : 'Se connecter'" side="right">
|
||||
<NuxtLink class="" :to="{ path: '/user/profile', force: true }">
|
||||
<div class="bg-light-20 dark:bg-dark-20 hover:border-opacity-70 flex border p-px border-light-50 dark:border-dark-50">
|
||||
<Icon icon="radix-icons:person" class="w-7 h-7 p-1" />
|
||||
</div>
|
||||
|
|
@ -56,4 +56,5 @@
|
|||
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||
|
||||
const open = ref(true);
|
||||
const { loggedIn } = useUserSession();
|
||||
</script>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
const { loggedIn, ready, fetch } = useUserSession();
|
||||
const meta = to.meta;
|
||||
|
||||
if(!ready)
|
||||
await fetch();
|
||||
|
||||
if(!!meta.guestsGoesTo && !loggedIn.value)
|
||||
{
|
||||
return navigateTo(meta.guestsGoesTo);
|
||||
}
|
||||
else if(meta.requireAuth && !loggedIn.value)
|
||||
{
|
||||
return abortNavigation();
|
||||
}
|
||||
else if(!!meta.usersGoesTo && loggedIn.value)
|
||||
{
|
||||
return navigateTo(meta.usersGoesTo);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
|
|
@ -2,6 +2,10 @@
|
|||
"name": "d-any",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"predev": "bun i && bunx nuxi cleanup",
|
||||
"dev": "bunx --bun nuxi dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/vue": "^4.1.2",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import { Icon } from '@iconify/vue/dist/iconify.js';
|
|||
|
||||
definePageMeta({
|
||||
layout: 'login',
|
||||
usersGoesTo: '/user/profile',
|
||||
});
|
||||
|
||||
const { add: addToast, clear: clearToasts } = useToast();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
const { user } = useUserSession();
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
})
|
||||
let { user, clear } = useUserSession();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head>
|
||||
<Title>Mon profil</Title>
|
||||
</Head>
|
||||
<div class="flex w-full items-start py-8 gap-6" v-if="user">
|
||||
<div class="flex gap-4 min-w-1/3 max-w-2/3 border border-light-35 dark:border-dark-35 p-4">
|
||||
<Avatar icon="radix-icons:person" :src="`/users/${user?.id}.medium.jpg`" class="w-32 h-32" />
|
||||
<div class="flex flex-col items-start">
|
||||
<ProseH5>{{ user.username }}</ProseH5>
|
||||
<ProseH5>{{ user.email }}</ProseH5>
|
||||
<HoverCard>
|
||||
<template v-slot:default><div class="border-light-red dark:border-dark-red bg-light-red bg-opacity-25 dark:bg-dark-red dark:bg-opacity-25 text-light-red dark:text-dark-red py-1 px-3" v-if="user.state === 0">Votre adresse mail n'as pas encore été validée. <Button class="ms-4">Renvoyez un mail</Button></div></template>
|
||||
<template v-slot:content><span>Tant que votre adresse mail n'as pas été validée, vous n'avez que des droits de lecture.</span></template>
|
||||
</HoverCard>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<Button @click="async () => await clear()">Se deconnecter</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -39,6 +39,7 @@ import { Icon } from '@iconify/vue/dist/iconify.js';
|
|||
|
||||
definePageMeta({
|
||||
layout: 'login',
|
||||
usersGoesTo: '/user/profile',
|
||||
});
|
||||
|
||||
const state = reactive<Registration>({
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export default defineEventHandler(async (e): Promise<Return> => {
|
|||
return { success: false, error: new Error('Données utilisateur introuvable') };
|
||||
}
|
||||
|
||||
const data = await logSession(e, await setUserSession(e, {
|
||||
const data = logSession(e, await setUserSession(e, {
|
||||
user: {
|
||||
...user.data,
|
||||
email: user.email,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import useDatabase from "~/composables/useDatabase";
|
||||
import { userSessionsTable as sessions } from "~/db/schema";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { userSessionsTable } from "~/db/schema";
|
||||
import { eq, and, sql } from "drizzle-orm";
|
||||
|
||||
const monthAsMs = 60 * 60 * 24 * 30 * 1000;
|
||||
|
||||
|
|
@ -8,12 +8,7 @@ export default defineNitroPlugin(() => {
|
|||
const db = useDatabase();
|
||||
|
||||
sessionHooks.hook('fetch', async (session, event) => {
|
||||
const result = await db.query.userSessionsTable.findFirst({
|
||||
columns: {
|
||||
timestamp: true,
|
||||
},
|
||||
where: and(eq(sessions.id, session.id as unknown as number), eq(sessions.user_id, session.user.id))
|
||||
});
|
||||
const result = db.select({ timestamp: userSessionsTable.timestamp }).from(userSessionsTable).where(and(eq(userSessionsTable.id, sql.placeholder('id')), eq(userSessionsTable.user_id, sql.placeholder('user_id')))).prepare().get({ id: session.id, user_id: session.user.id });
|
||||
|
||||
if(!result)
|
||||
{
|
||||
|
|
@ -27,9 +22,9 @@ export default defineNitroPlugin(() => {
|
|||
}
|
||||
else
|
||||
{
|
||||
await db.update(sessions).set({
|
||||
await db.update(userSessionsTable).set({
|
||||
timestamp: new Date(),
|
||||
}).where(and(eq(sessions.id, session.id as unknown as number), eq(sessions.user_id, session.user.id)));
|
||||
}).where(and(eq(userSessionsTable.id, sql.placeholder('id')), eq(userSessionsTable.user_id, sql.placeholder('user_id')))).prepare().run({ id: session.id, user_id: session.user.id });
|
||||
}
|
||||
});
|
||||
sessionHooks.hook('clear', async (session, event) => {
|
||||
|
|
@ -37,7 +32,7 @@ export default defineNitroPlugin(() => {
|
|||
{
|
||||
try
|
||||
{
|
||||
await db.delete(sessions).where(and(eq(sessions.id, session.id as unknown as number), eq(sessions.user_id, session.user.id)));
|
||||
db.delete(userSessionsTable).where(and(eq(userSessionsTable.id, sql.placeholder('id')), eq(userSessionsTable.user_id, sql.placeholder('user_id')))).prepare().run({ id: session.id, user_id: session.user.id });
|
||||
}
|
||||
catch(e) { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ export function logSession(e: H3Event<EventRequestHandler>, session: UserSession
|
|||
{
|
||||
const db = useDatabase();
|
||||
|
||||
db.insert(userSessionsTable).values({ id: sql.placeholder('id'), user_id: sql.placeholder('user_id'), timestamp: sql.placeholder('timestamp') }).prepare().execute({ id: session.id, user_id: session.user.id, timestamp: new Date()});
|
||||
console.log("Logging session %s", session.id)
|
||||
db.insert(userSessionsTable).values({ id: sql.placeholder('id'), user_id: sql.placeholder('user_id'), timestamp: sql.placeholder('timestamp') }).prepare().run({ id: session.id, user_id: session.user.id, timestamp: new Date() });
|
||||
return session;
|
||||
}
|
||||
Loading…
Reference in New Issue