@pulzar/core
Version:
Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support
196 lines • 6.28 kB
JavaScript
import { EventEmitter } from "events";
import { logger } from "../../utils/logger";
import { randomUUID } from "crypto";
export class AuthEventEmitter extends EventEmitter {
auditLog = [];
maxLogSize;
constructor(maxLogSize = 1000) {
super();
this.maxLogSize = maxLogSize;
this.setupDefaultListeners();
}
/**
* Setup default event listeners for logging
*/
setupDefaultListeners() {
this.on("auth.login", (event, context) => {
logger.info("User login attempt", {
userId: event.userId,
success: event.success,
error: event.error,
traceId: context?.traceId,
requestId: context?.requestId,
timestamp: event.timestamp,
});
});
this.on("auth.logout", (event, context) => {
logger.info("User logout", {
userId: event.userId,
sessionId: event.sessionId,
traceId: context?.traceId,
requestId: context?.requestId,
timestamp: event.timestamp,
});
});
this.on("auth.token_refresh", (event, context) => {
logger.debug("Token refresh", {
userId: event.userId,
success: event.success,
traceId: context?.traceId,
requestId: context?.requestId,
timestamp: event.timestamp,
});
});
this.on("auth.security_violation", (event, context) => {
logger.warn("Security violation detected", {
userId: event.userId,
type: event.type,
error: event.error,
metadata: event.metadata,
traceId: context?.traceId,
requestId: context?.requestId,
ipAddress: context?.ipAddress,
userAgent: context?.userAgent,
timestamp: event.timestamp,
});
});
this.on("auth.lockout", (event, context) => {
logger.warn("User account locked", {
userId: event.userId,
metadata: event.metadata,
traceId: context?.traceId,
requestId: context?.requestId,
timestamp: event.timestamp,
});
});
}
/**
* Emit auth event with automatic audit logging
*/
emitAuthEvent(type, data, context) {
const event = {
type,
timestamp: new Date(),
...data,
};
// Add to audit log
this.addToAuditLog(event);
// Emit the event
this.emit(`auth.${type}`, event, context);
this.emit("auth.*", event, context); // Wildcard listener
}
/**
* Add event to audit log with size management
*/
addToAuditLog(event) {
const auditEntry = {
id: randomUUID(),
event,
createdAt: new Date(),
};
this.auditLog.push(auditEntry);
// Maintain max log size
if (this.auditLog.length > this.maxLogSize) {
this.auditLog.shift();
}
}
/**
* Get audit log entries
*/
getAuditLog(filters) {
let filtered = this.auditLog;
if (filters) {
if (filters.userId) {
filtered = filtered.filter((entry) => entry.event.userId === filters.userId);
}
if (filters.type) {
filtered = filtered.filter((entry) => entry.event.type === filters.type);
}
if (filters.success !== undefined) {
filtered = filtered.filter((entry) => entry.event.success === filters.success);
}
if (filters.since) {
filtered = filtered.filter((entry) => entry.event.timestamp >= filters.since);
}
if (filters.limit) {
filtered = filtered.slice(-filters.limit);
}
}
return filtered;
}
/**
* Get auth statistics
*/
getStats() {
const totalEvents = this.auditLog.length;
const eventsByType = {};
let successfulEvents = 0;
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
let recentFailures = 0;
for (const entry of this.auditLog) {
const type = entry.event.type;
eventsByType[type] = (eventsByType[type] || 0) + 1;
if (entry.event.success) {
successfulEvents++;
}
if (!entry.event.success && entry.event.timestamp >= oneHourAgo) {
recentFailures++;
}
}
return {
totalEvents,
eventsByType,
successRate: totalEvents > 0 ? successfulEvents / totalEvents : 0,
recentFailures,
};
}
/**
* Clear audit log
*/
clearAuditLog() {
this.auditLog = [];
}
/**
* Export audit log as JSON
*/
exportAuditLog() {
return JSON.stringify(this.auditLog, null, 2);
}
}
// Global auth event emitter instance
export const authEvents = new AuthEventEmitter();
// Helper functions for common events
export function emitLoginEvent(userId, success, context, error, metadata) {
authEvents.emitAuthEvent("login", {
userId,
success,
error,
metadata,
ipAddress: context?.ipAddress,
userAgent: context?.userAgent,
}, context);
}
export function emitLogoutEvent(userId, sessionId, context) {
authEvents.emitAuthEvent("logout", {
userId,
sessionId,
success: true,
ipAddress: context?.ipAddress,
userAgent: context?.userAgent,
}, context);
}
export function emitSecurityViolation(userId, violationType, context, metadata) {
authEvents.emitAuthEvent("login", {
// Using login type for violations
userId,
success: false,
error: `Security violation: ${violationType}`,
metadata: {
violationType,
...metadata,
},
ipAddress: context?.ipAddress,
userAgent: context?.userAgent,
}, context);
}
//# sourceMappingURL=auth-events.js.map