diff --git a/server/prisma/migrations/20251225143531_user_preferences/migration.sql b/server/prisma/migrations/20251225143531_user_preferences/migration.sql new file mode 100644 index 0000000..0cf4c7e --- /dev/null +++ b/server/prisma/migrations/20251225143531_user_preferences/migration.sql @@ -0,0 +1,10 @@ +-- CreateTable +CREATE TABLE "UserPreferences" ( + "userId" TEXT NOT NULL PRIMARY KEY, + "toggleInputHotkey" TEXT NOT NULL, + "toggleOutputHotkey" TEXT NOT NULL, + CONSTRAINT "UserPreferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateIndex +CREATE INDEX "Session_userId_idx" ON "Session"("userId"); diff --git a/server/prisma/migrations/20251225145827_user_preferences_volumes/migration.sql b/server/prisma/migrations/20251225145827_user_preferences_volumes/migration.sql new file mode 100644 index 0000000..95ee7c3 --- /dev/null +++ b/server/prisma/migrations/20251225145827_user_preferences_volumes/migration.sql @@ -0,0 +1,21 @@ +/* + Warnings: + + - Added the required column `volumes` to the `UserPreferences` table without a default value. This is not possible if the table is not empty. + +*/ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_UserPreferences" ( + "userId" TEXT NOT NULL PRIMARY KEY, + "toggleInputHotkey" TEXT NOT NULL, + "toggleOutputHotkey" TEXT NOT NULL, + "volumes" JSONB NOT NULL, + CONSTRAINT "UserPreferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_UserPreferences" ("toggleInputHotkey", "toggleOutputHotkey", "userId") SELECT "toggleInputHotkey", "toggleOutputHotkey", "userId" FROM "UserPreferences"; +DROP TABLE "UserPreferences"; +ALTER TABLE "new_UserPreferences" RENAME TO "UserPreferences"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 1e46093..bfe776a 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -9,22 +9,32 @@ generator client { } model User { - id String @id @default(cuid()) - username String @unique - password String - displayName String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + username String @unique + password String + displayName String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - Session Session[] + Session Session[] + UserPreferences UserPreferences? } model Session { - id String @id + id String @id userId String expiresAt DateTime - user User @relation(references: [id], fields: [userId], onDelete: Cascade) + user User @relation(references: [id], fields: [userId], onDelete: Cascade) @@index([userId]) +} + +model UserPreferences { + userId String @id + toggleInputHotkey String + toggleOutputHotkey String + volumes Json + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) } \ No newline at end of file diff --git a/server/routes/user.ts b/server/routes/user.ts new file mode 100644 index 0000000..7c3c237 --- /dev/null +++ b/server/routes/user.ts @@ -0,0 +1,46 @@ +import type { FastifyInstance } from 'fastify' +import { z } from 'zod' +import prisma from '../prisma/client.ts' + +export default function (fastify: FastifyInstance) { + fastify.get('/preferences', async (req, reply) => { + if (req.user) { + return prisma.userPreferences.findFirst({ where: { userId: req.user.id } }) + } + + reply.code(401).send(false) + }) + + fastify.patch('/preferences', async (req, reply) => { + if (!req.user) { + reply.code(401).send(false) + + return + } + + try { + const schema = z.object({ + toggleInputHotkey: z.string(), + toggleOutputHotkey: z.string(), + volumes: z.record(z.string(), z.number()), + }) + const input = schema.parse(req.body) + + return prisma.userPreferences.update({ + where: { userId: req.user.id }, + data: input, + }) + } + catch (err) { + fastify.log.error(err) + reply.code(400) + + if (err instanceof z.ZodError) { + reply.send({ error: z.prettifyError(err) }) + } + else { + reply.send({ error: err.message }) + } + } + }) +}