Files
IPAM/prisma/schema.prisma
Mathieu BOURBON 73d016ec24 fix(prisma): provider statique + scripts de bascule SQLite/PostgreSQL
Prisma ne supporte pas env() pour le champ `provider` d'un datasource
(uniquement pour `url`). Le schéma utilise maintenant `provider = "sqlite"`
en statique, et deux scripts npm (`db:use-sqlite` / `db:use-postgres`)
réécrivent le fichier pour basculer entre les deux moteurs.

Sans ce fix, `prisma generate` échoue au boot.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 16:38:03 +02:00

215 lines
5.5 KiB
Plaintext

// IPAM — Schéma Prisma
// ---------------------------------------------------------------------
// Prisma n'accepte PAS `env()` pour le champ `provider` (seulement pour `url`).
// Le provider par défaut est donc `sqlite`. Pour basculer vers PostgreSQL :
// npm run db:use-postgres
// puis régénérer le client : `npm run db:generate` et migrer : `npm run db:migrate`.
// Pour revenir à SQLite : `npm run db:use-sqlite`.
// ---------------------------------------------------------------------
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
// =====================================================================
// Réseaux (subnets / VLAN)
// =====================================================================
model Network {
id String @id @default(cuid())
name String
cidr String @unique // ex: "192.168.1.0/24"
description String?
vlanId Int?
gateway String?
dnsServers String? // CSV — compat SQLite (pas de array natif)
color String? // Couleur d'affichage UI
hosts Host[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([cidr])
}
// =====================================================================
// Hôtes (une IP = un hôte)
// =====================================================================
model Host {
id String @id @default(cuid())
ipAddress String @unique // IPv4/IPv6
hostname String?
macAddress String?
description String?
vendor String? // Issue du MAC (OUI) ou d'une fingerprint
osGuess String? // OS détecté / renseigné
status HostStatus @default(UNKNOWN)
// Origine de la fiche : saisie manuelle ou découverte
source HostSource @default(MANUAL)
// Relations
networkId String?
network Network? @relation(fields: [networkId], references: [id], onDelete: SetNull)
ports Port[]
applications HostApplication[]
scanResults ScanResult[]
lastSeenAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([ipAddress])
@@index([networkId])
@@index([status])
}
enum HostStatus {
UP
DOWN
UNKNOWN
}
enum HostSource {
MANUAL
DISCOVERED
IMPORTED
}
// =====================================================================
// Ports ouverts sur un hôte
// =====================================================================
model Port {
id String @id @default(cuid())
number Int
protocol Protocol @default(TCP)
serviceName String? // ex: "http", "ssh", renseigné ou deviné
banner String? // Banner applicatif collecté
state PortState @default(OPEN)
hostId String
host Host @relation(fields: [hostId], references: [id], onDelete: Cascade)
// Lien éventuel vers une application métier déclarée
applicationId String?
application Application? @relation(fields: [applicationId], references: [id], onDelete: SetNull)
lastCheckedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([hostId, number, protocol])
@@index([hostId])
@@index([number])
}
enum Protocol {
TCP
UDP
}
enum PortState {
OPEN
CLOSED
FILTERED
UNKNOWN
}
// =====================================================================
// Applications (Jellyfin, Home Assistant, Nextcloud, etc.)
// =====================================================================
model Application {
id String @id @default(cuid())
name String @unique
description String?
category String? // ex: "media", "monitoring", "storage"
icon String? // URL ou clé d'icône
url String? // URL principale d'accès
hosts HostApplication[]
ports Port[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// Table de jointure Hôte <-> Application (N:N)
model HostApplication {
hostId String
applicationId String
host Host @relation(fields: [hostId], references: [id], onDelete: Cascade)
application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)
notes String?
createdAt DateTime @default(now())
@@id([hostId, applicationId])
}
// =====================================================================
// Découverte réseau — historique des scans
// =====================================================================
model Scan {
id String @id @default(cuid())
type ScanType
status ScanStatus @default(PENDING)
target String // CIDR, IP, ou hôte
params String? // JSON (Zod validé côté app)
startedAt DateTime?
endedAt DateTime?
hostsFound Int @default(0)
portsFound Int @default(0)
errorMessage String?
results ScanResult[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([status])
@@index([type])
}
enum ScanType {
PING
PORT
ARP
MDNS
FULL
}
enum ScanStatus {
PENDING
RUNNING
COMPLETED
FAILED
CANCELLED
}
// Résultat individuel d'un scan (rattaché à un hôte quand possible)
model ScanResult {
id String @id @default(cuid())
scanId String
scan Scan @relation(fields: [scanId], references: [id], onDelete: Cascade)
ipAddress String
hostId String?
host Host? @relation(fields: [hostId], references: [id], onDelete: SetNull)
data String // JSON (ports trouvés, services mDNS, MAC, etc.)
createdAt DateTime @default(now())
@@index([scanId])
@@index([ipAddress])
}