Project

General

Profile

Form Login » History » Revision 3

Revision 2 (Lê Sĩ Quý, 08/28/2025 12:05 PM) → Revision 3/4 (Lê Sĩ Quý, 08/28/2025 06:45 PM)

{{TOC}} 

 # Login 

 Northwind app sử dụng cơ chế authentcation đơn giản cung cấp bởi AKA-Form. Hệ thống thiết lập giá trị cứng cho email/password. Giá trị password được hash bằng hàm md5. 

 ## JSON Schema 

 Gồm 2 trường email và password 

 ``` javascript 
 { 
   "display": "form", 
   "components": [ 
     { 
       "label": "Email", 
       "applyMaskOn": "change", 
       "tableView": true, 
       "validate": { 
         "required": true 
       }, 
       "validateWhenHidden": false, 
       "key": "email", 
       "type": "email", 
       "input": true 
     }, 
     { 
       "label": "Password", 
       "applyMaskOn": "change", 
       "tableView": false, 
       "validate": { 
         "required": true 
       }, 
       "validateWhenHidden": false, 
       "key": "password", 
       "type": "password", 
       "input": true, 
       "protected": true 
     }, 
     { 
       "label": "Login", 
       "showValidations": false, 
       "disableOnInvalid": true, 
       "tableView": false, 
       "key": "submit", 
       "type": "button", 
       "input": true, 
       "saveOnEnter": false 
     } 
   ] 
 } 
 ``` 

 ## HTML Template 

 ``` html 
 <!DOCTYPE html> 
 <html lang="en"> 

 <head> 
     <meta charset="UTF-8"> 
     <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
     <title>Northwind - Đăng nhập</title> 
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css"> 
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css"> 
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css"> 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
     <script src="https://cdn.form.io/js/formio.embed.js"></script> 
     <script src="https://cdn.jsdelivr.net/npm/localstorage-slim"></script> 
     <script src="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js"></script> 
     <style> 
         body { 
             font-family: sans-serif; 
             background-color: #f4f4f4; 
             display: flex; 
             justify-content: center; 
             align-items: center; 
             min-height: 100vh; 
             margin: 0; 
         } 

         button[type="submit"] { 
             background-color: #007bff; 
             color: white; 
             padding: 10px 15px; 
             border: none; 
             border-radius: 4px; 
             cursor: pointer; 
             font-size: 1em; 
             width: 100%; 
         } 

         .login-container { 
             background-color: #fff; 
             padding: 30px; 
             border-radius: 8px; 
             box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 
             width: 400px; 
             max-width: 90%; 
             text-align: center; 
         } 

         .logo-container { 
             margin-bottom: 20px; 
         } 

         .logo { 
             max-width: 100px; 
             height: auto; 
         } 

         .app-name { 
             font-size: 1.5em; 
             color: #333; 
             margin-top: 10px; 
             text-transform: uppercase; 
         } 

         .form-group { 
             margin-bottom: 20px; 
             text-align: left; 
         } 


         .copyright { 
             margin-top: 20px; 
             font-size: 0.9em; 
             color: #777; 
         } 

         /* Responsive adjustments */ 
         @media (max-width: 600px) { 
             .login-container { 
                 padding: 20px; 
             } 

             .logo { 
                 max-width: 80px; 
             } 

             .app-name { 
                 font-size: 1.2em; 
             } 

             .copyright { 
                 font-size: 0.8em; 
             } 
         } 
     </style> 
 </head> 

 <body> 
     <div class="login-container"> 
         <div class="logo-container"> 
             <img src="https://northwind.gal/wp-content/uploads/2021/06/northwind-footer-logo.png" alt="Logo" class="logo"> 
             <h1 class="app-name">Orders Management</h1> 
         </div> 
         <div class="form-group" id="formio"></div> 

         <p class="copyright">&copy; 2025 Northwind, LLC. All rights reserved.</p> 
     </div> 
     <script> 
         var curForm; 
         var submission = {}; 

         $(function () { 
             Formio.createForm(document.getElementById("formio"), <?!= template ?>) 
                 .then(function (form) { 
                     // Prevent the submission from going to the form.io server. 
                     form.noAlerts = true; 
                     form.nosubmit = true; 
                     curForm = form; 

                     // Triggered when they click the submit button. 
                     form.on("submit", function (obj) { 
                         submission = obj; 
                         google.script.run 
                             .withSuccessHandler(onSuccess) 
                             .withFailureHandler(onFailure) 
                             .login(submission.data); 
                     }); 
                 }); 
         }); 

         function onFailure(err) { 
             curForm.emit("submitError", err); 
             var notyf = new Notyf(); 
             notyf.error(err.message); 
         } 

         function onSuccess(sid) { 
             if (sid) { 
                 curForm.emit("submitDone", submission); 
                 let url = "<?!= base ?>?url=<?!= callback ?>"; 
                 window.top.location.href = url; 
                 ls.set("sid", sid); 
                 ls.set("email", submission.data.email); 
             } else { 
                 let message = "Login Failed. Your user ID or password is incorrect."; 
                 curForm.emit("submitError", new Error(message)); 
                 var notyf = new Notyf(); 
                 notyf.error(message); 
             } 
         } 
     </script> 
 </body> 

 </html> 
 ``` 

 ## Giải thích Code 

 Form login sử dụng cácthư viện sau: 
 - [jQuery](https://jquery.com/) & [FormIO](https://help.form.io/developers/form-development/form-renderer) để tạo form sau khi page load xong 
 - [localstorage-slim](https://github.com/digitalfortress-tech/localstorage-slim) để lưu sid & email sau khi login thành công. Các giá trị này sẽ được xóa khi logout 
 - [Notyf](https://carlosroso.com/notyf/) hiển thị thông báo. 
 - Các thư viện đều được load từ CDN để tối ưu tốc độ, đơn giản hóa HTML Templated. Các bạn cần có kiến thức trong phần yêu cầu để hiểu logic của code JS + templated nhúng trong page. Trong page này gọi đến hàm backend **login** để kiểm tra thông tin đăng nhập bằng cách so sánh email + password với thông tin được lưu trữ trong sheet **Users**