first commit

This commit is contained in:
2025-12-22 22:40:38 -03:00
commit 309d9eefba
25 changed files with 902 additions and 0 deletions

24
backend/Dockerfile Normal file
View 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
View 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"
}
}

View 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");

View 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"

View 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
View 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}`);
});