Inject user middleware
This commit is contained in:
parent
7c3bc91f39
commit
26771cecdc
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -19,7 +19,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
"@types/jsonwebtoken": "^9.0.2",
|
"@types/jsonwebtoken": "^9.0.2",
|
||||||
"@types/node": "^20.2.5",
|
"@types/node": "^20.3.1",
|
||||||
"nodemon": "^2.0.22",
|
"nodemon": "^2.0.22",
|
||||||
"prisma": "^4.15.0",
|
"prisma": "^4.15.0",
|
||||||
"rimraf": "^5.0.1",
|
"rimraf": "^5.0.1",
|
||||||
|
@ -214,9 +214,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.2.5",
|
"version": "20.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz",
|
||||||
"integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ=="
|
"integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/qs": {
|
"node_modules/@types/qs": {
|
||||||
"version": "6.9.7",
|
"version": "6.9.7",
|
||||||
|
|
|
@ -10,13 +10,16 @@
|
||||||
"start": "node dist",
|
"start": "node dist",
|
||||||
"dev": "nodemon --ext js,ts,mts,mjs,json,prisma ./src/index.ts --exec ts-node-esm"
|
"dev": "nodemon --ext js,ts,mts,mjs,json,prisma ./src/index.ts --exec ts-node-esm"
|
||||||
},
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "ts-node --esm prisma/seed.ts"
|
||||||
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Douglas Barone",
|
"author": "Douglas Barone",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
"@types/jsonwebtoken": "^9.0.2",
|
"@types/jsonwebtoken": "^9.0.2",
|
||||||
"@types/node": "^20.2.5",
|
"@types/node": "^20.3.1",
|
||||||
"nodemon": "^2.0.22",
|
"nodemon": "^2.0.22",
|
||||||
"prisma": "^4.15.0",
|
"prisma": "^4.15.0",
|
||||||
"rimraf": "^5.0.1",
|
"rimraf": "^5.0.1",
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
-- CreateEnum
|
-- CreateEnum
|
||||||
CREATE TYPE "Role" AS ENUM ('ADMIN', 'INSPECTOR', 'USER');
|
CREATE TYPE "Role" AS ENUM ('ADMIN', 'INSPECTOR', 'USER');
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "PrinterModel" AS ENUM ('m3655idn', 'm2040dn', 'p6235cdn');
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "User" (
|
CREATE TABLE "User" (
|
||||||
"id" SERIAL NOT NULL,
|
"id" SERIAL NOT NULL,
|
||||||
|
@ -15,5 +18,18 @@ CREATE TABLE "User" (
|
||||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Printer" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"hostname" TEXT,
|
||||||
|
"friendlyName" TEXT,
|
||||||
|
"ip" TEXT NOT NULL,
|
||||||
|
"model" "PrinterModel" NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "Printer_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
-- CreateIndex
|
-- CreateIndex
|
||||||
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
|
@ -29,3 +29,21 @@ model User {
|
||||||
|
|
||||||
roles Role[] @default([USER])
|
roles Role[] @default([USER])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Printer {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
|
||||||
|
hostname String?
|
||||||
|
friendlyName String?
|
||||||
|
ip String
|
||||||
|
model PrinterModel
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @default(now()) @updatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PrinterModel {
|
||||||
|
m3655idn
|
||||||
|
m2040dn
|
||||||
|
p6235cdn
|
||||||
|
}
|
||||||
|
|
25
prisma/seed.ts
Normal file
25
prisma/seed.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
|
||||||
|
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' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.then(() => {
|
||||||
|
prisma.$disconnect()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error)
|
||||||
|
prisma.$disconnect()
|
||||||
|
process.exit(1)
|
||||||
|
})
|
|
@ -1,12 +1,15 @@
|
||||||
import 'dotenv/config'
|
import 'dotenv/config'
|
||||||
import express, { Request, Response } from 'express'
|
import express, { Request, Response } from 'express'
|
||||||
import bodyParser from 'body-parser'
|
import bodyParser from 'body-parser'
|
||||||
import { login } from './authentication.js'
|
|
||||||
import {
|
import {
|
||||||
authenticatedMiddleware,
|
authenticatedMiddleware,
|
||||||
hasRolesMiddleware
|
hasRolesMiddleware
|
||||||
} from './middleware/authorization.js'
|
} from './middleware/authorization.js'
|
||||||
|
import { injectUserMiddleware } from './middleware/injectUser.js'
|
||||||
|
|
||||||
import { RequestWithUser } from './types.js'
|
import { RequestWithUser } from './types.js'
|
||||||
|
import { login } from './authentication.js'
|
||||||
import { UserController } from './controllers/UserController.js'
|
import { UserController } from './controllers/UserController.js'
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
@ -15,6 +18,8 @@ const PORT = process.env.PORT || 3000
|
||||||
|
|
||||||
app.use('/', express.static('public'))
|
app.use('/', express.static('public'))
|
||||||
|
|
||||||
|
app.use(injectUserMiddleware)
|
||||||
|
|
||||||
app.use(bodyParser.json())
|
app.use(bodyParser.json())
|
||||||
|
|
||||||
// Test route
|
// Test route
|
||||||
|
|
|
@ -3,35 +3,12 @@ import { authenticate } from '../authentication.js'
|
||||||
import { RequestWithUser } from '../types.js'
|
import { RequestWithUser } from '../types.js'
|
||||||
import { Role } from '@prisma/client'
|
import { Role } from '@prisma/client'
|
||||||
|
|
||||||
function getToken(req: Request) {
|
|
||||||
const authHeader = req.headers.authorization as string
|
|
||||||
|
|
||||||
if (!authHeader) return null
|
|
||||||
|
|
||||||
const [type, token] = authHeader.split(' ')
|
|
||||||
if (type !== 'Bearer') throw new Error('Expected a Bearer token')
|
|
||||||
|
|
||||||
return token
|
|
||||||
}
|
|
||||||
|
|
||||||
async function injectUser(req: RequestWithUser) {
|
|
||||||
const token = getToken(req)
|
|
||||||
|
|
||||||
if (!token) return null
|
|
||||||
|
|
||||||
const user = await authenticate(token)
|
|
||||||
|
|
||||||
req.user = user
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function authenticatedMiddleware(
|
export async function authenticatedMiddleware(
|
||||||
req: RequestWithUser,
|
req: RequestWithUser,
|
||||||
res: Response,
|
res: Response,
|
||||||
next: NextFunction
|
next: NextFunction
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
await injectUser(req)
|
|
||||||
|
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
res.status(401).json({ error: 'Must be logged in' })
|
res.status(401).json({ error: 'Must be logged in' })
|
||||||
return
|
return
|
||||||
|
@ -50,8 +27,6 @@ export async function hasRolesMiddleware(roles: Role[]) {
|
||||||
next: NextFunction
|
next: NextFunction
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
await injectUser(req)
|
|
||||||
|
|
||||||
const userRoles = req.user?.roles
|
const userRoles = req.user?.roles
|
||||||
|
|
||||||
if (userRoles === undefined) {
|
if (userRoles === undefined) {
|
||||||
|
|
29
src/middleware/injectUser.ts
Normal file
29
src/middleware/injectUser.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { NextFunction, Request, Response } from 'express'
|
||||||
|
import { RequestWithUser } from '../types.js'
|
||||||
|
import { authenticate } from '../authentication.js'
|
||||||
|
|
||||||
|
function getToken(req: Request) {
|
||||||
|
const authHeader = req.headers.authorization as string
|
||||||
|
|
||||||
|
if (!authHeader) return null
|
||||||
|
|
||||||
|
const [type, token] = authHeader.split(' ')
|
||||||
|
if (type !== 'Bearer') throw new Error('Expected a Bearer token')
|
||||||
|
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function injectUserMiddleware(
|
||||||
|
req: RequestWithUser,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
) {
|
||||||
|
const token = getToken(req)
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
const user = await authenticate(token)
|
||||||
|
req.user = user
|
||||||
|
}
|
||||||
|
|
||||||
|
next()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user