UNPKG

@trustcaptcha/trustcaptcha-frontend

Version:

Frondend library for trustcaptcha

178 lines (177 loc) 7.79 kB
export class EventTracker { constructor() { this.userEvents = []; this.active = true; this.eventProperties = {}; // Gruppiere Event-Typen und ihre gemeinsamen Eigenschaften const mouseEvents = ['click', 'mousedown', 'mouseup', 'mousemove']; const mouseEventProperties = ['isTrusted', 'timeStamp', 'type', 'altKey', 'bubbles', 'button', 'buttons', 'cancelBubble', 'cancelable', 'clientX', 'clientY', 'composed', 'ctrlKey', 'defaultPrevented', 'detail', 'eventPhase', 'layerX', 'layerY', 'metaKey', 'movementX', 'movementY', 'offsetX', 'offsetY', 'pageX', 'pageY', 'returnValue', 'screenX', 'screenY', 'shiftKey', 'which', 'x', 'y']; mouseEvents.forEach(eventType => { this.eventProperties[eventType] = mouseEventProperties; }); const touchEvents = ['touchstart', 'touchend', 'touchmove', 'touchcancel']; const touchEventProperties = ['isTrusted', 'timeStamp', 'type', 'altKey', 'bubbles', 'cancelBubble', 'cancelable', 'changedTouches', 'composed', 'ctrlKey', 'defaultPrevented', 'detail', 'eventPhase', 'metaKey', 'returnValue', 'shiftKey', 'targetTouches', 'touches' ]; touchEvents.forEach(eventType => { this.eventProperties[eventType] = touchEventProperties; }); const keyboardEvents = ['keydown', 'keyup']; const keyboardEventProperties = ['isTrusted', 'timeStamp', 'type', 'altKey', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'ctrlKey', 'defaultPrevented', 'detail', 'eventPhase', 'isComposing', 'location', 'metaKey', 'repeat', 'returnValue', 'shiftKey']; keyboardEvents.forEach(eventType => { this.eventProperties[eventType] = keyboardEventProperties; }); const uiEvents = ['resize']; const uiEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'eventPhase', 'returnValue']; uiEvents.forEach(eventType => { this.eventProperties[eventType] = uiEventProperties; }); const focusEvents = ['focus', 'blur']; const focusEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'defaultPrevented', 'eventPhase', 'returnValue']; focusEvents.forEach(eventType => { this.eventProperties[eventType] = focusEventProperties; }); const clipboardEvents = ['copy', 'paste']; const clipboardEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'defaultPrevented', 'eventPhase', 'returnValue', 'clipboardData']; clipboardEvents.forEach(eventType => { this.eventProperties[eventType] = clipboardEventProperties; }); const scrollEvents = ['scroll']; const scrollEventProperties = ['isTrusted', 'timeStamp', 'type', 'bubbles', 'cancelBubble', 'cancelable', 'composed', 'defaultPrevented', 'eventPhase', 'returnValue']; scrollEvents.forEach(eventType => { this.eventProperties[eventType] = scrollEventProperties; }); // Event Listener hinzufügen mouseEvents.forEach(eventType => { if (eventType === 'mousemove') { document.addEventListener(eventType, this.throttle(event => this.saveEvent(event), 1)); } else { document.addEventListener(eventType, event => this.saveEvent(event)); } }); touchEvents.forEach(eventType => { document.addEventListener(eventType, event => this.saveEvent(event)); }); keyboardEvents.forEach(eventType => { document.addEventListener(eventType, event => this.saveEvent(event)); }); uiEvents.forEach(eventType => { window.addEventListener(eventType, event => this.saveEvent(event)); }); scrollEvents.forEach(eventType => { window.addEventListener(eventType, event => this.saveEvent(event)); }); clipboardEvents.forEach(eventType => { document.addEventListener(eventType, event => this.saveEvent(event)); }); // Focus und Blur Events für bestimmte Elemente const selectors = [ 'a[href]', 'area[href]', 'button', 'details', 'input:not([type="hidden"]):not([type="radio"]):not([type="checkbox"]):not([disabled])', 'iframe', 'object', 'select:not([disabled])', 'textarea:not([disabled])', 'summary', '[contenteditable]' ]; selectors.forEach(selector => { const elements = document.querySelectorAll(selector); elements.forEach(element => { focusEvents.forEach(eventType => { element.addEventListener(eventType, event => this.saveEvent(event)); }); }); }); } throttle(func, limit) { let inThrottle; return function () { const args = arguments; const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } getEventsAndResetArray() { const currentEvents = this.userEvents; this.userEvents = []; return currentEvents; } saveEvent(event) { if (!this.active) { return; } if (this.userEvents.length >= 25000) { this.userEvents.shift(); } const eventType = event.type; if (this.eventProperties.hasOwnProperty(eventType)) { const propsToInclude = this.eventProperties[eventType]; const sanitizedEvent = this.pickProperties(event, propsToInclude); this.userEvents.push(sanitizedEvent); } else { console.log('Unhandled event type:', eventType); } } pickProperties(event, props) { const safeEvent = {}; props.forEach(key => { try { let value = event[key]; if (key === 'clipboardData') { value = { files: value.files.length, items: value.items.length, types: value.types.length }; } else if (key === 'changedTouches' || key === 'targetTouches' || key === 'touches') { value = this.mapTouchList(value); } if (typeof value !== 'function') { safeEvent[key] = value; } } catch (err) { // Ignoriere nicht zugängliche Eigenschaften } }); return safeEvent; } mapTouchList(touches) { const touchesArray = []; for (let i = 0; i < touches.length; i++) { const touch = touches[i]; touchesArray.push({ clientX: touch.clientX, clientY: touch.clientY, force: touch.force, identifier: touch.identifier, pageX: touch.pageX, pageY: touch.pageY, radiusX: touch.radiusX, radiusY: touch.radiusY, rotationAngle: touch.rotationAngle, screenX: touch.screenX, screenY: touch.screenY, }); } return touchesArray; } stop() { this.active = false; } reset() { this.userEvents = []; this.active = true; } } //# sourceMappingURL=event_tracker.js.map