From 58f077950c92ad7cca15ce7796482be057d92e21 Mon Sep 17 00:00:00 2001 From: Douglas Barone Date: Thu, 15 Jun 2023 15:55:09 -0400 Subject: [PATCH] Refactor --- .../migrations/20230615181742_/migration.sql | 28 ++++++++ prisma/schema.prisma | 27 +++++++- prisma/seed.ts | 35 ++++++++-- src/controllers/routes/UserRouteController.ts | 2 +- src/index.ts | 68 +------------------ src/middleware/hasRolesMiddleware.ts | 8 +-- src/server.ts | 67 ++++++++++++++++++ 7 files changed, 155 insertions(+), 80 deletions(-) create mode 100644 prisma/migrations/20230615181742_/migration.sql create mode 100644 src/server.ts diff --git a/prisma/migrations/20230615181742_/migration.sql b/prisma/migrations/20230615181742_/migration.sql new file mode 100644 index 0000000..4513401 --- /dev/null +++ b/prisma/migrations/20230615181742_/migration.sql @@ -0,0 +1,28 @@ +/* + Warnings: + + - A unique constraint covering the columns `[serialNumber]` on the table `Printer` will be added. If there are existing duplicate values, this will fail. + +*/ +-- AlterTable +ALTER TABLE "Printer" ADD COLUMN "serialNumber" TEXT; + +-- CreateTable +CREATE TABLE "PrinterStatus" ( + "id" SERIAL NOT NULL, + "tonerBlackLevel" INTEGER NOT NULL, + "tonerCyanLevel" INTEGER, + "tonerMagentaLevel" INTEGER, + "tonerYellowLevel" INTEGER, + "counter" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "printerId" INTEGER NOT NULL, + + CONSTRAINT "PrinterStatus_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Printer_serialNumber_key" ON "Printer"("serialNumber"); + +-- AddForeignKey +ALTER TABLE "PrinterStatus" ADD CONSTRAINT "PrinterStatus_printerId_fkey" FOREIGN KEY ("printerId") REFERENCES "Printer"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 488b859..804e9e1 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -33,13 +33,22 @@ model User { model Printer { id Int @id @default(autoincrement()) - hostname String? friendlyName String? + + serialNumber String? @unique + hostname String? ip String model PrinterModel + blackTonerModel String? + cyanTonerModel String? + magentaTonerModel String? + yellowTonerModel String? + createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt + + PrinterStatus PrinterStatus[] } enum PrinterModel { @@ -47,3 +56,19 @@ enum PrinterModel { m2040dn p6235cdn } + +model PrinterStatus { + id Int @id @default(autoincrement()) + + tonerBlackLevel Int + tonerCyanLevel Int? + tonerMagentaLevel Int? + tonerYellowLevel Int? + + counter Int + + createdAt DateTime @default(now()) + + printerId Int + printer Printer @relation(fields: [printerId], references: [id]) +} diff --git a/prisma/seed.ts b/prisma/seed.ts index 499c114..69708f1 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -5,11 +5,36 @@ export const prisma = new PrismaClient() async function main() { await prisma.printer.createMany({ data: [ - { friendlyName: 'p04', ip: '10.7.0.134', model: 'm3655idn' }, - { friendlyName: 'p05', ip: '10.7.0.135', model: 'm2040dn' }, - { friendlyName: 'p06', ip: '10.7.0.136', model: 'm2040dn' }, - { friendlyName: 'p07', ip: '10.7.0.137', model: 'm2040dn' }, - { friendlyName: 'p08', ip: '10.7.0.138', model: 'p6235cdn' } + { + friendlyName: 'p04', + ip: '10.7.0.134', + model: 'm3655idn', + serialNumber: 'R4P1478461' + }, + { + friendlyName: 'p05', + ip: '10.7.0.135', + model: 'm2040dn', + serialNumber: 'VR91483974' + }, + { + friendlyName: 'p06', + ip: '10.7.0.136', + model: 'm2040dn', + serialNumber: 'VR91586433' + }, + { + friendlyName: 'p07', + ip: '10.7.0.137', + model: 'm2040dn', + serialNumber: 'VR91586432' + }, + { + friendlyName: 'p08', + ip: '10.7.0.138', + model: 'p6235cdn', + serialNumber: 'RCG0304510' + } ] }) } diff --git a/src/controllers/routes/UserRouteController.ts b/src/controllers/routes/UserRouteController.ts index 5165784..6efcfd9 100644 --- a/src/controllers/routes/UserRouteController.ts +++ b/src/controllers/routes/UserRouteController.ts @@ -3,7 +3,7 @@ import { prisma } from '../../prisma.js' import { Request, Response } from 'express' export class UserRouteController { - static async get(req: Request, res: Response) { + static async getOne(req: Request, res: Response) { const { username } = req.params if (!username) return res.status(400).json({ error: 'Missing username' }) diff --git a/src/index.ts b/src/index.ts index 39ae7ff..47ea45b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,74 +1,8 @@ import 'dotenv/config' -import express, { Request, Response } from 'express' -import bodyParser from 'body-parser' - -import { injectUserMiddleware } from './middleware/injectUserMiddleware.js' -import { authMiddleware } from './middleware/authMiddleware.js' -import { hasRolesMiddleware } from './middleware/hasRolesMiddleware.js' - -import { RequestWithUser } from './types/RequestWithUser.js' - -import { UserRouteController } from './controllers/routes/UserRouteController.js' -import { AuthenticationController } from './controllers/AuthenticationController.js' - -const app = express() +import { app } from './server.js' const PORT = process.env.PORT || 3000 -app.use('/', express.static('public')) - -app.use(injectUserMiddleware) - -app.use(bodyParser.json()) - -// Test route -app.get('/api/', async (req: Request, res: Response) => { - res.json({ message: 'Hello!' }) -}) - -// Login route -app.post('/api/login', async (req: Request, res: Response) => { - const { username, password } = req.body - - if (!username || !password) - return res.status(400).json({ error: 'Missing username or password' }) - - try { - const token = await AuthenticationController.login(username, password) - res.json({ token }) - } catch (error: any) { - res.status(401).json({ error: error.message }) - } -}) - -app.get( - '/api/me', - authMiddleware, - async (req: RequestWithUser, res: Response) => res.json(req.user) -) - -app.get( - '/api/protected', - authMiddleware, - async (req: RequestWithUser, res: Response) => { - res.json('Hello protected world! ' + req.user?.displayName) - } -) - -app.get( - '/api/admin', - await hasRolesMiddleware(['ADMIN']), - async (req: RequestWithUser, res: Response) => { - res.json('Hello Admin!' + req.user?.username) - } -) - -app.get( - '/api/user/:username', - await hasRolesMiddleware(['ADMIN']), - UserRouteController.get -) - // Start server app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`) diff --git a/src/middleware/hasRolesMiddleware.ts b/src/middleware/hasRolesMiddleware.ts index 603a1cd..e0e6ddc 100644 --- a/src/middleware/hasRolesMiddleware.ts +++ b/src/middleware/hasRolesMiddleware.ts @@ -2,12 +2,8 @@ import { Response, NextFunction } from 'express' import { RequestWithUser } from '../types/RequestWithUser.js' import { Role } from '@prisma/client' -export async function hasRolesMiddleware(roles: Role[]) { - return async function ( - req: RequestWithUser, - res: Response, - next: NextFunction - ) { +export function hasRolesMiddleware(roles: Role[]) { + return function (req: RequestWithUser, res: Response, next: NextFunction) { try { const userRoles = req.user?.roles diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..67dba01 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,67 @@ +import express, { Request, Response } from 'express' +import bodyParser from 'body-parser' + +import { injectUserMiddleware } from './middleware/injectUserMiddleware.js' +import { authMiddleware } from './middleware/authMiddleware.js' +import { hasRolesMiddleware } from './middleware/hasRolesMiddleware.js' + +import { RequestWithUser } from './types/RequestWithUser.js' + +import { UserRouteController } from './controllers/routes/UserRouteController.js' +import { AuthenticationController } from './controllers/AuthenticationController.js' + +export const app = express() + +app.use('/', express.static('public')) + +app.use(injectUserMiddleware) + +app.use(bodyParser.json()) + +// Test route +app.get('/api/', async (req: Request, res: Response) => { + res.json({ message: 'Hello!' }) +}) + +// Login route +app.post('/api/login', async (req: Request, res: Response) => { + const { username, password } = req.body + + if (!username || !password) + return res.status(400).json({ error: 'Missing username or password' }) + + try { + const token = await AuthenticationController.login(username, password) + res.json({ token }) + } catch (error: any) { + res.status(401).json({ error: error.message }) + } +}) + +app.get( + '/api/me', + authMiddleware, + async (req: RequestWithUser, res: Response) => res.json(req.user) +) + +app.get( + '/api/protected', + authMiddleware, + async (req: RequestWithUser, res: Response) => { + res.json('Hello protected world! ' + req.user?.displayName) + } +) + +app.get( + '/api/admin', + hasRolesMiddleware(['ADMIN']), + async (req: RequestWithUser, res: Response) => { + res.json('Hello Admin!' + req.user?.username) + } +) + +app.get( + '/api/user/:username', + hasRolesMiddleware(['ADMIN']), + UserRouteController.getOne +)