next-csrf
Version:
CSRF mitigation library for Next.js
143 lines (121 loc) • 4.34 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _decorateService = require('../util/decorate-service');
var _decorateService2 = _interopRequireDefault(_decorateService);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// counters to track primary input
var _activePointers = 0;
/*
Observe keyboard-, pointer-, mouse- and touch-events so that a query for
the current interaction type can be made at any time. For pointer interaction
this observer is limited to pointer button down/up - move is not observed!
USAGE:
var listener = engage();
listener.get() === {pointer: Boolean, key: Boolean}
*/
var _activeKeys = 0;
var pointerStartEvents = ['touchstart', 'pointerdown', 'MSPointerDown', 'mousedown'];
var pointerEndEvents = ['touchend', 'touchcancel', 'pointerup', 'MSPointerUp', 'pointercancel', 'MSPointerCancel', 'mouseup'];
function handleWindowBlurEvent() {
// reset internal counters when window loses focus
_activePointers = 0;
_activeKeys = 0;
}
function handlePointerStartEvent(event) {
if (event.isPrimary === false) {
// ignore non-primary pointer events
// https://w3c.github.io/pointerevents/#widl-PointerEvent-isPrimary
return;
}
// mousedown without following mouseup
// (likely not possible in Chrome)
_activePointers++;
}
function handlePointerEndEvent(event) {
if (event.isPrimary === false) {
// ignore non-primary pointer events
// https://w3c.github.io/pointerevents/#widl-PointerEvent-isPrimary
return;
} else if (event.touches) {
_activePointers = event.touches.length;
return;
}
// delay reset to when the current handlers are executed
(window.setImmediate || window.setTimeout)(function () {
// mouseup without prior mousedown
// (drag something out of the window)
_activePointers = Math.max(_activePointers - 1, 0);
});
}
function handleKeyStartEvent(event) {
// ignore modifier keys
switch (event.keyCode || event.which) {
case 16: // space
case 17: // control
case 18: // alt
case 91: // command left
case 93:
// command right
return;
}
// keydown without a following keyup
// (may happen on CMD+TAB)
_activeKeys++;
}
function handleKeyEndEvent(event) {
// ignore modifier keys
switch (event.keyCode || event.which) {
case 16: // space
case 17: // control
case 18: // alt
case 91: // command left
case 93:
// command right
return;
}
// delay reset to when the current handlers are executed
(window.setImmediate || window.setTimeout)(function () {
// keyup without prior keydown
// (may happen on CMD+R)
_activeKeys = Math.max(_activeKeys - 1, 0);
});
}
function getInteractionType() {
return {
pointer: Boolean(_activePointers),
key: Boolean(_activeKeys)
};
}
function disengage() {
_activePointers = _activeKeys = 0;
window.removeEventListener('blur', handleWindowBlurEvent, false);
document.documentElement.removeEventListener('keydown', handleKeyStartEvent, true);
document.documentElement.removeEventListener('keyup', handleKeyEndEvent, true);
pointerStartEvents.forEach(function (event) {
document.documentElement.removeEventListener(event, handlePointerStartEvent, true);
});
pointerEndEvents.forEach(function (event) {
document.documentElement.removeEventListener(event, handlePointerEndEvent, true);
});
}
function engage() {
// window blur must be in bubble phase so it won't capture regular blurs
window.addEventListener('blur', handleWindowBlurEvent, false);
// handlers to identify the method of focus change
document.documentElement.addEventListener('keydown', handleKeyStartEvent, true);
document.documentElement.addEventListener('keyup', handleKeyEndEvent, true);
pointerStartEvents.forEach(function (event) {
document.documentElement.addEventListener(event, handlePointerStartEvent, true);
});
pointerEndEvents.forEach(function (event) {
document.documentElement.addEventListener(event, handlePointerEndEvent, true);
});
return {
get: getInteractionType
};
}
exports.default = (0, _decorateService2.default)({ engage: engage, disengage: disengage });
module.exports = exports['default'];
//# sourceMappingURL=interaction-type.js.map