fix(prisma): remplace les enums par des String (compat SQLite)
SQLite ne supporte pas les enums Prisma. Les 6 enums (HostStatus, HostSource, Protocol, PortState, ScanType, ScanStatus) sont convertis en champs String avec valeurs par défaut littérales et documentation inline des valeurs autorisées. La validation reste assurée par Zod côté app. Adapte aussi les mappings statusVariant des pages hosts/scans en Record<string, BadgeVariant> avec fallback 'default'. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -49,10 +49,11 @@ model Host {
|
|||||||
vendor String? // Issue du MAC (OUI) ou d'une fingerprint
|
vendor String? // Issue du MAC (OUI) ou d'une fingerprint
|
||||||
osGuess String? // OS détecté / renseigné
|
osGuess String? // OS détecté / renseigné
|
||||||
|
|
||||||
status HostStatus @default(UNKNOWN)
|
// Valeurs : "UP" | "DOWN" | "UNKNOWN" (validation Zod côté app)
|
||||||
|
status String @default("UNKNOWN")
|
||||||
|
|
||||||
// Origine de la fiche : saisie manuelle ou découverte
|
// Origine de la fiche : "MANUAL" | "DISCOVERED" | "IMPORTED"
|
||||||
source HostSource @default(MANUAL)
|
source String @default("MANUAL")
|
||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
networkId String?
|
networkId String?
|
||||||
@@ -71,17 +72,10 @@ model Host {
|
|||||||
@@index([status])
|
@@index([status])
|
||||||
}
|
}
|
||||||
|
|
||||||
enum HostStatus {
|
// NOTE : les enums Prisma ne sont pas supportés par SQLite. On stocke
|
||||||
UP
|
// donc tous les statuts/types en `String` et on valide les valeurs
|
||||||
DOWN
|
// possibles côté app via Zod. Constantes documentées au-dessus de
|
||||||
UNKNOWN
|
// chaque champ.
|
||||||
}
|
|
||||||
|
|
||||||
enum HostSource {
|
|
||||||
MANUAL
|
|
||||||
DISCOVERED
|
|
||||||
IMPORTED
|
|
||||||
}
|
|
||||||
|
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
// Ports ouverts sur un hôte
|
// Ports ouverts sur un hôte
|
||||||
@@ -89,10 +83,12 @@ enum HostSource {
|
|||||||
model Port {
|
model Port {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
number Int
|
number Int
|
||||||
protocol Protocol @default(TCP)
|
// Valeurs : "TCP" | "UDP"
|
||||||
|
protocol String @default("TCP")
|
||||||
serviceName String? // ex: "http", "ssh", renseigné ou deviné
|
serviceName String? // ex: "http", "ssh", renseigné ou deviné
|
||||||
banner String? // Banner applicatif collecté
|
banner String? // Banner applicatif collecté
|
||||||
state PortState @default(OPEN)
|
// Valeurs : "OPEN" | "CLOSED" | "FILTERED" | "UNKNOWN"
|
||||||
|
state String @default("OPEN")
|
||||||
|
|
||||||
hostId String
|
hostId String
|
||||||
host Host @relation(fields: [hostId], references: [id], onDelete: Cascade)
|
host Host @relation(fields: [hostId], references: [id], onDelete: Cascade)
|
||||||
@@ -110,17 +106,8 @@ model Port {
|
|||||||
@@index([number])
|
@@index([number])
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Protocol {
|
// Protocol : "TCP" | "UDP" — voir Port.protocol
|
||||||
TCP
|
// PortState : "OPEN" | "CLOSED" | "FILTERED" | "UNKNOWN" — voir Port.state
|
||||||
UDP
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PortState {
|
|
||||||
OPEN
|
|
||||||
CLOSED
|
|
||||||
FILTERED
|
|
||||||
UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
// Applications (Jellyfin, Home Assistant, Nextcloud, etc.)
|
// Applications (Jellyfin, Home Assistant, Nextcloud, etc.)
|
||||||
@@ -159,9 +146,11 @@ model HostApplication {
|
|||||||
// Découverte réseau — historique des scans
|
// Découverte réseau — historique des scans
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
model Scan {
|
model Scan {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
type ScanType
|
// Valeurs : "PING" | "PORT" | "ARP" | "MDNS" | "FULL"
|
||||||
status ScanStatus @default(PENDING)
|
type String
|
||||||
|
// Valeurs : "PENDING" | "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED"
|
||||||
|
status String @default("PENDING")
|
||||||
target String // CIDR, IP, ou hôte
|
target String // CIDR, IP, ou hôte
|
||||||
params String? // JSON (Zod validé côté app)
|
params String? // JSON (Zod validé côté app)
|
||||||
startedAt DateTime?
|
startedAt DateTime?
|
||||||
@@ -180,21 +169,8 @@ model Scan {
|
|||||||
@@index([type])
|
@@index([type])
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ScanType {
|
// ScanType : "PING" | "PORT" | "ARP" | "MDNS" | "FULL" — voir Scan.type
|
||||||
PING
|
// ScanStatus : "PENDING" | "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED" — voir Scan.status
|
||||||
PORT
|
|
||||||
ARP
|
|
||||||
MDNS
|
|
||||||
FULL
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ScanStatus {
|
|
||||||
PENDING
|
|
||||||
RUNNING
|
|
||||||
COMPLETED
|
|
||||||
FAILED
|
|
||||||
CANCELLED
|
|
||||||
}
|
|
||||||
|
|
||||||
// Résultat individuel d'un scan (rattaché à un hôte quand possible)
|
// Résultat individuel d'un scan (rattaché à un hôte quand possible)
|
||||||
model ScanResult {
|
model ScanResult {
|
||||||
|
|||||||
@@ -30,11 +30,13 @@ async function getHosts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusVariant = {
|
type BadgeVariant = 'default' | 'success' | 'warning' | 'destructive' | 'info' | 'outline';
|
||||||
|
|
||||||
|
const statusVariant: Record<string, BadgeVariant> = {
|
||||||
UP: 'success',
|
UP: 'success',
|
||||||
DOWN: 'destructive',
|
DOWN: 'destructive',
|
||||||
UNKNOWN: 'default',
|
UNKNOWN: 'default',
|
||||||
} as const;
|
};
|
||||||
|
|
||||||
export default async function HostsPage() {
|
export default async function HostsPage() {
|
||||||
const hosts = await getHosts();
|
const hosts = await getHosts();
|
||||||
@@ -82,7 +84,7 @@ export default async function HostsPage() {
|
|||||||
{h.network?.name ?? '—'}
|
{h.network?.name ?? '—'}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Badge variant={statusVariant[h.status]}>{h.status}</Badge>
|
<Badge variant={statusVariant[h.status] ?? 'default'}>{h.status}</Badge>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-muted-foreground">
|
<TableCell className="text-muted-foreground">
|
||||||
{h.ports.length > 0 ? (
|
{h.ports.length > 0 ? (
|
||||||
|
|||||||
@@ -26,13 +26,15 @@ async function getScans() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusVariant = {
|
type BadgeVariant = 'default' | 'success' | 'warning' | 'destructive' | 'info' | 'outline';
|
||||||
|
|
||||||
|
const statusVariant: Record<string, BadgeVariant> = {
|
||||||
COMPLETED: 'success',
|
COMPLETED: 'success',
|
||||||
RUNNING: 'info',
|
RUNNING: 'info',
|
||||||
PENDING: 'default',
|
PENDING: 'default',
|
||||||
FAILED: 'destructive',
|
FAILED: 'destructive',
|
||||||
CANCELLED: 'warning',
|
CANCELLED: 'warning',
|
||||||
} as const;
|
};
|
||||||
|
|
||||||
function formatDuration(start: Date | null, end: Date | null) {
|
function formatDuration(start: Date | null, end: Date | null) {
|
||||||
if (!start || !end) return '—';
|
if (!start || !end) return '—';
|
||||||
@@ -83,7 +85,7 @@ export default async function ScansPage() {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-mono text-sm">{s.target}</TableCell>
|
<TableCell className="font-mono text-sm">{s.target}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Badge variant={statusVariant[s.status]}>{s.status}</Badge>
|
<Badge variant={statusVariant[s.status] ?? 'default'}>{s.status}</Badge>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="tabular-nums">{s.hostsFound}</TableCell>
|
<TableCell className="tabular-nums">{s.hostsFound}</TableCell>
|
||||||
<TableCell className="tabular-nums">{s.portsFound}</TableCell>
|
<TableCell className="tabular-nums">{s.portsFound}</TableCell>
|
||||||
|
|||||||
Reference in New Issue
Block a user