@trustcomponent/trustcaptcha-frontend
Version:
TrustCaptcha – Privacy-first CAPTCHA solution. GDPR-compliant, bot protection made in Europe.
140 lines (139 loc) • 6.06 kB
JavaScript
import { ApiManager } from "./api/api-manager";
import { Status } from "./status";
import { EventTracker } from "./information-collector/event_tracker";
import { ErrorModel } from "./api/error/error-model";
import { ErrorCode } from "./api/error/error-code";
import { SimpleEventEmitter } from "./simple-event-emitter";
export class CaptchaBox {
constructor(config, htmlElement) {
this.statusChangedEvent = new SimpleEventEmitter();
this.captchaFinishEvent = new SimpleEventEmitter();
this.status = Status.START;
this.boxCreationTimestamp = new Date();
this.eventTracker = new EventTracker();
this.verificationToken = null;
this.apiManager = null;
this.config = config;
this.htmlElement = htmlElement;
}
setup() {
this.formElement = this.htmlElement.closest('form');
if (this.formElement != null) {
this.honeypotField = this.createHoneypotField();
this.verificationTokenField = this.createVerificationTokenField();
this.registerElementFocusListeners();
}
else {
this.setErrorStatus(new ErrorModel(ErrorCode.NO_FORM_FOUND, "No parent form element found."));
}
}
createHoneypotField() {
const honeypotField = document.createElement('input');
honeypotField.setAttribute('type', 'text');
honeypotField.setAttribute('name', this.generateHoneypotName());
honeypotField.setAttribute('style', 'display:none');
honeypotField.setAttribute('tabindex', '-1');
this.formElement.appendChild(honeypotField);
return honeypotField;
}
generateHoneypotName() {
const baseNames = [
"userDetail", "confirmAction", "userData", "verifyContact", "sessionInfo",
"profileUpdate", "accountVerify", "securityCheck", "membershipInfo", "customerPreference",
"siteFeedback", "userExperience", "navigationData", "serviceUsage", "interactionTrack",
"clientDetail", "transactionVerify", "operationStatus", "activityLog", "registrationData",
"processCheck", "confirmationStatus", "userContribution", "accessValidation", "engagementLevel",
"validationCode", "preferenceSetting", "userEngage", "activityConfirm", "serviceInteraction"
];
const randomIndex = Math.floor(Math.random() * baseNames.length);
const randomNumber = Math.floor(Math.random() * 1000);
return baseNames[randomIndex] + randomNumber;
}
createVerificationTokenField() {
const verificationTokenField = document.createElement('input');
verificationTokenField.setAttribute('type', 'text');
verificationTokenField.setAttribute('name', this.config.tokenFieldName);
verificationTokenField.setAttribute('style', 'display:none');
verificationTokenField.setAttribute('tabindex', '-1');
return verificationTokenField;
}
registerElementFocusListeners() {
this.formElement.addEventListener('keydown', (event) => {
if (event instanceof KeyboardEvent) {
this.autostartVerification();
}
});
this.formElement.querySelectorAll('input:not([data-autostart="false"]), select:not([data-autostart="false"]), textarea:not([data-autostart="false"])').forEach(element => {
element.addEventListener('focusin', () => {
this.autostartVerification();
});
});
}
autostartVerification() {
if (this.config.autostart) {
this.startVerification();
}
}
startVerification() {
if (this.status !== Status.START) {
return;
}
this.switchStatus(Status.RUNNING);
this.apiManager = new ApiManager(this, (verificationToken) => {
this.eventTracker.stop();
this.finishVerification(verificationToken);
this.apiManager = null;
}, (reason) => {
this.eventTracker.stop();
this.setErrorStatus(reason);
this.apiManager = null;
});
this.apiManager.verify();
}
finishVerification(verificationToken) {
const jsonString = JSON.stringify(verificationToken, ['apiEndpoint', 'verificationId', 'encryptedAccessToken']);
const base64String = btoa(jsonString);
this.verificationToken = base64String;
this.verificationTokenField.setAttribute("value", base64String);
this.formElement.appendChild(this.verificationTokenField);
if (this.timerId)
clearTimeout(this.timerId);
this.timerId = window.setTimeout(() => this.reset(), Math.max(0, (verificationToken.expiresInMs || 900000) - 30000));
this.handleCaptchaSolved();
}
handleCaptchaSolved() {
if (this.verificationToken) {
this.captchaFinishEvent.emit("captchaSolved", this.verificationToken);
this.switchStatus(Status.DONE);
}
}
switchStatus(nextStatus) {
this.status = nextStatus;
this.statusChangedEvent.emit('statusChanged', nextStatus);
}
setErrorStatus(errorModel) {
this.switchStatus(Status.FAILED);
this.captchaFinishEvent.emit("captchaFailed", errorModel);
}
reset() {
if (this.timerId)
clearTimeout(this.timerId);
if (this.apiManager) {
this.apiManager.reset();
this.apiManager = null;
}
this.honeypotField.removeAttribute("value");
this.verificationToken = null;
this.verificationTokenField.removeAttribute("value");
if (this.verificationTokenField && this.formElement.contains(this.verificationTokenField)) {
this.formElement.removeChild(this.verificationTokenField);
}
this.eventTracker.reset();
this.switchStatus(Status.START);
this.captchaFinishEvent.emit("captchaReset");
}
setNewConfig(config) {
this.config = config;
}
}
//# sourceMappingURL=captcha-box.js.map