Tests connexion
This commit is contained in:
parent
edf23bdbaa
commit
fb58a24170
8
app.vue
8
app.vue
|
|
@ -34,12 +34,12 @@ onMounted(() => {
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="gapx-3 flex align-stretch">
|
<div class="gapx-3 flex align-stretch">
|
||||||
<NuxtLink @click="hideLeftPanel" class="site-nav-bar-text" aria-label="Accueil" :href="'/'">
|
<NuxtLink @click="hideLeftPanel" class="site-nav-bar-text" aria-label="Accueil" to="/">
|
||||||
<ThemeIcon icon="logo" :width=40 :height=40 />
|
<ThemeIcon icon="logo" :width=40 :height=40 />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink class="site-nav-bar-text mobile-hidden" aria-label="Systeme" :href="'/explorer'"
|
<NuxtLink class="site-nav-bar-text mobile-hidden" aria-label="Systeme" to="/explorer"
|
||||||
:class="{'mod-active': $route.path.startsWith('/explorer')}">Systeme</NuxtLink>
|
:class="{'mod-active': $route.path.startsWith('/explorer')}">Systeme</NuxtLink>
|
||||||
<NuxtLink class="site-nav-bar-text mobile-hidden" aria-label="Outils" :href="'/tools'"
|
<NuxtLink class="site-nav-bar-text mobile-hidden" aria-label="Outils" to="/tools"
|
||||||
:class="{'mod-active': $route.path.startsWith('/tools')}">Outils</NuxtLink>
|
:class="{'mod-active': $route.path.startsWith('/tools')}">Outils</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -48,7 +48,7 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
<div class="ps-1 gapx-1 flex align-center">
|
<div class="ps-1 gapx-1 flex align-center">
|
||||||
<ThemeSwitch class="mobile-hidden" />
|
<ThemeSwitch class="mobile-hidden" />
|
||||||
<NuxtLink class="site-login" href="/user/profile">
|
<NuxtLink class="site-login" to="/user/profile">
|
||||||
<ThemeIcon icon="user" :width=32 :height=32 />
|
<ThemeIcon icon="user" :width=32 :height=32 />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -270,4 +270,11 @@ html.light-mode .light-block {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
animation: rotate 1s linear infinite;
|
animation: rotate 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-form a {
|
||||||
|
padding: .5em;
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: var(--font-extrabold);
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +116,7 @@ function hidePreview(e: Event) {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template >
|
<template>
|
||||||
<template v-if="href !== ''">
|
<template v-if="href !== ''">
|
||||||
<a @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs"
|
<a @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs"
|
||||||
:href="stringifyParsedURL({ host: '/explorer', pathname: (content?._path ?? href) + (isTag && anchor ? '/' + anchor.substring(1) : ''), hash: !isTag ? anchor : '', search: '' })"
|
:href="stringifyParsedURL({ host: '/explorer', pathname: (content?._path ?? href) + (isTag && anchor ? '/' + anchor.substring(1) : ''), hash: !isTag ? anchor : '', search: '' })"
|
||||||
|
|
@ -160,7 +160,7 @@ function hidePreview(e: Event) {
|
||||||
</div>
|
</div>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</template>
|
</template>
|
||||||
<a v-bind="$attrs" :href="href" :target="target" v-else>
|
<NuxtLink v-bind="$attrs" :to="href" v-else>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</a>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
toc: Toc;
|
toc: Toc;
|
||||||
|
comments?: Comment[];
|
||||||
}
|
}
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -9,14 +10,11 @@ const props = defineProps<Props>();
|
||||||
<template>
|
<template>
|
||||||
<div class="site-body-right-column">
|
<div class="site-body-right-column">
|
||||||
<div class="site-body-right-column-inner">
|
<div class="site-body-right-column-inner">
|
||||||
|
<div v-if="comments !== undefined">
|
||||||
|
{{ comments.length }} commentaire{{ comments.length === 1 ? '' : 's' }}
|
||||||
|
</div>
|
||||||
<div v-if="!!toc" class="outline-view-outer node-insert-event">
|
<div v-if="!!toc" class="outline-view-outer node-insert-event">
|
||||||
<div class="list-item published-section-header">
|
<div class="list-item published-section-header">
|
||||||
<span class="published-section-header-icon">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-list">
|
|
||||||
<line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line>
|
|
||||||
<line x1="3" y1="18" x2="3.01" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span>Sur cette page</span>
|
<span>Sur cette page</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="outline-view">
|
<div class="outline-view">
|
||||||
|
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
export enum AuthStatus
|
|
||||||
{
|
|
||||||
disconnected, loading, connected
|
|
||||||
};
|
|
||||||
export interface Auth
|
|
||||||
{
|
|
||||||
id: Ref<number>;
|
|
||||||
data: Ref<Record<string, any>>;
|
|
||||||
sessionId: Ref<string>;
|
|
||||||
status: Ref<AuthStatus>;
|
|
||||||
|
|
||||||
lastRefresh: Ref<Date>;
|
|
||||||
|
|
||||||
register: (username: string, email: string, password: string, data?: Record<string, any>) => Promise<any>;
|
|
||||||
login: (usernameOrEmail: string, password: string) => Promise<void>;
|
|
||||||
logout: () => Promise<void>;
|
|
||||||
|
|
||||||
refresh: () => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function register(username: string, email: string, password: string, additionalData?: Record<string, any>): Promise<any>
|
|
||||||
{
|
|
||||||
const id = useState<number>("auth:id");
|
|
||||||
const data = useState<any>("auth:data");
|
|
||||||
const sessionId = useState<string>("auth:sessionId");
|
|
||||||
const status = useState<AuthStatus>("auth:status");
|
|
||||||
const lastRefresh = useState<Date>("auth:date");
|
|
||||||
status.value = AuthStatus.loading;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const result = await $fetch("/api/auth/register", {
|
|
||||||
method: 'POST',
|
|
||||||
body: { username, email, password, additionalData },
|
|
||||||
ignoreResponseError: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if(result.success)
|
|
||||||
{
|
|
||||||
id.value = result.id!;
|
|
||||||
data.value = { ...additionalData, username: username, email: email };
|
|
||||||
sessionId.value = result.sessionId!;
|
|
||||||
status.value = AuthStatus.connected;
|
|
||||||
lastRefresh.value = new Date();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(result.error)
|
|
||||||
{
|
|
||||||
status.value = AuthStatus.disconnected;
|
|
||||||
|
|
||||||
return result.error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status.value = AuthStatus.disconnected;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
console.log(JSON.stringify(e));
|
|
||||||
status.value = AuthStatus.disconnected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function login(usernameOrEmail: string, password: string): Promise<void>
|
|
||||||
{
|
|
||||||
const status = useState<AuthStatus>("auth:status");
|
|
||||||
status.value = AuthStatus.disconnected;
|
|
||||||
}
|
|
||||||
async function logout(): Promise<void>
|
|
||||||
{
|
|
||||||
const status = useState<AuthStatus>("auth:status");
|
|
||||||
status.value = AuthStatus.disconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refresh(): Promise<void>
|
|
||||||
{
|
|
||||||
const status = useState<AuthStatus>("auth:status");
|
|
||||||
status.value = AuthStatus.disconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function useAuth(): Auth {
|
|
||||||
const id = useState<number>("auth:id", () => 0);
|
|
||||||
const data = useState<any>("auth:data", () => { });
|
|
||||||
const sessionId = useState<string>("auth:sessionId", () => '');
|
|
||||||
const status = useState<AuthStatus>("auth:status", () => AuthStatus.disconnected);
|
|
||||||
|
|
||||||
const lastRefresh = useState<Date>("auth:date", () => new Date());
|
|
||||||
|
|
||||||
return {
|
|
||||||
id, data, sessionId, status, lastRefresh,
|
|
||||||
register, login, logout, refresh
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
export default defineNuxtRouteMiddleware((to) => {
|
|
||||||
const meta = to.meta.auth;
|
|
||||||
|
|
||||||
//useSession(to.)
|
|
||||||
|
|
||||||
return to;
|
|
||||||
})
|
|
||||||
|
|
@ -7,18 +7,22 @@ function toggleLeftPanel(_: Event) {
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { hash, path } = useRoute();
|
const { hash, path } = useRoute();
|
||||||
|
const route = path.substring(path.indexOf('/explorer') + '/explorer'.length);
|
||||||
|
|
||||||
const { data: page } = await useAsyncData('home', queryContent(path.substring(path.indexOf('/explorer') + '/explorer'.length)).findOne);
|
const { data: page } = await useAsyncData('home', queryContent(route).findOne);
|
||||||
|
const { data: comments } = await useFetch(`/api/comments`, {
|
||||||
|
query: {
|
||||||
|
route: route
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if(page.value)
|
if(page.value)
|
||||||
useContentHead(page.value!);
|
|
||||||
|
|
||||||
if(hash)
|
|
||||||
{
|
{
|
||||||
console.log(document.getElementById(hash.substring(1)));
|
useContentHead(page.value!);
|
||||||
document.getElementById(hash.substring(1))?.scrollTo({ behavior: 'smooth', top: 100 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const content = ref();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
document.querySelectorAll('.callout.is-collapsible .callout-title').forEach(e => {
|
document.querySelectorAll('.callout.is-collapsible .callout-title').forEach(e => {
|
||||||
e.addEventListener('click', (_) => {
|
e.addEventListener('click', (_) => {
|
||||||
|
|
@ -53,7 +57,7 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<RightComponent v-if="page.body?.toc" :toc="page?.body?.toc" />
|
<RightComponent v-if="page.body?.toc" :toc="page?.body?.toc" :comments="comments" />
|
||||||
</template>
|
</template>
|
||||||
<CanvasRenderer v-else-if="!!page && page._type == 'canvas'" :key="page._id" :canvas="page" />
|
<CanvasRenderer v-else-if="!!page && page._type == 'canvas'" :key="page._id" :canvas="page" />
|
||||||
<div v-else-if="!!page">
|
<div v-else-if="!!page">
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,70 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({
|
import { schema, type Login } from '~/schemas/login';
|
||||||
auth: {
|
|
||||||
unauthenticatedOnly: true,
|
definePageMeta({
|
||||||
navigateAuthenticatedTo: '/user/profile'
|
auth: {
|
||||||
|
disconnectedOnly: true,
|
||||||
|
connectedRedirect: '/user/profile'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const state = reactive<Login>({
|
||||||
|
username: '',
|
||||||
|
password: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const { status, login } = useAuth();
|
||||||
|
|
||||||
|
const usernameError = ref("");
|
||||||
|
const passwordError = ref("");
|
||||||
|
|
||||||
|
async function submit()
|
||||||
|
{
|
||||||
|
const data = schema.safeParse(state);
|
||||||
|
|
||||||
|
if(data.success && state.password !== "")
|
||||||
|
{
|
||||||
|
let errors = await login(data.data.username, data.data.password);
|
||||||
|
|
||||||
|
if(status.value === AuthStatus.connected)
|
||||||
|
{
|
||||||
|
await navigateTo('/user/profile', { replace: true });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errors = errors?.issues ?? errors;
|
||||||
|
usernameError.value = errors?.find((e: any) => e.path.includes("username"))?.message ?? "";
|
||||||
|
passwordError.value = errors?.find((e: any) => e.path.includes("password"))?.message ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usernameError.value = data.error?.issues.find(e => e.path.includes("username"))?.message ?? "";
|
||||||
|
passwordError.value = data.error?.issues.find(e => e.path.includes("password"))?.message ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Head>
|
<Head>
|
||||||
<Title>Se connecter</Title>
|
<Title>Se connecter</Title>
|
||||||
</Head>
|
</Head>
|
||||||
|
<div class="site-body-center-column">
|
||||||
|
<div class="render-container flex align-center justify-center">
|
||||||
|
<form v-if="status === AuthStatus.disconnected" @submit.prevent="submit" class="input-form input-form-wide">
|
||||||
|
<h1>Connexion</h1>
|
||||||
|
<Input type="text" autocomplete="username" v-model="state.username"
|
||||||
|
placeholder="" title="Nom d'utilisateur ou adresse mail" :error="usernameError" />
|
||||||
|
<Input type="password" autocomplete="current-password" v-model="state.password"
|
||||||
|
placeholder="" title="Mot de passe"
|
||||||
|
:error="passwordError" />
|
||||||
|
<button>Se connecter</button>
|
||||||
|
<NuxtLink to="/user/register">Pas de compte ?</NuxtLink>
|
||||||
|
</form>
|
||||||
|
<div v-else-if="status === AuthStatus.loading" class="input-form"><div class="loading"></div></div>
|
||||||
|
<div v-else class="not-found-container">
|
||||||
|
<div class="not-found-title">👀 Vous n'avez rien à faire ici. 👀</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
auth: {
|
auth: {
|
||||||
unauthenticatedOnly: false,
|
disconnectedOnly: false,
|
||||||
navigateUnauthenticatedTo: '/user/login'
|
disconnectedRedirect: '/user/login'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { schema, type Registration } from '~/schemas/registration';
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
auth: {
|
auth: {
|
||||||
unauthenticatedOnly: true,
|
disconnectedOnly: true,
|
||||||
navigateAuthenticatedTo: '/user/profile'
|
connectedRedirect: '/user/profile'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -86,7 +86,8 @@ async function submit()
|
||||||
<Input type="password" v-model="confirmPassword" placeholder="Confirmer le mot de passe"
|
<Input type="password" v-model="confirmPassword" placeholder="Confirmer le mot de passe"
|
||||||
title="Confirmer le mot de passe"
|
title="Confirmer le mot de passe"
|
||||||
:error="confirmPassword === '' || confirmPassword === state.password ? '' : 'Les mots de passe saisies ne sont pas identique'" />
|
:error="confirmPassword === '' || confirmPassword === state.password ? '' : 'Les mots de passe saisies ne sont pas identique'" />
|
||||||
<button>Valider</button>
|
<button>S'inscrire</button>
|
||||||
|
<NuxtLink to="/user/login">Se connecter</NuxtLink>
|
||||||
</form>
|
</form>
|
||||||
<div v-else-if="status === AuthStatus.loading" class="input-form"><div class="loading"></div></div>
|
<div v-else-if="status === AuthStatus.loading" class="input-form"><div class="loading"></div></div>
|
||||||
<div v-else class="not-found-container">
|
<div v-else class="not-found-container">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const schema = z.object({
|
||||||
|
username: z.string({ required_error: "Nom d'utilisateur obligatoire" }),
|
||||||
|
password: z.string({ required_error: "Mot de passe obligatoire" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Login = z.infer<typeof schema>;
|
||||||
|
|
@ -1,3 +1,96 @@
|
||||||
|
import useDatabase from '~/composables/useDatabase';
|
||||||
|
import { schema } from '~/schemas/login';
|
||||||
|
|
||||||
export default defineEventHandler(async (e) => {
|
export default defineEventHandler(async (e) => {
|
||||||
|
const { sessionPassword } = useRuntimeConfig();
|
||||||
|
const session = await useSession(e, {
|
||||||
|
password: sessionPassword,
|
||||||
|
});
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const db = useDatabase();
|
||||||
|
|
||||||
|
console.log(session.id);
|
||||||
|
|
||||||
|
if(session.id && session.data.id)
|
||||||
|
{
|
||||||
|
const checkSession = db.query("SELECT user_id FROM user_sessions WHERE id = ?1");
|
||||||
|
const sessionId = checkSession.get(session.id) as any;
|
||||||
|
|
||||||
|
console.log(sessionId);
|
||||||
|
|
||||||
|
if(sessionId && sessionId.user_id === session.data.id)
|
||||||
|
{
|
||||||
|
return { success: true, id: session.data.id, sessionId: session.id, data: session.data };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
setResponseStatus(e, 406);
|
||||||
|
return { success: false, error: { path: ['global'], message: 'Vous êtes déjà connecté' } };
|
||||||
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
const body = await readValidatedBody(e, schema.safeParse);
|
||||||
|
|
||||||
|
if (!body.success)
|
||||||
|
{
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
setResponseStatus(e, 406);
|
||||||
|
return { success: false, error: body.error };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const hash = await Bun.password.hash(body.data.password);
|
||||||
|
const checkID = db.query(`SELECT id FROM users WHERE (username = ?1 or email = ?1)`);
|
||||||
|
const id = checkID.get(body.data.username) as any;
|
||||||
|
|
||||||
|
if(!id || !id.id)
|
||||||
|
{
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
setResponseStatus(e, 401);
|
||||||
|
return { success: false, error: { path: ['username'], message: 'Identifiant inconnu' } };
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkHash = db.query(`SELECT COUNT(*) as count FROM users WHERE id = ?1 and hash = ?2`);
|
||||||
|
const validation = checkHash.get(id.id, hash) as any;
|
||||||
|
|
||||||
|
if(validation && validation.count && validation.count !== 1)
|
||||||
|
{
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
setResponseStatus(e, 401);
|
||||||
|
return { success: false, error: { path: ['password'], message: 'Mot de passe incorrect' } };
|
||||||
|
}
|
||||||
|
|
||||||
|
const loggingIn = db.query(`INSERT INTO user_sessions(id, user_id, ip, agent, lastRefresh) VALUES(?1, ?2, ?3, ?4, ?5)`);
|
||||||
|
loggingIn.get(session.id, id.id, getRequestIP(e), getRequestHeader(e, 'User-Agent'), Date.now());
|
||||||
|
|
||||||
|
await session.update(getData(db, id.id));
|
||||||
|
|
||||||
|
setResponseStatus(e, 201);
|
||||||
|
return { success: true, id: id.id, sessionId: session.id, data: session.data };
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
console.error(e);
|
||||||
|
return { success: false, error: e };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function getData(db: Database, id: string): any
|
||||||
|
{
|
||||||
|
const userQuery = db.query(`SELECT * FROM users WHERE id = ?1`);
|
||||||
|
const user = userQuery.get(id);
|
||||||
|
|
||||||
|
const userDataQuery = db.query(`SELECT * FROM users_data WHERE user_id = ?1`);
|
||||||
|
const userData = userDataQuery.get(id);
|
||||||
|
|
||||||
|
return { ...user, ...userData };
|
||||||
|
}
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
export default defineEventHandler(async (e) => {
|
|
||||||
});
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import useDatabase from '~/composables/useDatabase';
|
||||||
|
|
||||||
|
export interface Comment
|
||||||
|
{
|
||||||
|
user: number;
|
||||||
|
file: string;
|
||||||
|
position: number;
|
||||||
|
length: number;
|
||||||
|
sequence: number;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
export default defineEventHandler(async (e) => {
|
||||||
|
const query = getQuery(e);
|
||||||
|
|
||||||
|
if(query && query.route !== undefined)
|
||||||
|
{
|
||||||
|
const db = useDatabase();
|
||||||
|
|
||||||
|
const comments = db.query("SELECT * FROM comments WHERE file = ?1").all(query.route as string) as Comment[];
|
||||||
|
|
||||||
|
return comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
setResponseStatus(e, 404);
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue