From d7a3e8d49c0b9c0ef37299c08afbf5fce71a6455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rald=20Leban?= Date: Fri, 5 Dec 2025 10:09:05 +0100 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20ajouter=20la=20table=20utilisateur?= =?UTF-8?q?=20et=20l'=C3=A9num=C3=A9ration=20des=20r=C3=B4les?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/db/schema.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/utils/db/schema.ts b/src/utils/db/schema.ts index 0dc3c7e..0283ba5 100644 --- a/src/utils/db/schema.ts +++ b/src/utils/db/schema.ts @@ -1,5 +1,20 @@ import { relations } from 'drizzle-orm'; -import { integer, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core'; +import { integer, pgEnum, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core'; + +/** + * Énumération des rôles attribuables à un utilisateur + */ +export const UserRoles = ['seller', 'TO'] as [string, ...string[]]; +export const userRoles = pgEnum('user_roles', UserRoles); + +/** + * Tables des utilisateurs + */ +export const usersTable = pgTable('users', { + id: uuid().defaultRandom().primaryKey(), + name: text().notNull().unique(), + role: userRoles().notNull(), +}); /** * Table des séries d'événements From 5b8d0c194f4ce3974bc7159940d4c9636d2850e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rald=20Leban?= Date: Fri, 5 Dec 2025 14:25:38 +0100 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20cr=C3=A9er=20et=20supprimer=20un=20?= =?UTF-8?q?utilisateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 3 ++- src/modules/authentication/index.ts | 14 +++++++++++ src/modules/authentication/model.ts | 27 ++++++++++++++++++++ src/modules/authentication/service.ts | 36 +++++++++++++++++++++++++++ src/utils/db/schema.ts | 2 +- 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/modules/authentication/index.ts create mode 100644 src/modules/authentication/model.ts create mode 100644 src/modules/authentication/service.ts diff --git a/src/index.ts b/src/index.ts index 54a86e9..069853c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { Elysia } from 'elysia'; +import { authenticationModule } from './modules/authentication'; import { seriesModule } from './modules/series'; -const app = new Elysia().use(seriesModule).listen(3000); +const app = new Elysia().use(seriesModule).use(authenticationModule).listen(3000); console.log(`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`); diff --git a/src/modules/authentication/index.ts b/src/modules/authentication/index.ts new file mode 100644 index 0000000..348d969 --- /dev/null +++ b/src/modules/authentication/index.ts @@ -0,0 +1,14 @@ +import Elysia from 'elysia'; +import { AuthenticationModel } from './model'; +import { AuthenticationService } from './service'; + +export const authenticationModule = new Elysia({ prefix: '/authentication' }) + // POST /authentication/register + // Créer un nouvel utilisateur + .post('/register', async ({ body }) => AuthenticationService.createUser(body), { + body: AuthenticationModel.createUsersBody, + }) + // DELETE /authentication/delete + .delete('/delete', async ({ body }) => AuthenticationService.deleteUser(body), { + body: AuthenticationModel.deleteUsersBody, + }); diff --git a/src/modules/authentication/model.ts b/src/modules/authentication/model.ts new file mode 100644 index 0000000..41cf59f --- /dev/null +++ b/src/modules/authentication/model.ts @@ -0,0 +1,27 @@ +import { UserRoles } from '@/utils/db/schema'; +import { t } from 'elysia'; + +export namespace AuthenticationModel { + export const createUsersBody = t.Object({ + name: t.String({ + minLength: 1, + }), + role: t.UnionEnum(UserRoles, { + default: undefined, + }), + }); + + export type CreateUserBody = typeof createUsersBody.static; + + export const findUsersByNameBody = t.Object({ + name: t.String({ minLength: 1 }), + }); + + export type FindUserByNameBody = typeof findUsersByNameBody.static; + + export const deleteUsersBody = t.Object({ + id: t.String({ format: 'uuid' }), + }); + + export type DeleteUserBody = typeof deleteUsersBody.static; +} diff --git a/src/modules/authentication/service.ts b/src/modules/authentication/service.ts new file mode 100644 index 0000000..5984a86 --- /dev/null +++ b/src/modules/authentication/service.ts @@ -0,0 +1,36 @@ +import { db } from '@/utils/db'; +import { usersTable } from '@/utils/db/schema'; +import { eq } from 'drizzle-orm'; +import { status } from 'elysia'; +import { AuthenticationModel } from './model'; + +export abstract class AuthenticationService { + static async findUserByName(data: AuthenticationModel.FindUserByNameBody) { + return db.query.usersTable.findFirst({ + where: eq(usersTable.name, data.name), + }); + } + + static async createUser(data: AuthenticationModel.CreateUserBody) { + const existingUser = await AuthenticationService.findUserByName(data); + if (existingUser) { + throw status(409, 'Un utilisateur avec ce nom existe déjà.'); + } + + const [createdUser] = await db.insert(usersTable).values(data).returning(); + + return status(201, createdUser); + } + + static async deleteUser(data: AuthenticationModel.DeleteUserBody) { + const [deletedUser] = await db.delete(usersTable).where(eq(usersTable.id, data.id)).returning({ + id: usersTable.id, + }); + + if (!deletedUser) { + throw status(404); + } + + return status(204); + } +} diff --git a/src/utils/db/schema.ts b/src/utils/db/schema.ts index 0283ba5..0184aff 100644 --- a/src/utils/db/schema.ts +++ b/src/utils/db/schema.ts @@ -4,7 +4,7 @@ import { integer, pgEnum, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg- /** * Énumération des rôles attribuables à un utilisateur */ -export const UserRoles = ['seller', 'TO'] as [string, ...string[]]; +export const UserRoles = ['TO'] as [string, ...string[]]; export const userRoles = pgEnum('user_roles', UserRoles); /** From f4a210eeb502fdcebb3bd71e29f44ebc639051a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rald=20Leban?= Date: Fri, 5 Dec 2025 14:29:40 +0100 Subject: [PATCH 3/3] chore: ajouter @elysiajs/jwt --- bun.lock | 6 +++++- package.json | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bun.lock b/bun.lock index 78c7928..c556c18 100644 --- a/bun.lock +++ b/bun.lock @@ -1,10 +1,10 @@ { "lockfileVersion": 1, - "configVersion": 0, "workspaces": { "": { "name": "PNReST", "dependencies": { + "@elysiajs/jwt": "^1.4.0", "drizzle-orm": "^0.44.7", "drizzle-typebox": "^0.3.3", "elysia": "latest", @@ -23,6 +23,8 @@ "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], + "@elysiajs/jwt": ["@elysiajs/jwt@1.4.0", "", { "dependencies": { "jose": "^6.0.11" }, "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-Z0PvZhQxdDeKZ8HslXzDoXXD83NKExNPmoiAPki3nI2Xvh5wtUrBH+zWOD17yP14IbRo8fxGj3L25MRCAPsgPA=="], + "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], @@ -125,6 +127,8 @@ "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="], + "memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], diff --git a/package.json b/package.json index b051d9e..cbc7621 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "db:migrate": "bun --bun drizzle-kit migrate" }, "dependencies": { + "@elysiajs/jwt": "^1.4.0", "drizzle-orm": "^0.44.7", "drizzle-typebox": "^0.3.3", "elysia": "latest",