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
This commit is contained in:
361
prisma/schema.prisma
Normal file
361
prisma/schema.prisma
Normal file
@@ -0,0 +1,361 @@
|
||||
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")
|
||||
}
|
||||
Reference in New Issue
Block a user