diff --git a/bun.lockb b/bun.lockb index 5948c7b..d37f33e 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/standard/SearchView.vue b/components/standard/SearchView.vue index 2afdb83..4f48dc2 100644 --- a/components/standard/SearchView.vue +++ b/components/standard/SearchView.vue @@ -76,7 +76,7 @@ async function debounced()
+ @mousedown.prevent="navigateTo(`/users/${result.id}`); input = ''; emit('navigate');">
diff --git a/db.sqlite b/db.sqlite index 4200a9b..c73c06c 100644 Binary files a/db.sqlite and b/db.sqlite differ diff --git a/modules/database.sync/module.ts b/modules/database.sync/module.ts index 24d6799..8989b14 100644 --- a/modules/database.sync/module.ts +++ b/modules/database.sync/module.ts @@ -26,22 +26,41 @@ export default defineNuxtModule({ const db = new Database(nuxt.options.runtimeConfig.dbFile); db.exec(`PRAGMA foreign_keys = 0`); + const oldSchema = db.query(`SELECT * FROM sqlite_schema WHERE type = 'table'`).all() as Schema[]; const structure = db.query(`SELECT * FROM pragma_table_info(?1)`); - (db.transaction((tables: Schema[]) => { + (db.transaction((tables: Schema[], oldTables: Schema[]) => { for(const table of tables) { + const oldIdx = oldTables.findIndex(e => e.name === table.name); + if(table.name === 'sqlite_sequence') + { + oldTables.splice(oldIdx, 1); continue; + } const columns = structure.all(table.name) as Structure[]; - db.exec(`ALTER TABLE ${table.name} RENAME TO ${table.name}_old`); - db.exec(table.sql); - db.exec(`INSERT INTO ${table.name} (${columns.map(e => `"${e.name}"`).join(', ')}) SELECT * FROM ${table.name}_old`); - db.exec(`DROP TABLE ${table.name}_old`); + if(oldIdx !== -1) + { + oldTables.splice(oldIdx, 1); + + db.exec(`ALTER TABLE ${table.name} RENAME TO ${table.name}_old`); + db.exec(table.sql); + db.exec(`INSERT INTO ${table.name} (${columns.map(e => `"${e.name}"`).join(', ')}) SELECT * FROM ${table.name}_old`); + db.exec(`DROP TABLE ${table.name}_old`); + } + else + { + db.exec(table.sql); + } } - })).immediate(schema); + for(const table of oldTables) + { + db.exec(`DROP TABLE ${table.name}`); + } + })).immediate(schema, oldSchema); db.exec(`PRAGMA foreign_keys = 1`); diff --git a/pages/[...slug].vue b/pages/[...slug].vue index ee7f12f..09c7c43 100644 --- a/pages/[...slug].vue +++ b/pages/[...slug].vue @@ -2,13 +2,8 @@ Inconnu -
-
-
-
-
Introuvable
-
Cette page n'existe pas
-
-
+
+
Introuvable
+
Cette page n'existe pas
\ No newline at end of file diff --git a/pages/users/[id].vue b/pages/users/[id].vue index e7024c0..7180fc9 100644 --- a/pages/users/[id].vue +++ b/pages/users/[id].vue @@ -1,6 +1,31 @@ + + \ No newline at end of file diff --git a/server/api/auth/register.post.ts b/server/api/auth/register.post.ts index bf3a59f..c173807 100644 --- a/server/api/auth/register.post.ts +++ b/server/api/auth/register.post.ts @@ -62,13 +62,13 @@ export default defineEventHandler(async (e): Promise => { { const hash = await Bun.password.hash(body.data.password); const registration = db.query(`INSERT INTO users(username, email, hash, state) VALUES(?1, ?2, ?3, 0)`); - registration.get(body.data.username, body.data.email, hash) as any; + registration.run(body.data.username, body.data.email, hash); const userIdQuery = db.query(`SELECT id FROM users WHERE username = ?1`); const id = (userIdQuery.get(body.data.username) as any).id; - const registeringData = db.query(`INSERT INTO users_data(user_id) VALUES(?1)`); - registeringData.get(id); + const registeringData = db.query(`INSERT INTO users_data(user_id, signin_timestamp) VALUES(?1, ?2)`); + registeringData.run(id, Date.now()); logSession(e, await setUserSession(e, { user: { id: id, username: body.data.username, email: body.data.email, state: 0 } }) as UserSessionRequired); diff --git a/server/api/users/[id].get.ts b/server/api/users/[id].get.ts index d45318d..1e65580 100644 --- a/server/api/users/[id].get.ts +++ b/server/api/users/[id].get.ts @@ -12,5 +12,5 @@ export default defineEventHandler((e) => { const db = useDatabase(); - return db.query(`SELECT id, usernamme, email, state FROM users WHERE id = ?1`).get(id) as User; + return db.query(`SELECT id, username, email, state, d.* FROM users u LEFT JOIN users_data d ON u.id = d.user_id WHERE u.id = ?1`).get(id) as User; }); \ No newline at end of file diff --git a/server/api/users/[id]/comments.get.ts b/server/api/users/[id]/comments.get.ts new file mode 100644 index 0000000..db50495 --- /dev/null +++ b/server/api/users/[id]/comments.get.ts @@ -0,0 +1,16 @@ +import useDatabase from "~/composables/useDatabase"; +import type { Comment } from "~/types/auth"; + +export default defineEventHandler((e) => { + const id = getRouterParam(e, 'id'); + + if(!id) + { + setResponseStatus(e, 400); + return; + } + + const db = useDatabase(); + + return db.query(`SELECT * FROM explorer_comments WHERE user_id = ?1`).all(id) as Comment[]; +}); \ No newline at end of file diff --git a/server/api/users/[id]/projects.get.ts b/server/api/users/[id]/projects.get.ts new file mode 100644 index 0000000..b96dff4 --- /dev/null +++ b/server/api/users/[id]/projects.get.ts @@ -0,0 +1,16 @@ +import useDatabase from "~/composables/useDatabase"; +import type { Project } from "~/types/api"; + +export default defineEventHandler((e) => { + const id = getRouterParam(e, 'id'); + + if(!id) + { + setResponseStatus(e, 400); + return; + } + + const db = useDatabase(); + + return db.query(`SELECT * FROM explorer_projects WHERE owner = ?1`).all(id) as Project[]; +}); \ No newline at end of file diff --git a/server/plugins/session.ts b/server/plugins/session.ts index 8701e58..0fb0e4c 100644 --- a/server/plugins/session.ts +++ b/server/plugins/session.ts @@ -11,10 +11,12 @@ export default defineNitroPlugin(() => { if(!result) { + clearUserSession(event); throw createError({ statusCode: 401, message: 'Unauthorized' }); } else if(result && result.lastRefresh && result.lastRefresh < Date.now() - monthAsMs) { + clearUserSession(event); throw createError({ statusCode: 401, message: 'Session has expired' }); } else @@ -25,8 +27,12 @@ export default defineNitroPlugin(() => { sessionHooks.hook('clear', async (session, event) => { if(session.id && session.user) { - const query = db.prepare('DELETE FROM user_sessions WHERE id = ?1 AND user_id = ?2'); - query.run(session.id, session.user.id); + try + { + const query = db.prepare('DELETE FROM user_sessions WHERE id = ?1 AND user_id = ?2'); + query.run(session.id, session.user.id); + } + catch(e) { } } }); }); \ No newline at end of file diff --git a/template.sqlite b/template.sqlite index 381db22..903b355 100644 Binary files a/template.sqlite and b/template.sqlite differ diff --git a/types/auth.d.ts b/types/auth.d.ts index f2a8be5..0010eb9 100644 --- a/types/auth.d.ts +++ b/types/auth.d.ts @@ -28,7 +28,7 @@ export interface UserRawData { } export interface UserExtendedData { - + signin_timestamp: number; } export type User = UserRawData & UserExtendedData; diff --git a/utils/utils.ts b/utils/utils.ts index 8a5a4d8..44a45a7 100644 --- a/utils/utils.ts +++ b/utils/utils.ts @@ -5,4 +5,31 @@ export function unifySlug(slug: string | string[]): string export function parseId(id: string | undefined): string |undefined { return id?.normalize('NFD')?.replace(/[\u0300-\u036f]/g, '')?.replace(/^\d\. */g, '')?.replace(/\s/g, "-")?.replace(/%/g, "-percent")?.replace(/\?/g, "-q")?.toLowerCase(); +} +export function padLeft(text: string, pad: string, length: number): string +{ + return text.concat(pad.repeat(length - text.length)); +} +export function padRight(text: string, pad: string, length: number): string +{ + return pad.repeat(length - text.length).concat(text); +} +export function format(date: Date, template: string): string +{ + const transforms = { + "yyyy": (date: Date) => date.getUTCFullYear().toString(), + "MM": (date: Date) => padRight((date.getUTCMonth() + 1).toString(), '0', 2), + "dd": (date: Date) => padRight(date.getUTCDate().toString(), '0', 2), + "mm": (date: Date) => padRight(date.getFullYear().toString(), '0', 2), + "HH": (date: Date) => padRight(date.getFullYear().toString(), '0', 2), + "ss": (date: Date) => padRight(date.getFullYear().toString(), '0', 2), + }; + const keys = Object.keys(transforms); + + for(const key of keys) + { + template = template.replaceAll(key, () => transforms[key](date)); + } + + return template; } \ No newline at end of file