Project

General

Profile

Form Login » History » Version 3

Lê Sĩ Quý, 08/28/2025 06:45 PM

1 1 Lê Sĩ Quý
{{TOC}}
2
3
# Login
4
5
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.
6
7
## JSON Schema
8
9
Gồm 2 trường email và password
10
11
``` javascript
12
{
13
  "display": "form",
14
  "components": [
15
    {
16
      "label": "Email",
17
      "applyMaskOn": "change",
18
      "tableView": true,
19
      "validate": {
20
        "required": true
21
      },
22
      "validateWhenHidden": false,
23
      "key": "email",
24
      "type": "email",
25
      "input": true
26
    },
27
    {
28
      "label": "Password",
29
      "applyMaskOn": "change",
30
      "tableView": false,
31
      "validate": {
32
        "required": true
33
      },
34
      "validateWhenHidden": false,
35
      "key": "password",
36
      "type": "password",
37
      "input": true,
38
      "protected": true
39
    },
40
    {
41
      "label": "Login",
42
      "showValidations": false,
43
      "disableOnInvalid": true,
44
      "tableView": false,
45
      "key": "submit",
46
      "type": "button",
47
      "input": true,
48
      "saveOnEnter": false
49
    }
50
  ]
51
}
52
```
53 2 Lê Sĩ Quý
54
## HTML Template
55
56
``` html
57
<!DOCTYPE html>
58
<html lang="en">
59
60
<head>
61
    <meta charset="UTF-8">
62
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
63
    <title>Northwind - Đăng nhập</title>
64
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
65
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css">
66
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css">
67
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
68
    <script src="https://cdn.form.io/js/formio.embed.js"></script>
69
    <script src="https://cdn.jsdelivr.net/npm/localstorage-slim"></script>
70
    <script src="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js"></script>
71
    <style>
72
        body {
73
            font-family: sans-serif;
74
            background-color: #f4f4f4;
75
            display: flex;
76
            justify-content: center;
77
            align-items: center;
78
            min-height: 100vh;
79
            margin: 0;
80
        }
81
82
        button[type="submit"] {
83
            background-color: #007bff;
84
            color: white;
85
            padding: 10px 15px;
86
            border: none;
87
            border-radius: 4px;
88
            cursor: pointer;
89
            font-size: 1em;
90
            width: 100%;
91
        }
92
93
        .login-container {
94
            background-color: #fff;
95
            padding: 30px;
96
            border-radius: 8px;
97
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
98
            width: 400px;
99
            max-width: 90%;
100
            text-align: center;
101
        }
102
103
        .logo-container {
104
            margin-bottom: 20px;
105
        }
106
107
        .logo {
108
            max-width: 100px;
109
            height: auto;
110
        }
111
112
        .app-name {
113
            font-size: 1.5em;
114
            color: #333;
115
            margin-top: 10px;
116
            text-transform: uppercase;
117
        }
118
119
        .form-group {
120
            margin-bottom: 20px;
121
            text-align: left;
122
        }
123
124
125
        .copyright {
126
            margin-top: 20px;
127
            font-size: 0.9em;
128
            color: #777;
129
        }
130
131
        /* Responsive adjustments */
132
        @media (max-width: 600px) {
133
            .login-container {
134
                padding: 20px;
135
            }
136
137
            .logo {
138
                max-width: 80px;
139
            }
140
141
            .app-name {
142
                font-size: 1.2em;
143
            }
144
145
            .copyright {
146
                font-size: 0.8em;
147
            }
148
        }
149
    </style>
150
</head>
151
152
<body>
153
    <div class="login-container">
154
        <div class="logo-container">
155
            <img src="https://northwind.gal/wp-content/uploads/2021/06/northwind-footer-logo.png" alt="Logo" class="logo">
156
            <h1 class="app-name">Orders Management</h1>
157
        </div>
158
        <div class="form-group" id="formio"></div>
159
160
        <p class="copyright">&copy; 2025 Northwind, LLC. All rights reserved.</p>
161
    </div>
162
    <script>
163
        var curForm;
164
        var submission = {};
165
166
        $(function () {
167
            Formio.createForm(document.getElementById("formio"), <?!= template ?>)
168
                .then(function (form) {
169
                    // Prevent the submission from going to the form.io server.
170
                    form.noAlerts = true;
171
                    form.nosubmit = true;
172
                    curForm = form;
173
174
                    // Triggered when they click the submit button.
175
                    form.on("submit", function (obj) {
176
                        submission = obj;
177
                        google.script.run
178
                            .withSuccessHandler(onSuccess)
179
                            .withFailureHandler(onFailure)
180
                            .login(submission.data);
181
                    });
182
                });
183
        });
184
185
        function onFailure(err) {
186
            curForm.emit("submitError", err);
187
            var notyf = new Notyf();
188
            notyf.error(err.message);
189
        }
190
191
        function onSuccess(sid) {
192
            if (sid) {
193
                curForm.emit("submitDone", submission);
194
                let url = "<?!= base ?>?url=<?!= callback ?>";
195
                window.top.location.href = url;
196
                ls.set("sid", sid);
197
                ls.set("email", submission.data.email);
198
            } else {
199
                let message = "Login Failed. Your user ID or password is incorrect.";
200
                curForm.emit("submitError", new Error(message));
201
                var notyf = new Notyf();
202
                notyf.error(message);
203
            }
204
        }
205
    </script>
206
</body>
207
208
</html>
209
```
210 3 Lê Sĩ Quý
211
## Giải thích Code
212
213
Form login sử dụng cácthư viện sau:
214
- [jQuery](https://jquery.com/) & [FormIO](https://help.form.io/developers/form-development/form-renderer) để tạo form sau khi page load xong
215
- [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
216
- [Notyf](https://carlosroso.com/notyf/) hiển thị thông báo.
217
- 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**