DEV Community

Charlie Fubon
Charlie Fubon

Posted on

D3


/**
 * Copyright (c) 2025 Canadian Imperial Bank of Commerce. All rights reserved.
 * Simplified Digital Identity Verification Tool - Widget Constructor Pattern
 */

com.cibc.go.myclient.view.form.widget.DigitalIdentityVerificationTool = (function($, superClass, global, utilities, DigitalIdentityVerification) {
    utilities.assertArrayElementsNotNull(arguments);

    var divTool = function(widgetFactory, parent, settings) {
        var self = this;
        var newSettings = $.extend({
            trigger: settings.trigger ? settings.trigger : "button",
            dialog: self.showDialog
        }, settings);
        superClass.call(self, widgetFactory, parent, newSettings);
    };

    utilities.inherits(divTool, superClass);
    divTool.superclass_ = superClass.prototype;

    /**
     * @override
     */
    divTool.prototype.postRender = function() {
        var self = this;
        divTool.superclass_.postRender.call(this);
        this.element && this.element.find('.ui-button-icon-primary').remove();
    };

    /**
     * Show simplified DIV verification - no redundant data collection
     */
    divTool.prototype.showDialog = function() {
        var self = this;
        var clientData = this.getClientData();
        var validationErrors = this.validateClientData(clientData);

        if (validationErrors.length > 0) {
            this.showValidationErrorDialog(validationErrors);
            return;
        }

        var validEmails = this.getValidEmails(clientData.emails);

        if (validEmails.length === 1) {
            this.performDivVerification(clientData, validEmails[0]);
        } else if (validEmails.length > 1) {
            this.showEmailSelectionDialog(clientData, validEmails);
        }
    };

    /**
     * Extract client data from existing form fields
     */
    divTool.prototype.getClientData = function() {
        var client = com.cibc.go.myclient.global.CurrentPage.client;
        var clientData = {
            firstName: client.get(com.cibc.go.myclient.model.FieldConstants.Client.firstName.id) || "",
            lastName: client.get(com.cibc.go.myclient.model.FieldConstants.Client.lastName.id) || "",
            dateOfBirth: client.get(com.cibc.go.myclient.model.FieldConstants.Client.dob.id) || "",
            preferredLanguage: client.get(com.cibc.go.myclient.model.FieldConstants.Client.languageCode.id) || "",
            iaCode: client.get(com.cibc.go.myclient.model.FieldConstants.Client.iaCode.id) || "",
            emails: []
        };

        // Collect email addresses
        for (var i = 0; i <= 2; i++) {
            var emailKey = 'emailInfo[' + i + '].emailAddress';
            var emailAddress = client.get(emailKey);
            if (emailAddress && this.isValidEmail(emailAddress)) {
                clientData.emails.push(emailAddress);
            }
        }

        return clientData;
    };

    /**
     * Validate required client data
     */
    divTool.prototype.validateClientData = function(clientData) {
        var errors = [];

        if (!clientData.firstName) errors.push("First Name is required");
        if (!clientData.lastName) errors.push("Last Name is required");
        if (!clientData.dateOfBirth) errors.push("Date of Birth is required");
        if (!clientData.preferredLanguage) errors.push("Preferred Language is required");
        if (!clientData.iaCode) errors.push("IA Code is required");
        if (clientData.emails.length === 0) errors.push("At least one valid email address is required");

        return errors;
    };

    /**
     * Basic email validation
     */
    divTool.prototype.isValidEmail = function(email) {
        if (!email || typeof email !== 'string') return false;
        var atIndex = email.indexOf('@');
        if (atIndex === -1 || atIndex === 0 || atIndex === email.length - 1) return false;
        var domainPart = email.substring(atIndex + 1);
        return domainPart.indexOf('.') !== -1;
    };

    /**
     * Filter valid emails
     */
    divTool.prototype.getValidEmails = function(emails) {
        var validEmails = [];
        for (var i = 0; i < emails.length; i++) {
            if (this.isValidEmail(emails[i])) {
                validEmails.push(emails[i]);
            }
        }
        return validEmails;
    };

    /**
     * Show validation error dialog
     */
    divTool.prototype.showValidationErrorDialog = function(errors) {
        var dialogContent = '<div style="padding: 15px;">' +
                           '<p><strong>Please correct the following:</strong></p>' +
                           '<ul style="margin: 10px 0; padding-left: 20px;">';

        for (var i = 0; i < errors.length; i++) {
            dialogContent += '<li style="margin: 5px 0;">' + errors[i] + '</li>';
        }

        dialogContent += '</ul></div>';

        this.createDialog('Validation Required', dialogContent, [{
            text: 'OK',
            click: function() { $(this).dialog('close'); }
        }]);
    };

    /**
     * Show email selection dialog
     */
    divTool.prototype.showEmailSelectionDialog = function(clientData, validEmails) {
        var self = this;
        var emailOptions = '';

        for (var i = 0; i < validEmails.length; i++) {
            emailOptions += '<option value="' + validEmails[i] + '">' + validEmails[i] + '</option>';
        }

        var dialogContent = '<div style="padding: 15px;">' +
                           '<label>Select email for verification:</label><br/><br/>' +
                           '<select id="divEmailSelect" style="width: 100%; padding: 5px;">' +
                           emailOptions +
                           '</select>' +
                           '</div>';

        this.createDialog('Select Email', dialogContent, [
            {
                text: 'Continue',
                click: function() {
                    var selectedEmail = $('#divEmailSelect').val();
                    $(this).dialog('close');
                    self.performDivVerification(clientData, selectedEmail);
                }
            },
            {
                text: 'Cancel',
                click: function() { $(this).dialog('close'); }
            }
        ]);
    };

    /**
     * Generic dialog helper
     */
    divTool.prototype.createDialog = function(title, content, buttons) {
        var dialogId = 'divDialog_' + Date.now();
        var dialogHtml = '<div id="' + dialogId + '" title="' + title + '">' + content + '</div>';

        $(dialogHtml).dialog({
            width: 400,
            modal: true,
            resizable: false,
            buttons: buttons,
            close: function() {
                $('#' + dialogId).remove();
            }
        });
    };

    /**
     * Perform DIV verification
     */
    divTool.prototype.performDivVerification = function(clientData, selectedEmail) {
        var userData = {
            client: {
                firstName: clientData.firstName,
                lastName: clientData.lastName,
                dob: clientData.dateOfBirth,
                languageCode: clientData.preferredLanguage,
                iaCode: clientData.iaCode
            }
        };

        // Sanitize data
        var finalData = this.sanitizeCrossRefId(userData);

        // Create authentication iframe
        var authFrame = this.createAuthFrame();
        var self = this;

        authFrame.onload = function() {
            try {
                var authCode = self.extractAuthCode(authFrame);
                if (authCode) {
                    self.submitDivRequest(finalData, selectedEmail, authCode);
                }
                document.body.removeChild(authFrame);
            } catch(e) {
                document.body.removeChild(authFrame);
                self.showErrorMessage("Authentication failed. Please try again.");
            }
        };
    };

    /**
     * Sanitize cross reference data
     */
    divTool.prototype.sanitizeCrossRefId = function(userData) {
        var sanitized = $.extend(true, {}, userData);
        for(var key in sanitized) {
            if(sanitized[key] === "") {
                sanitized[key] = null;
            }
        }
        return sanitized;
    };

    /**
     * Create hidden authentication iframe
     */
    divTool.prototype.createAuthFrame = function() {
        var frame = document.createElement('iframe');
        frame.style.display = 'none';
        frame.src = document.getElementById('authRedirectFrame').src;
        document.body.appendChild(frame);
        return frame;
    };

    /**
     * Extract auth code from redirected URL
     */
    divTool.prototype.extractAuthCode = function(frame) {
        var redirectedUrl = frame.contentWindow.location.href;
        var authCode = redirectedUrl.match(/[?&]code=([^&]*)/);
        return authCode ? authCode[1] : null;
    };

    /**
     * Submit DIV request
     */
    divTool.prototype.submitDivRequest = function(userData, email, authCode) {
        var self = this;

        $.ajax({
            type: "POST",
            url: "/client/idVerify",
            data: {
                clients: JSON.stringify([userData]),
                emailForDiv: email,
                crossRefId: null,
                authCode: authCode,
                debugConsoleChanges: "[]"
            },
            success: function(response) {
                self.handleDivResponse(response);
            },
            error: function() {
                self.showErrorMessage("Verification request failed. Please try again.");
            }
        });
    };

    /**
     * Handle DIV response
     */
    divTool.prototype.handleDivResponse = function(data) {
        if (data && data.returnCode === "ERROR") {
            var errorMsg = "Verification failed. Please try again.";
            if (data.errorMessages && data.errorMessages.length > 0) {
                errorMsg = data.errorMessages.join(', ');
            }
            this.showErrorMessage(errorMsg);
        } else {
            this.showSuccessMessage("Identity verification initiated successfully.");
        }
    };

    /**
     * Show error message
     */
    divTool.prototype.showErrorMessage = function(message) {
        this.createDialog('Error', '<div style="padding: 15px;">' + message + '</div>', [{
            text: 'OK',
            click: function() { $(this).dialog('close'); }
        }]);
    };

    /**
     * Show success message  
     */
    divTool.prototype.showSuccessMessage = function(message) {
        this.createDialog('Success', '<div style="padding: 15px;">' + message + '</div>', [{
            text: 'OK',
            click: function() { $(this).dialog('close'); }
        }]);
    };

    /**
     * @override - Don't let user edit in text box
     */
    divTool.prototype.showEditor = function(event) {
        return this;
    };

    /**
     * @override
     */
    divTool.prototype.clickEditor = function(event) {
        return this;
    };

    return divTool;

})(jQuery, com.cibc.go.myclient.view.form.widget.DataPicker, com.cibc.go.myclient.global, com.cibc.go.Utilities, com.cibc.go.myclient.view.DigitalIdentityVerification);

Enter fullscreen mode Exit fullscreen mode

Top comments (0)