odac 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/auto-pr-description.yml +0 -2
- package/.github/workflows/codeql.yml +46 -0
- package/.github/workflows/release.yml +13 -6
- package/.github/workflows/test-coverage.yml +10 -9
- package/.releaserc.js +9 -6
- package/CHANGELOG.md +62 -150
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTING.md +8 -8
- package/LICENSE +21 -661
- package/README.md +12 -12
- package/SECURITY.md +4 -4
- package/bin/odac.js +101 -0
- package/{framework/web/candy.js → client/odac.js} +310 -44
- package/docs/backend/01-overview/{01-whats-in-the-candy-box.md → 01-whats-in-the-odac-box.md} +4 -2
- package/docs/backend/01-overview/02-super-handy-helper-functions.md +29 -1
- package/docs/backend/01-overview/03-development-server.md +11 -11
- package/docs/backend/02-structure/01-typical-project-layout.md +4 -4
- package/docs/backend/03-config/00-configuration-overview.md +6 -6
- package/docs/backend/03-config/01-database-connection.md +1 -1
- package/docs/backend/03-config/02-static-route-mapping-optional.md +4 -4
- package/docs/backend/03-config/04-environment-variables.md +20 -20
- package/docs/backend/03-config/05-early-hints.md +4 -4
- package/docs/backend/04-routing/01-basic-page-routes.md +4 -4
- package/docs/backend/04-routing/02-controller-less-view-routes.md +5 -5
- package/docs/backend/04-routing/03-api-and-data-routes.md +3 -3
- package/docs/backend/04-routing/04-authentication-aware-routes.md +5 -5
- package/docs/backend/04-routing/05-advanced-routing.md +3 -3
- package/docs/backend/04-routing/06-error-pages.md +17 -17
- package/docs/backend/04-routing/07-cron-jobs.md +13 -13
- package/docs/backend/04-routing/08-middleware.md +214 -0
- package/docs/backend/04-routing/09-websocket-auth-middleware.md +292 -0
- package/docs/backend/04-routing/09-websocket-examples.md +381 -0
- package/docs/backend/04-routing/09-websocket-quick-reference.md +211 -0
- package/docs/backend/04-routing/09-websocket.md +298 -0
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +3 -3
- package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +41 -0
- package/docs/backend/05-controllers/03-controller-classes.md +19 -19
- package/docs/backend/05-forms/01-custom-forms.md +114 -114
- package/docs/backend/05-forms/02-automatic-database-insert.md +82 -82
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +26 -26
- package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +10 -10
- package/docs/backend/07-views/01-the-view-directory.md +1 -1
- package/docs/backend/07-views/02-rendering-a-view.md +22 -22
- package/docs/backend/07-views/03-template-syntax.md +52 -52
- package/docs/backend/07-views/03-variables.md +84 -84
- package/docs/backend/07-views/04-request-data.md +57 -57
- package/docs/backend/07-views/05-conditionals.md +78 -78
- package/docs/backend/07-views/06-loops.md +114 -114
- package/docs/backend/07-views/07-translations.md +66 -66
- package/docs/backend/07-views/08-backend-javascript.md +103 -103
- package/docs/backend/07-views/09-comments.md +71 -71
- package/docs/backend/08-database/01-database-connection.md +8 -8
- package/docs/backend/08-database/02-using-mysql.md +49 -49
- package/docs/backend/09-validation/01-the-validator-service.md +38 -38
- package/docs/backend/10-authentication/01-user-logins-with-authjs.md +15 -15
- package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +10 -10
- package/docs/backend/10-authentication/03-register.md +12 -12
- package/docs/backend/10-authentication/{04-candy-register-forms.md → 04-odac-register-forms.md} +141 -141
- package/docs/backend/10-authentication/05-session-management.md +10 -10
- package/docs/backend/10-authentication/{06-candy-login-forms.md → 06-odac-login-forms.md} +125 -125
- package/docs/backend/11-mail/01-the-mail-service.md +5 -5
- package/docs/backend/12-streaming/01-streaming-overview.md +96 -54
- package/docs/backend/13-utilities/{01-candy-var.md → 01-odac-var.md} +109 -109
- package/docs/frontend/01-overview/01-introduction.md +30 -30
- package/docs/frontend/02-ajax-navigation/01-quick-start.md +45 -45
- package/docs/frontend/02-ajax-navigation/02-configuration.md +14 -14
- package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +36 -36
- package/docs/frontend/03-forms/01-form-handling.md +32 -32
- package/docs/frontend/04-api-requests/01-get-post.md +33 -33
- package/docs/frontend/05-streaming/01-client-streaming.md +15 -15
- package/docs/frontend/06-websocket/00-overview.md +76 -0
- package/docs/frontend/06-websocket/01-websocket-client.md +139 -0
- package/docs/frontend/06-websocket/02-shared-websocket.md +149 -0
- package/docs/index.json +49 -11
- package/eslint.config.mjs +6 -6
- package/{framework/index.js → index.js} +1 -1
- package/package.json +14 -39
- package/{framework/src → src}/Auth.js +59 -59
- package/{framework/src → src}/Config.js +3 -3
- package/{framework/src → src}/Lang.js +7 -7
- package/{framework/src → src}/Mail.js +5 -5
- package/{framework/src → src}/Mysql.js +42 -42
- package/src/Odac.js +112 -0
- package/{framework/src → src}/Request.js +38 -36
- package/{framework/src → src}/Route/Internal.js +116 -116
- package/src/Route/Middleware.js +75 -0
- package/src/Route.js +621 -0
- package/src/Server.js +22 -0
- package/{framework/src → src}/Stream.js +11 -3
- package/{framework/src → src}/Validator.js +21 -21
- package/{framework/src → src}/Var.js +5 -5
- package/{framework/src → src}/View/EarlyHints.js +1 -1
- package/{framework/src → src}/View/Form.js +69 -69
- package/{framework/src → src}/View.js +78 -81
- package/src/WebSocket.js +403 -0
- package/template/config.json +5 -0
- package/{web → template}/controller/page/about.js +6 -6
- package/{web → template}/controller/page/index.js +9 -9
- package/{web → template}/package.json +4 -5
- package/{web → template}/public/assets/css/style.css +4 -4
- package/{web → template}/public/assets/js/app.js +6 -6
- package/{web → template}/route/www.js +6 -6
- package/{web → template}/skeleton/main.html +1 -1
- package/{web → template}/view/content/about.html +5 -5
- package/{web → template}/view/content/home.html +12 -12
- package/template/view/footer/main.html +11 -0
- package/{web → template}/view/head/main.html +1 -1
- package/{web → template}/view/header/main.html +2 -2
- package/test/core/Candy.test.js +58 -58
- package/test/core/Commands.test.js +7 -7
- package/test/core/Config.test.js +82 -85
- package/test/core/Lang.test.js +2 -2
- package/test/core/Process.test.js +6 -6
- package/test/framework/Route.test.js +56 -37
- package/test/framework/View/EarlyHints.test.js +2 -2
- package/test/framework/WebSocket.test.js +100 -0
- package/test/framework/middleware.test.js +85 -0
- package/test/server/Api.test.js +31 -31
- package/test/server/DNS.test.js +11 -11
- package/test/server/Hub.test.js +497 -0
- package/test/server/Mail.account.test_.js +3 -3
- package/test/server/Mail.init.test_.js +10 -10
- package/test/server/Mail.test_.js +20 -20
- package/test/server/SSL.test_.js +54 -54
- package/test/server/Server.test.js +39 -39
- package/test/server/Service.test_.js +7 -7
- package/test/server/Subdomain.test.js +7 -7
- package/test/server/Web/Firewall.test.js +87 -87
- package/test/server/Web/Proxy.test.js +397 -0
- package/test/server/{Web.test_.js → Web.test.js} +137 -205
- package/test/server/__mocks__/fs.js +2 -2
- package/test/server/__mocks__/{globalCandy.js → globalOdac.js} +5 -5
- package/test/server/__mocks__/index.js +6 -6
- package/test/server/__mocks__/testFactories.js +1 -1
- package/test/server/__mocks__/testHelpers.js +7 -7
- package/.husky/pre-commit +0 -2
- package/.kiro/steering/code-style.md +0 -56
- package/.kiro/steering/product.md +0 -20
- package/.kiro/steering/structure.md +0 -77
- package/.kiro/steering/tech.md +0 -87
- package/AGENTS.md +0 -84
- package/bin/candy +0 -10
- package/bin/candypack +0 -10
- package/cli/index.js +0 -3
- package/cli/src/Cli.js +0 -348
- package/cli/src/Connector.js +0 -93
- package/cli/src/Monitor.js +0 -416
- package/core/Candy.js +0 -87
- package/core/Commands.js +0 -239
- package/core/Config.js +0 -1094
- package/core/Lang.js +0 -52
- package/core/Log.js +0 -43
- package/core/Process.js +0 -26
- package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +0 -20
- package/docs/server/01-installation/01-quick-install.md +0 -19
- package/docs/server/01-installation/02-manual-installation-via-npm.md +0 -9
- package/docs/server/02-get-started/01-core-concepts.md +0 -7
- package/docs/server/02-get-started/02-basic-commands.md +0 -57
- package/docs/server/02-get-started/03-cli-reference.md +0 -276
- package/docs/server/02-get-started/04-cli-quick-reference.md +0 -102
- package/docs/server/03-service/01-start-a-new-service.md +0 -57
- package/docs/server/03-service/02-delete-a-service.md +0 -48
- package/docs/server/04-web/01-create-a-website.md +0 -36
- package/docs/server/04-web/02-list-websites.md +0 -9
- package/docs/server/04-web/03-delete-a-website.md +0 -29
- package/docs/server/05-subdomain/01-create-a-subdomain.md +0 -32
- package/docs/server/05-subdomain/02-list-subdomains.md +0 -33
- package/docs/server/05-subdomain/03-delete-a-subdomain.md +0 -41
- package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +0 -34
- package/docs/server/07-mail/01-create-a-mail-account.md +0 -23
- package/docs/server/07-mail/02-delete-a-mail-account.md +0 -20
- package/docs/server/07-mail/03-list-mail-accounts.md +0 -20
- package/docs/server/07-mail/04-change-account-password.md +0 -23
- package/framework/src/Candy.js +0 -81
- package/framework/src/Route.js +0 -455
- package/framework/src/Server.js +0 -15
- package/locale/de-DE.json +0 -80
- package/locale/en-US.json +0 -79
- package/locale/es-ES.json +0 -80
- package/locale/fr-FR.json +0 -80
- package/locale/pt-BR.json +0 -80
- package/locale/ru-RU.json +0 -80
- package/locale/tr-TR.json +0 -85
- package/locale/zh-CN.json +0 -80
- package/server/index.js +0 -5
- package/server/src/Api.js +0 -88
- package/server/src/DNS.js +0 -940
- package/server/src/Hub.js +0 -535
- package/server/src/Mail.js +0 -571
- package/server/src/SSL.js +0 -180
- package/server/src/Server.js +0 -27
- package/server/src/Service.js +0 -248
- package/server/src/Subdomain.js +0 -64
- package/server/src/Web/Firewall.js +0 -170
- package/server/src/Web/Proxy.js +0 -134
- package/server/src/Web.js +0 -451
- package/server/src/mail/imap.js +0 -1091
- package/server/src/mail/server.js +0 -32
- package/server/src/mail/smtp.js +0 -786
- package/test/server/Client.test.js +0 -338
- package/test/server/__mocks__/http-proxy.js +0 -105
- package/watchdog/index.js +0 -3
- package/watchdog/src/Watchdog.js +0 -156
- package/web/config.json +0 -5
- package/web/view/footer/main.html +0 -11
- /package/{framework/src → src}/Env.js +0 -0
- /package/{framework/src → src}/Route/Cron.js +0 -0
- /package/{framework/src → src}/Token.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Odac Login Forms
|
|
2
2
|
|
|
3
|
-
The `<
|
|
3
|
+
The `<odac:login>` component provides a zero-configuration way to create secure login forms. Simply write HTML, and Odac handles validation, security, authentication, and session management automatically.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -22,17 +22,17 @@ That's all you need! The `auth` configuration is optional.
|
|
|
22
22
|
### 2. Create Your Form (view/content/login.html)
|
|
23
23
|
|
|
24
24
|
```html
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
<
|
|
28
|
-
</
|
|
25
|
+
<odac:login redirect="/dashboard">
|
|
26
|
+
<odac:field name="email" type="email" placeholder="Email">
|
|
27
|
+
<odac:validate rule="required|email" message="Please enter a valid email"/>
|
|
28
|
+
</odac:field>
|
|
29
29
|
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
</
|
|
30
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
31
|
+
<odac:validate rule="required" message="Password is required"/>
|
|
32
|
+
</odac:field>
|
|
33
33
|
|
|
34
|
-
<
|
|
35
|
-
</
|
|
34
|
+
<odac:submit>Login</odac:submit>
|
|
35
|
+
</odac:login>
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
That's it! No JavaScript, no controller code needed. The form automatically:
|
|
@@ -63,15 +63,15 @@ If you want to customize table names or primary key:
|
|
|
63
63
|
|
|
64
64
|
## Form Attributes
|
|
65
65
|
|
|
66
|
-
### `<
|
|
66
|
+
### `<odac:login>`
|
|
67
67
|
|
|
68
68
|
Main form container with configuration options:
|
|
69
69
|
|
|
70
70
|
```html
|
|
71
|
-
<
|
|
71
|
+
<odac:login
|
|
72
72
|
redirect="/dashboard"> <!-- Redirect URL after successful login -->
|
|
73
73
|
<!-- fields here -->
|
|
74
|
-
</
|
|
74
|
+
</odac:login>
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
**Attributes:**
|
|
@@ -79,12 +79,12 @@ Main form container with configuration options:
|
|
|
79
79
|
|
|
80
80
|
## Field Types
|
|
81
81
|
|
|
82
|
-
### `<
|
|
82
|
+
### `<odac:field>`
|
|
83
83
|
|
|
84
84
|
Defines an input field with validation rules:
|
|
85
85
|
|
|
86
86
|
```html
|
|
87
|
-
<
|
|
87
|
+
<odac:field
|
|
88
88
|
name="email" <!-- Field name (required) -->
|
|
89
89
|
type="email" <!-- Input type (default: text) -->
|
|
90
90
|
placeholder="Email" <!-- Placeholder text -->
|
|
@@ -92,8 +92,8 @@ Defines an input field with validation rules:
|
|
|
92
92
|
class="form-input" <!-- CSS class (optional) -->
|
|
93
93
|
id="email-field"> <!-- HTML ID (optional) -->
|
|
94
94
|
|
|
95
|
-
<
|
|
96
|
-
</
|
|
95
|
+
<odac:validate rule="required|email" message="Valid email required"/>
|
|
96
|
+
</odac:field>
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
**Attributes:**
|
|
@@ -113,12 +113,12 @@ Defines an input field with validation rules:
|
|
|
113
113
|
|
|
114
114
|
## Validation Rules
|
|
115
115
|
|
|
116
|
-
### `<
|
|
116
|
+
### `<odac:validate>`
|
|
117
117
|
|
|
118
118
|
Defines validation rules for a field:
|
|
119
119
|
|
|
120
120
|
```html
|
|
121
|
-
<
|
|
121
|
+
<odac:validate
|
|
122
122
|
rule="required|minlen:4"
|
|
123
123
|
message="This field is required and must be at least 4 characters"/>
|
|
124
124
|
```
|
|
@@ -150,23 +150,23 @@ Defines validation rules for a field:
|
|
|
150
150
|
|
|
151
151
|
### Multiple Validation Rules
|
|
152
152
|
|
|
153
|
-
You can add multiple `<
|
|
153
|
+
You can add multiple `<odac:validate>` tags for different error messages:
|
|
154
154
|
|
|
155
155
|
```html
|
|
156
|
-
<
|
|
157
|
-
<
|
|
158
|
-
<
|
|
159
|
-
</
|
|
156
|
+
<odac:field name="email" type="email">
|
|
157
|
+
<odac:validate rule="required" message="Email is required"/>
|
|
158
|
+
<odac:validate rule="email" message="Please enter a valid email address"/>
|
|
159
|
+
</odac:field>
|
|
160
160
|
```
|
|
161
161
|
|
|
162
162
|
Or combine rules in a single tag:
|
|
163
163
|
|
|
164
164
|
```html
|
|
165
|
-
<
|
|
166
|
-
<
|
|
165
|
+
<odac:field name="email" type="email">
|
|
166
|
+
<odac:validate
|
|
167
167
|
rule="required|email"
|
|
168
168
|
message="Please enter a valid email address"/>
|
|
169
|
-
</
|
|
169
|
+
</odac:field>
|
|
170
170
|
```
|
|
171
171
|
|
|
172
172
|
## Message Placeholders
|
|
@@ -174,11 +174,11 @@ Or combine rules in a single tag:
|
|
|
174
174
|
Use placeholders in error messages for dynamic values:
|
|
175
175
|
|
|
176
176
|
```html
|
|
177
|
-
<
|
|
178
|
-
<
|
|
177
|
+
<odac:field name="username" type="text">
|
|
178
|
+
<odac:validate
|
|
179
179
|
rule="minlen:4"
|
|
180
180
|
message="Username '{value}' is too short. Minimum {min} characters required"/>
|
|
181
|
-
</
|
|
181
|
+
</odac:field>
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
**Available Placeholders:**
|
|
@@ -191,23 +191,23 @@ Use placeholders in error messages for dynamic values:
|
|
|
191
191
|
|
|
192
192
|
## Submit Button
|
|
193
193
|
|
|
194
|
-
### `<
|
|
194
|
+
### `<odac:submit>`
|
|
195
195
|
|
|
196
196
|
Defines the submit button:
|
|
197
197
|
|
|
198
198
|
```html
|
|
199
|
-
<
|
|
199
|
+
<odac:submit
|
|
200
200
|
text="Login" <!-- Button text -->
|
|
201
201
|
loading="Logging in..." <!-- Loading state text -->
|
|
202
202
|
class="btn btn-primary" <!-- CSS class -->
|
|
203
203
|
id="login-button"> <!-- HTML ID -->
|
|
204
|
-
</
|
|
204
|
+
</odac:submit>
|
|
205
205
|
```
|
|
206
206
|
|
|
207
207
|
Or use content as button text:
|
|
208
208
|
|
|
209
209
|
```html
|
|
210
|
-
<
|
|
210
|
+
<odac:submit>Login</odac:submit>
|
|
211
211
|
```
|
|
212
212
|
|
|
213
213
|
## Complete Examples
|
|
@@ -215,70 +215,70 @@ Or use content as button text:
|
|
|
215
215
|
### Basic Login Form
|
|
216
216
|
|
|
217
217
|
```html
|
|
218
|
-
<
|
|
218
|
+
<odac:login redirect="/dashboard">
|
|
219
219
|
|
|
220
220
|
<!-- Email Field -->
|
|
221
|
-
<
|
|
222
|
-
<
|
|
223
|
-
<
|
|
224
|
-
</
|
|
221
|
+
<odac:field name="email" type="email" placeholder="Email Address">
|
|
222
|
+
<odac:validate rule="required" message="Email is required"/>
|
|
223
|
+
<odac:validate rule="email" message="Please enter a valid email address"/>
|
|
224
|
+
</odac:field>
|
|
225
225
|
|
|
226
226
|
<!-- Password Field -->
|
|
227
|
-
<
|
|
228
|
-
<
|
|
229
|
-
</
|
|
227
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
228
|
+
<odac:validate rule="required" message="Password is required"/>
|
|
229
|
+
</odac:field>
|
|
230
230
|
|
|
231
231
|
<!-- Submit Button -->
|
|
232
|
-
<
|
|
232
|
+
<odac:submit text="Login" loading="Logging in..."/>
|
|
233
233
|
|
|
234
|
-
</
|
|
234
|
+
</odac:login>
|
|
235
235
|
```
|
|
236
236
|
|
|
237
237
|
### Login with Username
|
|
238
238
|
|
|
239
239
|
```html
|
|
240
|
-
<
|
|
240
|
+
<odac:login redirect="/dashboard">
|
|
241
241
|
|
|
242
242
|
<!-- Username Field -->
|
|
243
|
-
<
|
|
244
|
-
<
|
|
245
|
-
<
|
|
246
|
-
</
|
|
243
|
+
<odac:field name="username" type="text" placeholder="Username">
|
|
244
|
+
<odac:validate rule="required" message="Username is required"/>
|
|
245
|
+
<odac:validate rule="minlen:4" message="Username must be at least {min} characters"/>
|
|
246
|
+
</odac:field>
|
|
247
247
|
|
|
248
248
|
<!-- Password Field -->
|
|
249
|
-
<
|
|
250
|
-
<
|
|
251
|
-
</
|
|
249
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
250
|
+
<odac:validate rule="required" message="Password is required"/>
|
|
251
|
+
</odac:field>
|
|
252
252
|
|
|
253
253
|
<!-- Submit Button -->
|
|
254
|
-
<
|
|
254
|
+
<odac:submit>Login</odac:submit>
|
|
255
255
|
|
|
256
|
-
</
|
|
256
|
+
</odac:login>
|
|
257
257
|
```
|
|
258
258
|
|
|
259
259
|
### Login with Remember Me
|
|
260
260
|
|
|
261
261
|
```html
|
|
262
|
-
<
|
|
262
|
+
<odac:login redirect="/dashboard">
|
|
263
263
|
|
|
264
264
|
<!-- Email Field -->
|
|
265
|
-
<
|
|
266
|
-
<
|
|
267
|
-
</
|
|
265
|
+
<odac:field name="email" type="email" placeholder="Email">
|
|
266
|
+
<odac:validate rule="required|email" message="Please enter a valid email"/>
|
|
267
|
+
</odac:field>
|
|
268
268
|
|
|
269
269
|
<!-- Password Field -->
|
|
270
|
-
<
|
|
271
|
-
<
|
|
272
|
-
</
|
|
270
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
271
|
+
<odac:validate rule="required" message="Password is required"/>
|
|
272
|
+
</odac:field>
|
|
273
273
|
|
|
274
274
|
<!-- Remember Me Checkbox -->
|
|
275
|
-
<
|
|
276
|
-
</
|
|
275
|
+
<odac:field name="remember" type="checkbox" label="Remember me">
|
|
276
|
+
</odac:field>
|
|
277
277
|
|
|
278
278
|
<!-- Submit Button -->
|
|
279
|
-
<
|
|
279
|
+
<odac:submit>Login</odac:submit>
|
|
280
280
|
|
|
281
|
-
</
|
|
281
|
+
</odac:login>
|
|
282
282
|
```
|
|
283
283
|
|
|
284
284
|
### Styled Login Form
|
|
@@ -287,40 +287,40 @@ Or use content as button text:
|
|
|
287
287
|
<div class="login-container">
|
|
288
288
|
<h2>Welcome Back</h2>
|
|
289
289
|
|
|
290
|
-
<
|
|
290
|
+
<odac:login redirect="/dashboard">
|
|
291
291
|
|
|
292
292
|
<div class="form-group">
|
|
293
|
-
<
|
|
293
|
+
<odac:field
|
|
294
294
|
name="email"
|
|
295
295
|
type="email"
|
|
296
296
|
placeholder="Email Address"
|
|
297
297
|
class="form-control">
|
|
298
|
-
<
|
|
299
|
-
</
|
|
300
|
-
<span class="
|
|
298
|
+
<odac:validate rule="required|email" message="Please enter a valid email"/>
|
|
299
|
+
</odac:field>
|
|
300
|
+
<span class="odac-form-error" odac-form-error="email"></span>
|
|
301
301
|
</div>
|
|
302
302
|
|
|
303
303
|
<div class="form-group">
|
|
304
|
-
<
|
|
304
|
+
<odac:field
|
|
305
305
|
name="password"
|
|
306
306
|
type="password"
|
|
307
307
|
placeholder="Password"
|
|
308
308
|
class="form-control">
|
|
309
|
-
<
|
|
310
|
-
</
|
|
311
|
-
<span class="
|
|
309
|
+
<odac:validate rule="required" message="Password is required"/>
|
|
310
|
+
</odac:field>
|
|
311
|
+
<span class="odac-form-error" odac-form-error="password"></span>
|
|
312
312
|
</div>
|
|
313
313
|
|
|
314
314
|
<div class="form-group">
|
|
315
|
-
<
|
|
316
|
-
</
|
|
315
|
+
<odac:field name="remember" type="checkbox" label="Remember me" class="form-check-input">
|
|
316
|
+
</odac:field>
|
|
317
317
|
</div>
|
|
318
318
|
|
|
319
|
-
<
|
|
319
|
+
<odac:submit class="btn btn-primary btn-block" text="Login" loading="Logging in..."/>
|
|
320
320
|
|
|
321
|
-
<span class="
|
|
321
|
+
<span class="odac-form-error" odac-form-error="_odac_form"></span>
|
|
322
322
|
|
|
323
|
-
</
|
|
323
|
+
</odac:login>
|
|
324
324
|
|
|
325
325
|
<p class="text-center mt-3">
|
|
326
326
|
<a href="/forgot-password">Forgot password?</a>
|
|
@@ -332,7 +332,7 @@ Or use content as button text:
|
|
|
332
332
|
|
|
333
333
|
### Automatic Security
|
|
334
334
|
|
|
335
|
-
|
|
335
|
+
Odac automatically handles:
|
|
336
336
|
|
|
337
337
|
1. **CSRF Protection** - Form tokens prevent cross-site attacks
|
|
338
338
|
2. **Password Verification** - Passwords are verified against bcrypt hashes
|
|
@@ -352,13 +352,13 @@ Each form gets a unique token when rendered:
|
|
|
352
352
|
|
|
353
353
|
## HTML5 Validation
|
|
354
354
|
|
|
355
|
-
|
|
355
|
+
Odac automatically adds HTML5 validation attributes for better UX:
|
|
356
356
|
|
|
357
357
|
```html
|
|
358
358
|
<!-- This field -->
|
|
359
|
-
<
|
|
360
|
-
<
|
|
361
|
-
</
|
|
359
|
+
<odac:field name="email" type="email">
|
|
360
|
+
<odac:validate rule="required|email"/>
|
|
361
|
+
</odac:field>
|
|
362
362
|
|
|
363
363
|
<!-- Generates this HTML -->
|
|
364
364
|
<input
|
|
@@ -380,22 +380,22 @@ This provides instant feedback to users before form submission.
|
|
|
380
380
|
|
|
381
381
|
### Display Errors
|
|
382
382
|
|
|
383
|
-
Error messages are automatically displayed in `<span>` elements with `
|
|
383
|
+
Error messages are automatically displayed in `<span>` elements with `odac-form-error` attribute:
|
|
384
384
|
|
|
385
385
|
```html
|
|
386
386
|
<!-- Errors appear here automatically -->
|
|
387
|
-
<span class="
|
|
388
|
-
<span class="
|
|
389
|
-
<span class="
|
|
387
|
+
<span class="odac-form-error" odac-form-error="email" style="display:none;"></span>
|
|
388
|
+
<span class="odac-form-error" odac-form-error="password" style="display:none;"></span>
|
|
389
|
+
<span class="odac-form-error" odac-form-error="_odac_form" style="display:none;"></span>
|
|
390
390
|
```
|
|
391
391
|
|
|
392
392
|
### Success Messages
|
|
393
393
|
|
|
394
|
-
Success messages appear in elements with `
|
|
394
|
+
Success messages appear in elements with `odac-form-success` class:
|
|
395
395
|
|
|
396
396
|
```html
|
|
397
397
|
<!-- Success message appears here -->
|
|
398
|
-
<span class="
|
|
398
|
+
<span class="odac-form-success" style="display:none;"></span>
|
|
399
399
|
```
|
|
400
400
|
|
|
401
401
|
### Custom Styling
|
|
@@ -403,14 +403,14 @@ Success messages appear in elements with `candy-form-success` class:
|
|
|
403
403
|
Style error and success messages with CSS:
|
|
404
404
|
|
|
405
405
|
```css
|
|
406
|
-
.
|
|
406
|
+
.odac-form-error {
|
|
407
407
|
color: red;
|
|
408
408
|
font-size: 0.875rem;
|
|
409
409
|
margin-top: 0.25rem;
|
|
410
410
|
display: block;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
.
|
|
413
|
+
.odac-form-success {
|
|
414
414
|
color: green;
|
|
415
415
|
font-size: 1rem;
|
|
416
416
|
padding: 1rem;
|
|
@@ -419,7 +419,7 @@ Style error and success messages with CSS:
|
|
|
419
419
|
border-radius: 0.25rem;
|
|
420
420
|
}
|
|
421
421
|
|
|
422
|
-
input.
|
|
422
|
+
input._odac_error {
|
|
423
423
|
border-color: red;
|
|
424
424
|
}
|
|
425
425
|
```
|
|
@@ -506,49 +506,49 @@ The login form supports multiple authentication methods:
|
|
|
506
506
|
### Email + Password
|
|
507
507
|
|
|
508
508
|
```html
|
|
509
|
-
<
|
|
510
|
-
<
|
|
511
|
-
<
|
|
512
|
-
</
|
|
513
|
-
<
|
|
514
|
-
<
|
|
515
|
-
</
|
|
516
|
-
<
|
|
517
|
-
</
|
|
509
|
+
<odac:login redirect="/dashboard">
|
|
510
|
+
<odac:field name="email" type="email" placeholder="Email">
|
|
511
|
+
<odac:validate rule="required|email"/>
|
|
512
|
+
</odac:field>
|
|
513
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
514
|
+
<odac:validate rule="required"/>
|
|
515
|
+
</odac:field>
|
|
516
|
+
<odac:submit>Login</odac:submit>
|
|
517
|
+
</odac:login>
|
|
518
518
|
```
|
|
519
519
|
|
|
520
520
|
### Username + Password
|
|
521
521
|
|
|
522
522
|
```html
|
|
523
|
-
<
|
|
524
|
-
<
|
|
525
|
-
<
|
|
526
|
-
</
|
|
527
|
-
<
|
|
528
|
-
<
|
|
529
|
-
</
|
|
530
|
-
<
|
|
531
|
-
</
|
|
523
|
+
<odac:login redirect="/dashboard">
|
|
524
|
+
<odac:field name="username" type="text" placeholder="Username">
|
|
525
|
+
<odac:validate rule="required"/>
|
|
526
|
+
</odac:field>
|
|
527
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
528
|
+
<odac:validate rule="required"/>
|
|
529
|
+
</odac:field>
|
|
530
|
+
<odac:submit>Login</odac:submit>
|
|
531
|
+
</odac:login>
|
|
532
532
|
```
|
|
533
533
|
|
|
534
534
|
### Email or Username + Password
|
|
535
535
|
|
|
536
536
|
```html
|
|
537
|
-
<
|
|
538
|
-
<
|
|
539
|
-
<
|
|
540
|
-
</
|
|
541
|
-
<
|
|
542
|
-
<
|
|
543
|
-
</
|
|
544
|
-
<
|
|
545
|
-
</
|
|
537
|
+
<odac:login redirect="/dashboard">
|
|
538
|
+
<odac:field name="identifier" type="text" placeholder="Email or Username">
|
|
539
|
+
<odac:validate rule="required"/>
|
|
540
|
+
</odac:field>
|
|
541
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
542
|
+
<odac:validate rule="required"/>
|
|
543
|
+
</odac:field>
|
|
544
|
+
<odac:submit>Login</odac:submit>
|
|
545
|
+
</odac:login>
|
|
546
546
|
```
|
|
547
547
|
|
|
548
548
|
## Best Practices
|
|
549
549
|
|
|
550
550
|
1. **Always use HTTPS** - Login forms should only be served over HTTPS
|
|
551
|
-
2. **Validate on both client and server** -
|
|
551
|
+
2. **Validate on both client and server** - Odac does this automatically
|
|
552
552
|
3. **Provide clear error messages** - Don't reveal whether email/username exists
|
|
553
553
|
4. **Add "Forgot Password" link** - Help users recover their accounts
|
|
554
554
|
5. **Consider rate limiting** - Prevent brute force attacks (implement in controller)
|
|
@@ -567,7 +567,7 @@ The login form supports multiple authentication methods:
|
|
|
567
567
|
### Validation Not Working
|
|
568
568
|
|
|
569
569
|
- Ensure validation rules are spelled correctly
|
|
570
|
-
- Check that field names match between `<
|
|
570
|
+
- Check that field names match between `<odac:field>` and validation
|
|
571
571
|
- Verify HTML5 validation isn't blocking submission
|
|
572
572
|
|
|
573
573
|
### Login Failing
|
|
@@ -585,12 +585,12 @@ The login form supports multiple authentication methods:
|
|
|
585
585
|
|
|
586
586
|
### Redirect Not Working
|
|
587
587
|
|
|
588
|
-
- Ensure `redirect` attribute is set on `<
|
|
588
|
+
- Ensure `redirect` attribute is set on `<odac:login>`
|
|
589
589
|
- Check that the redirect URL is valid
|
|
590
590
|
- Verify user has permission to access the redirect page
|
|
591
591
|
|
|
592
592
|
## Related Documentation
|
|
593
593
|
|
|
594
|
-
- [
|
|
594
|
+
- [Odac Register Forms](04-odac-register-forms.md) - Create registration forms
|
|
595
595
|
- [Session Management](05-session-management.md) - Understanding sessions
|
|
596
596
|
- [Authentication Overview](00-authentication-overview.md) - Auth system basics
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
## ✉️ The `Mail` Service
|
|
2
2
|
|
|
3
|
-
The `
|
|
3
|
+
The `Odac.Mail` service is your friendly neighborhood postal worker. It provides a super simple way to send emails using the mail server settings you've already configured in the Odac core.
|
|
4
4
|
|
|
5
5
|
#### How to Send an Email
|
|
6
6
|
|
|
7
|
-
`
|
|
7
|
+
`Odac.Mail.send(to, subject, htmlBody)`
|
|
8
8
|
|
|
9
9
|
* `to`: The email address of the person you're sending it to.
|
|
10
10
|
* `subject`: The subject line for your email.
|
|
@@ -17,8 +17,8 @@ Just like the database service, `send` is an `async` method, so using it with `a
|
|
|
17
17
|
Let's imagine you have a controller that handles a contact form on your website.
|
|
18
18
|
|
|
19
19
|
```javascript
|
|
20
|
-
module.exports = async function (
|
|
21
|
-
const { recipient, subject, message } =
|
|
20
|
+
module.exports = async function (Odac) {
|
|
21
|
+
const { recipient, subject, message } = Odac.Request.post;
|
|
22
22
|
|
|
23
23
|
// It's always a good idea to check your data first!
|
|
24
24
|
if (!recipient || !subject || !message) {
|
|
@@ -27,7 +27,7 @@ module.exports = async function (Candy) {
|
|
|
27
27
|
|
|
28
28
|
try {
|
|
29
29
|
// Let's try to send the email
|
|
30
|
-
await
|
|
30
|
+
await Odac.Mail.send(recipient, subject, `<p>${message}</p>`);
|
|
31
31
|
|
|
32
32
|
// If we get here, it worked!
|
|
33
33
|
return { success: true, message: 'Email sent successfully!' };
|