Explorar el Código

Perform more advanced input and string sanitization and validation for performance and security

Nariman Jelveh hace 1 año
padre
commit
ce411ed728

+ 1 - 1
src/UI/UINotification.js

@@ -25,7 +25,7 @@ function UINotification(options){
     let h = '';
     h += `<div id="ui-notification__${global_element_id}" class="notification antialiased animate__animated animate__fadeInRight animate__slow">`;
         h += `<img class="notification-close" src="${html_encode(window.icons['close.svg'])}">`;
-        h += options.content;
+        h += html_encode(options.content);
     h += `</div>`;
 
     $('body').append(h);

+ 14 - 4
src/UI/UIWindowChangePassword.js

@@ -88,21 +88,31 @@ async function UIWindowChangePassword(options){
         const new_password = $(el_window).find('.new-password').val();
         const confirm_new_password = $(el_window).find('.confirm-new-password').val();
 
-        let data;
+        // hide success message
+        $(el_window).find('.form-success-msg').hide();
 
-        if(current_password === '' || new_password === '' || confirm_new_password === ''){
+        // check if all fields are filled
+        if(!current_password || !new_password || !confirm_new_password){
             $(el_window).find('.form-error-msg').html('All fields are required.');
             $(el_window).find('.form-error-msg').fadeIn();
             return;
         }
+        // check if new password and confirm new password are the same
         else if(new_password !== confirm_new_password){
             $(el_window).find('.form-error-msg').html(i18n('passwords_do_not_match'));
             $(el_window).find('.form-error-msg').fadeIn();
             return;
         }
-        
+        // check password strength
+        const pass_strength = check_password_strength(new_password);
+        if(!pass_strength.overallPass){
+            $(el_window).find('.form-error-msg').html(i18n('password_strength_error'));
+            $(el_window).find('.form-error-msg').fadeIn();
+            return;
+        }
+
         $(el_window).find('.form-error-msg').hide();
-    
+
         $.ajax({
             url: api_origin + "/passwd",
             type: 'POST',

+ 9 - 3
src/UI/UIWindowNewPassword.js

@@ -30,8 +30,6 @@ async function UIWindowNewPassword(options){
         h += `<div class="change-password" style="padding: 20px; border-bottom: 1px solid #ced7e1;">`;
             // error msg
             h += `<div class="form-error-msg"></div>`;
-            // success msg
-            h += `<div class="form-success-msg"></div>`;
             // new password
             h += `<div style="overflow: hidden; margin-top: 20px; margin-bottom: 20px;">`;
                 h += `<label for="new-password-${internal_id}">${i18n('new_password')}</label>`;
@@ -84,7 +82,7 @@ async function UIWindowNewPassword(options){
             const new_password = $(el_window).find('.new-password').val();
             const confirm_new_password = $(el_window).find('.confirm-new-password').val();
 
-            if(new_password === '' || confirm_new_password === ''){
+            if(!new_password || !confirm_new_password){
                 $(el_window).find('.form-error-msg').html('All fields are required.');
                 $(el_window).find('.form-error-msg').fadeIn();
                 return;
@@ -94,6 +92,14 @@ async function UIWindowNewPassword(options){
                 $(el_window).find('.form-error-msg').fadeIn();
                 return;
             }
+
+            // check password strength
+            const pass_strength = check_password_strength(new_password);
+            if(!pass_strength.overallPass){
+                $(el_window).find('.form-error-msg').html(i18n('password_strength_error'));
+                $(el_window).find('.form-error-msg').fadeIn();
+                return;
+            }
             
             $(el_window).find('.form-error-msg').hide();
         

+ 37 - 6
src/UI/UIWindowSignup.js

@@ -114,7 +114,7 @@ function UIWindowSignup(options){
                 'justify-content': 'center',
                 'align-items': 'center',
                 padding: '30px 10px 10px 10px',
-            }    
+            }
         })
 
         $(el_window).find('.login-c2a-clickable').on('click', async function(e){
@@ -132,17 +132,48 @@ function UIWindowSignup(options){
         })
 
         $(el_window).find('.signup-btn').on('click', function(e){
-            // todo do some basic validation client-side
-
             //Username
             let username = $(el_window).find('.username').val();
+
+            if(!username){
+                $(el_window).find('.signup-error-msg').html(i18n('username_required'));
+                $(el_window).find('.signup-error-msg').fadeIn();
+                return;
+            }
         
             //Email
             let email = $(el_window).find('.email').val();
-        
+
+            // must have an email
+            if(!email){
+                $(el_window).find('.signup-error-msg').html(i18n('email_required'));
+                $(el_window).find('.signup-error-msg').fadeIn();
+                return;
+            }
+            // must be a valid email
+            else if(!is_email(email)){
+                $(el_window).find('.signup-error-msg').html(i18n('email_invalid'));
+                $(el_window).find('.signup-error-msg').fadeIn();
+                return;
+            }
+
             //Password
             let password = $(el_window).find('.password').val();
-            
+
+            // must have a password
+            if(!password){
+                $(el_window).find('.signup-error-msg').html(i18n('password_required'));
+                $(el_window).find('.signup-error-msg').fadeIn();
+                return;
+            }
+            // check password strength
+            const pass_strength = check_password_strength(password);
+            if(!pass_strength.overallPass){
+                $(el_window).find('.signup-error-msg').html(i18n('password_strength_error'));
+                $(el_window).find('.signup-error-msg').fadeIn();
+                return;
+            }
+
             //xyzname
             let p102xyzname = $(el_window).find('.p102xyzname').val();
 
@@ -186,7 +217,7 @@ function UIWindowSignup(options){
                 error: function (err){
                     $(el_window).find('.signup-error-msg').html(err.responseText);
                     $(el_window).find('.signup-error-msg').fadeIn();
-                    // re-enable 'Create Account' button
+                    // re-enable 'Create Account' button so user can try again
                     $(el_window).find('.signup-btn').prop('disabled', false);
                 }
             });

+ 0 - 4
src/UI/UIWindowTaskManager.js

@@ -34,10 +34,6 @@ const UIWindowTaskManager = async function UIWindowTaskManager () {
         body_css: {
             width: 'initial',
             padding: '20px',
-            // 'background-color': `hsla(
-            //     var(--primary-hue),
-            //     calc(max(var(--primary-saturation) - 15%, 0%)),
-            //     calc(min(100%,var(--primary-lightness) + 20%)), .91)`,
             'background-color': `hsla(
                 var(--primary-hue),
                 var(--primary-saturation),

+ 50 - 2
src/helpers.js

@@ -27,10 +27,8 @@ import UIWindowSaveAccount from './UI/UIWindowSaveAccount.js';
 import UIWindowCopyProgress from './UI/UIWindowCopyProgress.js';
 import UIWindowMoveProgress from './UI/UIWindowMoveProgress.js';
 import UIWindowNewFolderProgress from './UI/UIWindowNewFolderProgress.js';
-import UIWindowDownloadProgress from './UI/UIWindowDownloadProgress.js';
 import UIWindowUploadProgress from './UI/UIWindowUploadProgress.js';
 import UIWindowProgressEmptyTrash from './UI/UIWindowProgressEmptyTrash.js';
-import download from './helpers/download.js';
 import update_username_in_gui from './helpers/update_username_in_gui.js';
 import update_title_based_on_uploads from './helpers/update_title_based_on_uploads.js';
 import content_type_to_icon from './helpers/content_type_to_icon.js';
@@ -3497,3 +3495,53 @@ window.report_app_closed = (instance_id) => {
 
     // TODO: Once other AppConnections exist, those will need notifying too.
 };
+
+window.check_password_strength = (password) => {
+    // Define criteria for password strength
+    const criteria = {
+        minLength: 8,
+        hasUpperCase: /[A-Z]/.test(password),
+        hasLowerCase: /[a-z]/.test(password),
+        hasNumber: /\d/.test(password),
+        hasSpecialChar: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)
+    };
+
+    let overallPass = true;
+
+    // Initialize report object
+    let criteria_report = {
+        minLength: {
+            message: `Password must be at least ${criteria.minLength} characters long`,
+            pass: password.length >= criteria.minLength,
+        },
+        hasUpperCase: {
+            message: 'Password must contain at least one uppercase letter',
+            pass: criteria.hasUpperCase,
+        },
+        hasLowerCase: {
+            message: 'Password must contain at least one lowercase letter',
+            pass: criteria.hasLowerCase,
+        },
+        hasNumber: {
+            message: 'Password must contain at least one number',
+            pass: criteria.hasNumber,
+        },
+        hasSpecialChar: {
+            message: 'Password must contain at least one special character',
+            pass: criteria.hasSpecialChar,
+        },
+    };
+
+    // Check overall pass status and add messages
+    for (let criterion in criteria) {
+        if (!criteria_report[criterion].pass) {
+            overallPass = false;
+            break;
+        }
+    }
+
+    return {
+        overallPass: overallPass,
+        report: criteria_report,
+    };
+}

+ 4 - 0
src/i18n/translations/en.js

@@ -88,6 +88,7 @@ const en = {
         email: "Email",
         email_change_confirmation_sent: "A confirmation email has been sent to your new email address. Please check your inbox and follow the instructions to complete the process.",
         email_or_username: "Email or Username",
+        email_required: 'Email is required.',
         empty_trash: 'Empty Trash',
         empty_trash_confirmation: `Are you sure you want to permanently delete the items in Trash?`,
         emptying_trash: 'Emptying Trash…',
@@ -148,6 +149,8 @@ const en = {
         oss_code_and_content: "Open Source Software and Content",
         password: "Password",
         password_changed: "Password changed.",
+        password_required: 'Password is required.',
+        password_strength_error: "Password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one special character.",
         passwords_do_not_match: '`New Password` and `Confirm New Password` do not match.',
         paste: 'Paste',
         paste_into_folder: "Paste Into Folder",
@@ -238,6 +241,7 @@ const en = {
         usage: 'Usage',
         username: "Username",
         username_changed: 'Username updated successfully.',
+        username_required: 'Username is required.',
         versions: "Versions",
         visibility: 'Visibility',
         yes: 'Yes',