This commit is contained in:
Douglas Barone 2023-06-15 15:55:09 -04:00
parent ade37ed373
commit 58f077950c
7 changed files with 155 additions and 80 deletions

View File

@ -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;

View File

@ -33,13 +33,22 @@ model User {
model Printer { model Printer {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
hostname String?
friendlyName String? friendlyName String?
serialNumber String? @unique
hostname String?
ip String ip String
model PrinterModel model PrinterModel
blackTonerModel String?
cyanTonerModel String?
magentaTonerModel String?
yellowTonerModel String?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt updatedAt DateTime @default(now()) @updatedAt
PrinterStatus PrinterStatus[]
} }
enum PrinterModel { enum PrinterModel {
@ -47,3 +56,19 @@ enum PrinterModel {
m2040dn m2040dn
p6235cdn 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])
}

View File

@ -5,11 +5,36 @@ export const prisma = new PrismaClient()
async function main() { async function main() {
await prisma.printer.createMany({ await prisma.printer.createMany({
data: [ data: [
{ friendlyName: 'p04', ip: '10.7.0.134', model: 'm3655idn' }, {
{ friendlyName: 'p05', ip: '10.7.0.135', model: 'm2040dn' }, friendlyName: 'p04',
{ friendlyName: 'p06', ip: '10.7.0.136', model: 'm2040dn' }, ip: '10.7.0.134',
{ friendlyName: 'p07', ip: '10.7.0.137', model: 'm2040dn' }, model: 'm3655idn',
{ friendlyName: 'p08', ip: '10.7.0.138', model: 'p6235cdn' } 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'
}
] ]
}) })
} }

View File

@ -3,7 +3,7 @@ import { prisma } from '../../prisma.js'
import { Request, Response } from 'express' import { Request, Response } from 'express'
export class UserRouteController { export class UserRouteController {
static async get(req: Request, res: Response) { static async getOne(req: Request, res: Response) {
const { username } = req.params const { username } = req.params
if (!username) return res.status(400).json({ error: 'Missing username' }) if (!username) return res.status(400).json({ error: 'Missing username' })

View File

@ -1,74 +1,8 @@
import 'dotenv/config' import 'dotenv/config'
import express, { Request, Response } from 'express' import { app } from './server.js'
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()
const PORT = process.env.PORT || 3000 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 // Start server
app.listen(PORT, () => { app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`) console.log(`Server listening on port ${PORT}`)

View File

@ -2,12 +2,8 @@ import { Response, NextFunction } from 'express'
import { RequestWithUser } from '../types/RequestWithUser.js' import { RequestWithUser } from '../types/RequestWithUser.js'
import { Role } from '@prisma/client' import { Role } from '@prisma/client'
export async function hasRolesMiddleware(roles: Role[]) { export function hasRolesMiddleware(roles: Role[]) {
return async function ( return function (req: RequestWithUser, res: Response, next: NextFunction) {
req: RequestWithUser,
res: Response,
next: NextFunction
) {
try { try {
const userRoles = req.user?.roles const userRoles = req.user?.roles

67
src/server.ts Normal file
View File

@ -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
)