first commit
This commit is contained in:
24
backend/Dockerfile
Normal file
24
backend/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files first for caching
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN apk add --no-cache openssl
|
||||
|
||||
# Install dependencies
|
||||
RUN npm install
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Generate Prisma Client
|
||||
RUN npx prisma generate
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Start command (dev mode for now)
|
||||
CMD ["npm", "run", "dev"]
|
||||
22
backend/package.json
Normal file
22
backend/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "controlpatente-backend",
|
||||
"version": "1.0.0",
|
||||
"description": "Backend for ALPR System",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"start": "node src/index.js",
|
||||
"dev": "nodemon src/index.js",
|
||||
"migrate": "npx prisma migrate dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.18.2",
|
||||
"pg": "^8.11.0",
|
||||
"socket.io": "^4.6.1",
|
||||
"@prisma/client": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.22",
|
||||
"prisma": "^5.0.0"
|
||||
}
|
||||
}
|
||||
23
backend/prisma/migrations/20251223000209_init/migration.sql
Normal file
23
backend/prisma/migrations/20251223000209_init/migration.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "Plate" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"number" TEXT NOT NULL,
|
||||
"owner" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'ALLOWED',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Plate_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AccessLog" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"plateNumber" TEXT NOT NULL,
|
||||
"accessStatus" TEXT NOT NULL,
|
||||
"timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AccessLog_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Plate_number_key" ON "Plate"("number");
|
||||
3
backend/prisma/migrations/migration_lock.toml
Normal file
3
backend/prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
||||
24
backend/prisma/schema.prisma
Normal file
24
backend/prisma/schema.prisma
Normal file
@@ -0,0 +1,24 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
binaryTargets = ["native", "linux-musl-arm64-openssl-3.0.x"]
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model Plate {
|
||||
id Int @id @default(autoincrement())
|
||||
number String @unique
|
||||
owner String?
|
||||
status String @default("ALLOWED") // ALLOWED, DENIED
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model AccessLog {
|
||||
id Int @id @default(autoincrement())
|
||||
plateNumber String
|
||||
accessStatus String // GRANTED, DENIED, UNKNOWN
|
||||
timestamp DateTime @default(now())
|
||||
}
|
||||
98
backend/src/index.js
Normal file
98
backend/src/index.js
Normal file
@@ -0,0 +1,98 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const http = require('http');
|
||||
const { Server } = require('socket.io');
|
||||
|
||||
const app = express();
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
const server = http.createServer(app);
|
||||
const io = new Server(server, {
|
||||
cors: {
|
||||
origin: "*",
|
||||
methods: ["GET", "POST"]
|
||||
}
|
||||
});
|
||||
|
||||
// Hello World
|
||||
app.get('/', (req, res) => {
|
||||
res.send('ALPR Backend Running');
|
||||
});
|
||||
|
||||
// Plates CRUD
|
||||
app.get('/api/plates', async (req, res) => {
|
||||
try {
|
||||
const plates = await prisma.plate.findMany();
|
||||
res.json(plates);
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/plates', async (req, res) => {
|
||||
const { number, owner, status } = req.body;
|
||||
try {
|
||||
const plate = await prisma.plate.create({
|
||||
data: { number, owner, status: status || 'ALLOWED' }
|
||||
});
|
||||
res.json(plate);
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Detection Endpoint (from Python)
|
||||
app.post('/api/detect', async (req, res) => {
|
||||
const { plate_number } = req.body;
|
||||
console.log(`Detected: ${plate_number}`);
|
||||
|
||||
try {
|
||||
// Check if plate exists
|
||||
let plate = await prisma.plate.findUnique({
|
||||
where: { number: plate_number }
|
||||
});
|
||||
|
||||
let accessStatus = 'DENIED';
|
||||
|
||||
if (plate && plate.status === 'ALLOWED') {
|
||||
accessStatus = 'GRANTED';
|
||||
}
|
||||
|
||||
if (!plate) {
|
||||
// Optional: Auto-create unknown plates?
|
||||
// For now, treat as UNKNOWN (Denied)
|
||||
accessStatus = 'UNKNOWN';
|
||||
}
|
||||
|
||||
// Log the access attempt
|
||||
const log = await prisma.accessLog.create({
|
||||
data: {
|
||||
plateNumber: plate_number,
|
||||
accessStatus,
|
||||
timestamp: new Date()
|
||||
}
|
||||
});
|
||||
|
||||
// Notify Frontend via WebSocket
|
||||
io.emit('new_detection', {
|
||||
plate: plate_number,
|
||||
status: accessStatus,
|
||||
timestamp: log.timestamp
|
||||
});
|
||||
|
||||
res.json({ message: 'Processed', accessStatus });
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
});
|
||||
Reference in New Issue
Block a user