Viewing File: /usr/local/cpanel/base/securitypolicy/SourceIPCheck/_security_questions.tmpl

[%# This needs to be kept in sync with its WHM counterpart. %]
[%# action, userquestions (hash) %]
[% USE Api2 -%]
[% USE JSON -%]
[%
#----------------------------------------------------------------
# Developer Notes:
#----------------------------------------------------------------
# 1) Extract out the css and js into seperate files and minify
# 2) Replace the YUI2/CJT1 with angularjs or just javascript.
# 3) Remove the popup for validation.
#----------------------------------------------------------------
%]

<link rel="stylesheet" type="text/css" href="[% MagicRevision('/unprotected/yui/assets/skins/sam/autocomplete.css') %]" />
<link rel="stylesheet" type="text/css" href="[% MagicRevision('/unprotected/yui/container/assets/container.css') %]" />

<style type="text/css">
html {
    min-width: 320px;
}

.yui-skin-sam input.yui-ac-input {
    position: static;
    width: auto;
}

.combobox {
    border: 1px solid #aaaaaa;
    display: inline-block;
}

.combobox input {
    border: 0;
    border-right: 1px solid #aaaaaa;
    padding: 2px;
}

.combobox a {
    display: inline-block;
    padding: 0 2px;
}

.combobox a:hover {
    text-decoration: none;
}

.cjt-text-input-placeholder {
    opacity: .5;
    text-align: center;
    font-style: italic;
}

#userform {
    text-align: center; /* Center the continue button on < 480px */
}

tr.answer td {
    padding-bottom: 20px;
}

.cjt_validation_error {
    margin-top: 5px;
}

/* Reset a lot of the odd padding/margin/height/width rules in styles_v2 */

#security-container {
    width: auto;
}

#security-sub-container {
    height: auto;
    width: auto;
    position: relative;  /* Put the container back in the document flow to push the cPanel logo down appropriately */
    left: 0;
}

#security-sub {
    height: auto;
    padding-left: inherit;
}

#security-sub .login-rt {
    padding: 0;
}

.security_policy .copyright {
    margin-top: 30px;
}

</style>

<script src="[% MagicRevision('/yui-gen/data/data.js') %]"></script>
<script src="[% MagicRevision('/yui/autocomplete/autocomplete.js') %]"></script>
<script src="[% MagicRevision('/cjt/combobox.js') %]"></script>

<script>
(function() {
    var questions = [% Api2.exec('SourceIPCheck','samplequestions').json() || '[]' %];
    var selected_questions = [% userquestions.json() || '[]' %];

    var VALID = {};

    /**
     * Validate that the answer has a reasonable length
     *
     * @method answerMinLengthValidator
     * @return {Boolean}
     */
    function answerMinLengthValidator() {
        var value = this.el.value.trim();
        return value.length >= 2;
    };

    /**
     * Validate that the question has a reasonable length
     *
     * @method questionMinLengthValidator
     * @return {Boolean}
     */
    function questionMinLengthValidator() {
        var val = this.el.value.trim();
        return (val.length >= 2);
    };

    /**
     * Factory method to generate a q/a section validator function.
     *
     * @method makeQuestionAnswerValidator
     * @param  {Validator} questionValidator
     * @param  {Validator} answerValidator
     * @return {Function}
     */
    function makeQuestionAnswerValidator(questionValidator, answerValidator) {
        /**
         * Run the the question and answer validation routines.
         *
         * @method validate
         * @private
         */
        return function validate() {
            questionValidator.verify();
            if(questionValidator.is_valid()) {
                var el = answerValidator.validators[0].el;
                if (el.value !== el.defaultValue) {
                    answerValidator.verify();
                }
            }
        };
    }

    /**
     * Factory method to make a select function for the current q & a section.
     *
     * @method makeOnSelectHandler
     * @param  {Function} validateFn
     * @param  {Validator} questionValidator
     * @param  {HtmlInputElement} answerInputEl
     * @return {Function}
     */
    function makeOnSelectHandler(validateFn, questionValidator, answerInputEl) {
        return function() {
            validateFn();
        }
    }

    /**
     * Checked that the current question is not the same as
     * any of the other questions. This is needed since the
     * use can supply any question they want.
     *
     * @method  questionIsUnique
     * @return {Boolean}
     */
    function questionIsUnique() {
        var thisQuestionEl = this.el;
        if (thisQuestionEl.value == thisQuestionEl.defaultValue) {
            return true; // not yet initialized. ignore it for now.
        }

        var questionEls = document.querySelectorAll(".security_question");
        var hasDuplicates = false;

        for(var i = 0, l = questionEls.length; i < l; i++) {
            var questionEl = questionEls[i];
            if (questionEl.id !== thisQuestionEl.id &&           // Not the current question
                questionEl.value !== questionEl.defaultValue) {  // Not comparing to an unset question
                if (questionEl.value === thisQuestionEl.value) {
                    hasDuplicates = true;
                }
            }
        }

        return !hasDuplicates;
    }

    /**
     * Initialize the form
     *
     * @method  init
     * @private
     */
    var init = function() {
        // Setup the validators for
        // the questions & answers
        for (var i = 1; i <= 4; i++) {
            // NOTE: There are 4 sets of questions generated.
            // So this look divides the questions list into 4 groups
            // of 7:
            //   questions 0-7,
            //   questions 8-13,
            //   questions 14-21,
            //   ...
            var currentQuestions = questions.slice(7 * (i - 1), 7 + 7 * (i - 1));
            var questionInputEl = DOM.get("q" + i + "ques");
            var questionExpanderEl = DOM.get("q" + i + "_expander");
            var answerInputEl = DOM.get("q" + i + "answer");

            // Remove the current question from the available questions
            // so we can only have one of the n questions with that question.
            if ( questionInputEl.value && (currentQuestions.indexOf(questionInputEl.value) === -1) ) {
                currentQuestions.unshift(questionInputEl.value);
            }

            // Attach the dropdown part of the combo to each question
            var cb = new CPANEL.widgets.Combobox( questionInputEl, null, currentQuestions, {
                    expander: questionExpanderEl
                } );
            cb.formatResult = cb.formatEscapedResult;

            // Build the question validation
            var questionValidator = new CPANEL.validate.validator("[% locale.maketext('Question') %]" + " " + LOCALE.numf(i));
            questionValidator.add(questionInputEl, "max_length($input$,128)", "[% locale.maketext('The question cannot be longer than 128 characters.') %]", null, { no_width_height: 1 });
            questionValidator.add(questionInputEl, questionMinLengthValidator, "[% locale.maketext('The question must be at least 2 characters long.') %]", null, { no_width_height: 1 });
            questionValidator.add(questionInputEl, questionIsUnique, "[% locale.maketext('The question must be unique.') %]", null, { no_width_height: 1 });
            questionValidator.attach();

            // Build the answer validation
            var answerValidator = new CPANEL.validate.validator("[% locale.maketext('Answer') %]" + " " + LOCALE.numf(i));
            answerValidator.add(answerInputEl, "max_length($input$,128)", "[% locale.maketext('The answer cannot be longer than 128 characters.') %]", null, { no_width_height: 1 });

            answerValidator.add(answerInputEl, answerMinLengthValidator, "[% locale.maketext('The answer must be at least 2 characters long.') %]", null, { no_width_height: 1 });

            // Attach the section Q & A valiators to run if there is a
            // change in the question via typing or the dropbox selection
            var validateFn = makeQuestionAnswerValidator(questionValidator, answerValidator);
            EVENT.on( questionInputEl, "keydown", validateFn );
            EVENT.on( questionInputEl, "keyup", validateFn );
            EVENT.on( questionInputEl, "blur", validateFn );
            EVENT.on( questionInputEl, "input", validateFn );
            cb.itemSelectEvent.subscribe( makeOnSelectHandler(validateFn, questionValidator, answerInputEl) );

            if (questionInputEl.defaultValue) {
                YAHOO.util.Dom.setAttribute(
                    answerInputEl,
                    "placeholder",
                    "[% locale.maketext('No change') %]"
                );
            }

            VALID["q" + i] = questionValidator;
            VALID["a" + i] = answerValidator;
            VALID["a" + i].attach();
        }

        CPANEL.validate.attach_to_form("submit-button", VALID);

        // Move the focus to the first question
        // so keyboard users don't have to tab
        // around.
        DOM.get("q1ques").focus();
    }

    YAHOO.util.Event.onDOMReady(init);

})();
</script>

<form name="userform" id="userform" action="[% action FILTER html %]" method="post">
    <input type="hidden" name="formaction" value="setquestions" />

    <table>
    [% FOR i = [1 .. 4] -%]
        <tr class="question-row">
            <td class="label-cell">
                <label for="q[%i%]">[% locale.maketext('Question [numf,_1]:',i) %]</label>
            </td>
            <td class="field-cell">
                <div class="combobox"><input id="q[%i%]ques" name="q[%i%]ques" class="security_question" value="[% userquestions.$i FILTER html %]" size="50" placeholder="[% locale.maketext('Select a security question, or enter your own.') %]" /><span id="q[%i%]_expander" class="security_question_expander">▼</span>
                </div>
                <div id="q[%i%]ques_error" class="security_question_error show_inline"></div>
            </td>
        </tr>
        <tr class="answer">
            <td class="label-cell">
                <label for="q[%i%]answer">[% locale.maketext('Answer [numf,_1]:', i) %]</label>
            </td>
            <td class="field-cell">
                <input id="q[%i%]answer" class="security_question_answer" name="q[%i%]answer" size="50" />
                <div id="q[%i%]answer_error" class="show_inline"></div>
            </td>
        </tr>
    [% END -%]
    </table>

    <button type="submit" id="submit-button" class="input-button" />
        [% locale.maketext("Continue") %]
    </button>
</form>
Back to Directory File Manager