Project

General

Profile

Actions

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

{
  "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

<!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 & FormIO để tạo form sau khi page load xong
  • 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 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

Demo

Updated by Lê Sĩ Quý 8 months ago · 4 revisions