+
+
+
-
-
-
-
+
+ No se encontraron notificaciones
+
+
+ Intenta ajustar los filtros o la búsqueda
+
+
+
{ searchQuery = ''; selectedTypes = [] }"
>
-
-
-
-
-
-
-
- {{ notification.title }}
-
-
- hace {{ notification.time }}
-
-
-
- {{ notification.message }}
-
-
-
+ Limpiar filtros
+
+
+
+
+
+
+
+
+
+
+
+
+ No tienes notificaciones
+
+
+ Cuando recibas notificaciones, aparecerán aquí
+
diff --git a/nuxt4-app/server/api/notifications/list.get.ts b/nuxt4-app/server/api/notifications/list.get.ts
new file mode 100644
index 0000000..7dc032d
--- /dev/null
+++ b/nuxt4-app/server/api/notifications/list.get.ts
@@ -0,0 +1,71 @@
+/**
+ * Endpoint para obtener notificaciones pendientes para el usuario actual
+ *
+ * Este endpoint permite al cliente hacer polling para obtener notificaciones
+ * generadas por el backend que aún no han sido entregadas.
+ *
+ * Casos de uso:
+ * - Polling periódico para obtener nuevas notificaciones
+ * - Sincronización inicial al cargar la aplicación
+ */
+
+// En memoria: cola de notificaciones por usuario
+// Nota: En producción, esto debería estar en Redis o una BD
+const notificationQueue = new Map
()
+
+export default defineEventHandler(async (event) => {
+ try {
+ // Leer el usuario actual de los headers de Authentik
+ const headers = getHeaders(event)
+ const userId = headers['x-authentik-uid']
+ const username = headers['x-authentik-username']
+
+ // Verificar que el usuario esté autenticado
+ if (!userId) {
+ throw createError({
+ statusCode: 401,
+ statusMessage: 'Usuario no autenticado'
+ })
+ }
+
+ // Obtener notificaciones pendientes para este usuario
+ const pendingNotifications = notificationQueue.get(userId) || []
+
+ // Limpiar la cola después de entregarlas
+ notificationQueue.delete(userId)
+
+ return {
+ success: true,
+ notifications: pendingNotifications,
+ count: pendingNotifications.length,
+ user: {
+ uid: userId,
+ username
+ }
+ }
+ } catch (error: any) {
+ console.error('Error al obtener notificaciones:', error)
+
+ // Si ya es un error de H3, relanzarlo
+ if (error.statusCode) {
+ throw error
+ }
+
+ // Error genérico
+ throw createError({
+ statusCode: 500,
+ statusMessage: 'Error al obtener notificaciones'
+ })
+ }
+})
+
+/**
+ * Función helper para agregar una notificación a la cola de un usuario
+ * Esta función puede ser llamada desde otros endpoints del servidor
+ */
+export function queueNotification(userId: string, notification: any) {
+ if (!notificationQueue.has(userId)) {
+ notificationQueue.set(userId, [])
+ }
+ notificationQueue.get(userId)!.push(notification)
+}
diff --git a/nuxt4-app/server/api/notifications/send.post.ts b/nuxt4-app/server/api/notifications/send.post.ts
new file mode 100644
index 0000000..c9537e5
--- /dev/null
+++ b/nuxt4-app/server/api/notifications/send.post.ts
@@ -0,0 +1,95 @@
+/**
+ * Endpoint para enviar notificaciones a usuarios específicos desde el backend
+ *
+ * Esta API permite crear notificaciones que se entregarán directamente
+ * al cliente para ser guardadas en su localStorage.
+ *
+ * Casos de uso:
+ * - Notificaciones del sistema
+ * - Alertas generadas por procesos del backend
+ * - Notificaciones administrativas
+ */
+
+export default defineEventHandler(async (event) => {
+ try {
+ // Leer el body de la petición
+ const body = await readBody(event)
+
+ // Validar campos requeridos
+ if (!body.targetUserId || !body.title) {
+ throw createError({
+ statusCode: 400,
+ statusMessage: 'Faltan campos requeridos: targetUserId y title'
+ })
+ }
+
+ // Validar tipo de notificación
+ const validTypes = ['info', 'warning', 'success', 'error']
+ const type = body.type || 'info'
+ if (!validTypes.includes(type)) {
+ throw createError({
+ statusCode: 400,
+ statusMessage: `Tipo inválido. Debe ser uno de: ${validTypes.join(', ')}`
+ })
+ }
+
+ // Leer el usuario actual de los headers de Authentik
+ const headers = getHeaders(event)
+ const currentUserId = headers['x-authentik-uid']
+ const currentUsername = headers['x-authentik-username']
+
+ // Verificar que el usuario esté autenticado
+ if (!currentUserId) {
+ throw createError({
+ statusCode: 401,
+ statusMessage: 'Usuario no autenticado'
+ })
+ }
+
+ // Opcional: verificar permisos (por ejemplo, solo admins pueden enviar notificaciones)
+ // const groups = headers['x-authentik-groups']?.split('|') || []
+ // if (!groups.includes('admins')) {
+ // throw createError({
+ // statusCode: 403,
+ // statusMessage: 'No tienes permisos para enviar notificaciones'
+ // })
+ // }
+
+ // Construir la notificación
+ const notification = {
+ targetUserId: body.targetUserId,
+ type: type as 'info' | 'warning' | 'success' | 'error',
+ title: body.title,
+ message: body.message || '',
+ origin: 'backend' as const,
+ metadata: {
+ sentBy: currentUsername,
+ sentAt: new Date().toISOString(),
+ ...body.metadata
+ }
+ }
+
+ // Nota: Como usamos localStorage en el cliente, no guardamos en BD
+ // En su lugar, retornamos la notificación para que el cliente la guarde
+ // El cliente debe hacer polling o usar SSE/WebSocket para obtener notificaciones
+
+ return {
+ success: true,
+ notification,
+ message: 'Notificación creada correctamente'
+ }
+ } catch (error: any) {
+ console.error('Error al enviar notificación:', error)
+
+ // Si ya es un error de H3, relanzarlo
+ if (error.statusCode) {
+ throw error
+ }
+
+ // Error genérico
+ throw createError({
+ statusCode: 500,
+ statusMessage: 'Error al procesar la notificación'
+ })
+ }
+})