Files
MSP-CAS/prisma/schema.prisma
MSP Monitor f4491757d9 Initial commit: MSP Monitor Dashboard
- Next.js 14 frontend with dark cyan/navy theme
- tRPC API with Prisma ORM
- MeshCentral, LibreNMS, Headwind MDM integrations
- Multi-tenant architecture
- Alert system with email/SMS/webhook notifications
- Docker Compose deployment
- Complete documentation
2026-01-21 19:29:20 +00:00

362 lines
11 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ==================== CLIENTES ====================
model Cliente {
id String @id @default(cuid())
nombre String
codigo String @unique
email String?
telefono String?
activo Boolean @default(true)
notas String?
meshcentralGrupo String? @map("meshcentral_grupo")
librenmsGrupo Int? @map("librenms_grupo")
headwindGrupo Int? @map("headwind_grupo")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
ubicaciones ClienteUbicacion[]
dispositivos Dispositivo[]
usuarios Usuario[]
alertas Alerta[]
alertaReglas AlertaRegla[]
@@map("clientes")
}
model ClienteUbicacion {
id String @id @default(cuid())
clienteId String @map("cliente_id")
nombre String
direccion String?
ciudad String?
estado String?
pais String @default("Mexico")
codigoPostal String? @map("codigo_postal")
latitud Float?
longitud Float?
principal Boolean @default(false)
createdAt DateTime @default(now()) @map("created_at")
cliente Cliente @relation(fields: [clienteId], references: [id], onDelete: Cascade)
dispositivos Dispositivo[]
@@map("cliente_ubicaciones")
}
// ==================== DISPOSITIVOS ====================
enum TipoDispositivo {
PC
LAPTOP
SERVIDOR
CELULAR
TABLET
ROUTER
SWITCH
FIREWALL
AP
IMPRESORA
OTRO
}
enum EstadoDispositivo {
ONLINE
OFFLINE
ALERTA
MANTENIMIENTO
DESCONOCIDO
}
model Dispositivo {
id String @id @default(cuid())
clienteId String @map("cliente_id")
ubicacionId String? @map("ubicacion_id")
tipo TipoDispositivo
nombre String
descripcion String?
estado EstadoDispositivo @default(DESCONOCIDO)
// IDs externos
meshcentralId String? @unique @map("meshcentral_id")
librenmsId Int? @unique @map("librenms_id")
headwindId Int? @unique @map("headwind_id")
// Info general
ip String?
mac String?
sistemaOperativo String? @map("sistema_operativo")
versionSO String? @map("version_so")
fabricante String?
modelo String?
serial String?
// Para equipos de computo
cpu String?
ram Int? // En MB
disco Int? // En GB
// Para celulares
imei String?
numeroTelefono String? @map("numero_telefono")
operador String?
// Para red
firmware String?
snmpCommunity String? @map("snmp_community")
// Metricas actuales
cpuUsage Float? @map("cpu_usage")
ramUsage Float? @map("ram_usage")
discoUsage Float? @map("disco_usage")
temperatura Float?
bateria Int?
// Ubicacion GPS (celulares)
latitud Float?
longitud Float?
gpsUpdatedAt DateTime? @map("gps_updated_at")
// Timestamps
lastSeen DateTime? @map("last_seen")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
cliente Cliente @relation(fields: [clienteId], references: [id], onDelete: Cascade)
ubicacion ClienteUbicacion? @relation(fields: [ubicacionId], references: [id])
software DispositivoSoftware[]
metricas DispositivoMetrica[]
metricasHourly DispositivoMetricaHourly[]
alertas Alerta[]
sesiones SesionRemota[]
auditLogs AuditLog[]
@@index([clienteId])
@@index([tipo])
@@index([estado])
@@map("dispositivos")
}
model DispositivoSoftware {
id String @id @default(cuid())
dispositivoId String @map("dispositivo_id")
nombre String
version String?
editor String?
instaladoEn DateTime? @map("instalado_en")
tamanio Int? // En MB
createdAt DateTime @default(now()) @map("created_at")
dispositivo Dispositivo @relation(fields: [dispositivoId], references: [id], onDelete: Cascade)
@@unique([dispositivoId, nombre, version])
@@map("dispositivo_software")
}
model DispositivoMetrica {
id String @id @default(cuid())
dispositivoId String @map("dispositivo_id")
timestamp DateTime @default(now())
cpuUsage Float? @map("cpu_usage")
ramUsage Float? @map("ram_usage")
discoUsage Float? @map("disco_usage")
temperatura Float?
bateria Int?
redIn BigInt? @map("red_in") // bytes
redOut BigInt? @map("red_out") // bytes
dispositivo Dispositivo @relation(fields: [dispositivoId], references: [id], onDelete: Cascade)
@@index([dispositivoId, timestamp])
@@map("dispositivo_metricas")
}
model DispositivoMetricaHourly {
id String @id @default(cuid())
dispositivoId String @map("dispositivo_id")
hora DateTime
cpuAvg Float? @map("cpu_avg")
cpuMax Float? @map("cpu_max")
ramAvg Float? @map("ram_avg")
ramMax Float? @map("ram_max")
discoAvg Float? @map("disco_avg")
tempAvg Float? @map("temp_avg")
tempMax Float? @map("temp_max")
redInTotal BigInt? @map("red_in_total")
redOutTotal BigInt? @map("red_out_total")
dispositivo Dispositivo @relation(fields: [dispositivoId], references: [id], onDelete: Cascade)
@@unique([dispositivoId, hora])
@@map("dispositivo_metricas_hourly")
}
// ==================== ALERTAS ====================
enum SeveridadAlerta {
INFO
WARNING
CRITICAL
}
enum EstadoAlerta {
ACTIVA
RECONOCIDA
RESUELTA
}
model Alerta {
id String @id @default(cuid())
clienteId String @map("cliente_id")
dispositivoId String? @map("dispositivo_id")
reglaId String? @map("regla_id")
severidad SeveridadAlerta
estado EstadoAlerta @default(ACTIVA)
titulo String
mensaje String
origen String? // meshcentral, librenms, headwind, sistema
origenId String? @map("origen_id")
reconocidaPor String? @map("reconocida_por")
reconocidaEn DateTime? @map("reconocida_en")
resueltaPor String? @map("resuelta_por")
resueltaEn DateTime? @map("resuelta_en")
notificada Boolean @default(false)
createdAt DateTime @default(now()) @map("created_at")
cliente Cliente @relation(fields: [clienteId], references: [id], onDelete: Cascade)
dispositivo Dispositivo? @relation(fields: [dispositivoId], references: [id])
regla AlertaRegla? @relation(fields: [reglaId], references: [id])
@@index([clienteId, estado])
@@index([severidad])
@@index([createdAt])
@@map("alertas")
}
model AlertaRegla {
id String @id @default(cuid())
clienteId String? @map("cliente_id") // null = global
nombre String
descripcion String?
activa Boolean @default(true)
tipoDispositivo TipoDispositivo? @map("tipo_dispositivo")
metrica String // cpu, ram, disco, temperatura, etc
operador String // >, <, >=, <=, ==
umbral Float
duracionMinutos Int @default(5) @map("duracion_minutos")
severidad SeveridadAlerta
notificarEmail Boolean @default(true) @map("notificar_email")
notificarSms Boolean @default(false) @map("notificar_sms")
notificarWebhook Boolean @default(false) @map("notificar_webhook")
webhookUrl String? @map("webhook_url")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
cliente Cliente? @relation(fields: [clienteId], references: [id], onDelete: Cascade)
alertas Alerta[]
@@map("alerta_reglas")
}
// ==================== USUARIOS ====================
enum RolUsuario {
SUPER_ADMIN
ADMIN
TECNICO
CLIENTE
VIEWER
}
model Usuario {
id String @id @default(cuid())
clienteId String? @map("cliente_id") // null = acceso global
email String @unique
nombre String
passwordHash String? @map("password_hash")
meshcentralUser String? @unique @map("meshcentral_user")
rol RolUsuario @default(VIEWER)
activo Boolean @default(true)
avatar String?
telefono String?
notificarEmail Boolean @default(true) @map("notificar_email")
notificarSms Boolean @default(false) @map("notificar_sms")
lastLogin DateTime? @map("last_login")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
cliente Cliente? @relation(fields: [clienteId], references: [id], onDelete: SetNull)
permisos UsuarioPermiso[]
sesiones SesionRemota[]
auditLogs AuditLog[]
@@map("usuarios")
}
model UsuarioPermiso {
id String @id @default(cuid())
usuarioId String @map("usuario_id")
recurso String // dispositivos, alertas, reportes, configuracion, etc
accion String // read, write, delete, execute
permitido Boolean @default(true)
usuario Usuario @relation(fields: [usuarioId], references: [id], onDelete: Cascade)
@@unique([usuarioId, recurso, accion])
@@map("usuario_permisos")
}
// ==================== SESIONES Y AUDITORIA ====================
model SesionRemota {
id String @id @default(cuid())
usuarioId String @map("usuario_id")
dispositivoId String @map("dispositivo_id")
tipo String // desktop, terminal, files
meshSessionId String? @map("mesh_session_id")
iniciadaEn DateTime @default(now()) @map("iniciada_en")
finalizadaEn DateTime? @map("finalizada_en")
duracion Int? // segundos
ip String?
usuario Usuario @relation(fields: [usuarioId], references: [id])
dispositivo Dispositivo @relation(fields: [dispositivoId], references: [id])
@@map("sesiones_remotas")
}
model AuditLog {
id String @id @default(cuid())
usuarioId String? @map("usuario_id")
dispositivoId String? @map("dispositivo_id")
accion String
recurso String
detalles Json?
ip String?
userAgent String? @map("user_agent")
createdAt DateTime @default(now()) @map("created_at")
usuario Usuario? @relation(fields: [usuarioId], references: [id])
dispositivo Dispositivo? @relation(fields: [dispositivoId], references: [id])
@@index([usuarioId])
@@index([createdAt])
@@map("audit_log")
}
// ==================== CONFIGURACION ====================
model Configuracion {
id String @id @default(cuid())
clave String @unique
valor Json
tipo String // string, number, boolean, json
categoria String // general, integracion, notificacion, etc
descripcion String?
updatedAt DateTime @updatedAt @map("updated_at")
@@map("configuracion")
}