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
package/docs/backend/10-authentication/{04-candy-register-forms.md → 04-odac-register-forms.md}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Odac Register Forms
|
|
2
2
|
|
|
3
|
-
The `<
|
|
3
|
+
The `<odac:register>` component provides a zero-configuration way to create secure registration forms. Simply write HTML, and Odac handles validation, security, database operations, and auto-login automatically.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -22,21 +22,21 @@ That's all you need! The `auth` configuration is optional.
|
|
|
22
22
|
### 2. Create Your Form (view/content/register.html)
|
|
23
23
|
|
|
24
24
|
```html
|
|
25
|
-
<
|
|
26
|
-
<
|
|
27
|
-
<
|
|
28
|
-
</
|
|
25
|
+
<odac:register redirect="/dashboard">
|
|
26
|
+
<odac:field name="email" type="email" placeholder="Email" unique>
|
|
27
|
+
<odac:validate rule="required|email" message="Please enter a valid email"/>
|
|
28
|
+
</odac:field>
|
|
29
29
|
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
</
|
|
30
|
+
<odac:field name="username" type="text" placeholder="Username" unique>
|
|
31
|
+
<odac:validate rule="required|minlen:4" message="Username must be at least 4 characters"/>
|
|
32
|
+
</odac:field>
|
|
33
33
|
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
</
|
|
34
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
35
|
+
<odac:validate rule="required|minlen:8" message="Password must be at least 8 characters"/>
|
|
36
|
+
</odac:field>
|
|
37
37
|
|
|
38
|
-
<
|
|
39
|
-
</
|
|
38
|
+
<odac:submit>Create Account</odac:submit>
|
|
39
|
+
</odac:register>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
That's it! No JavaScript, no controller code, no SQL needed. The form automatically:
|
|
@@ -76,16 +76,16 @@ If you want to customize table names or primary key:
|
|
|
76
76
|
|
|
77
77
|
## Form Attributes
|
|
78
78
|
|
|
79
|
-
### `<
|
|
79
|
+
### `<odac:register>`
|
|
80
80
|
|
|
81
81
|
Main form container with configuration options:
|
|
82
82
|
|
|
83
83
|
```html
|
|
84
|
-
<
|
|
84
|
+
<odac:register
|
|
85
85
|
redirect="/dashboard" <!-- Redirect URL after successful registration -->
|
|
86
86
|
autologin="true"> <!-- Auto-login after registration (default: true) -->
|
|
87
87
|
<!-- fields here -->
|
|
88
|
-
</
|
|
88
|
+
</odac:register>
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
**Attributes:**
|
|
@@ -94,20 +94,20 @@ Main form container with configuration options:
|
|
|
94
94
|
|
|
95
95
|
## Field Types
|
|
96
96
|
|
|
97
|
-
### `<
|
|
97
|
+
### `<odac:field>`
|
|
98
98
|
|
|
99
99
|
Defines an input field with validation rules:
|
|
100
100
|
|
|
101
101
|
```html
|
|
102
|
-
<
|
|
102
|
+
<odac:field
|
|
103
103
|
name="email" <!-- Field name (required) -->
|
|
104
104
|
type="email" <!-- Input type (default: text) -->
|
|
105
105
|
placeholder="Email" <!-- Placeholder text -->
|
|
106
106
|
label="Email Address" <!-- Label text (optional) -->
|
|
107
107
|
unique> <!-- Check uniqueness in database -->
|
|
108
108
|
|
|
109
|
-
<
|
|
110
|
-
</
|
|
109
|
+
<odac:validate rule="required|email" message="Valid email required"/>
|
|
110
|
+
</odac:field>
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
**Attributes:**
|
|
@@ -132,19 +132,19 @@ Use the `skip` attribute for fields that should be validated but not saved to th
|
|
|
132
132
|
|
|
133
133
|
```html
|
|
134
134
|
<!-- Password confirmation - validate but don't save -->
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
</
|
|
135
|
+
<odac:field name="confirm_password" type="password" placeholder="Confirm Password" skip>
|
|
136
|
+
<odac:validate rule="required|same:password" message="Passwords must match"/>
|
|
137
|
+
</odac:field>
|
|
138
138
|
|
|
139
139
|
<!-- Terms acceptance - validate but don't save -->
|
|
140
|
-
<
|
|
141
|
-
<
|
|
142
|
-
</
|
|
140
|
+
<odac:field name="terms" type="checkbox" label="I accept the terms" skip>
|
|
141
|
+
<odac:validate rule="accepted" message="You must accept the terms"/>
|
|
142
|
+
</odac:field>
|
|
143
143
|
|
|
144
144
|
<!-- Captcha verification - validate but don't save -->
|
|
145
|
-
<
|
|
146
|
-
<
|
|
147
|
-
</
|
|
145
|
+
<odac:field name="captcha" type="text" placeholder="Enter captcha" skip>
|
|
146
|
+
<odac:validate rule="required" message="Please complete the captcha"/>
|
|
147
|
+
</odac:field>
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
**Common Use Cases:**
|
|
@@ -156,12 +156,12 @@ Use the `skip` attribute for fields that should be validated but not saved to th
|
|
|
156
156
|
|
|
157
157
|
## Validation Rules
|
|
158
158
|
|
|
159
|
-
### `<
|
|
159
|
+
### `<odac:validate>`
|
|
160
160
|
|
|
161
161
|
Defines validation rules for a field:
|
|
162
162
|
|
|
163
163
|
```html
|
|
164
|
-
<
|
|
164
|
+
<odac:validate
|
|
165
165
|
rule="required|minlen:4|alphanumeric"
|
|
166
166
|
message="Username must be 4+ alphanumeric characters"/>
|
|
167
167
|
```
|
|
@@ -210,27 +210,27 @@ Defines validation rules for a field:
|
|
|
210
210
|
|
|
211
211
|
### Multiple Validation Rules
|
|
212
212
|
|
|
213
|
-
You can add multiple `<
|
|
213
|
+
You can add multiple `<odac:validate>` tags for different error messages:
|
|
214
214
|
|
|
215
215
|
```html
|
|
216
|
-
<
|
|
217
|
-
<
|
|
218
|
-
<
|
|
219
|
-
<
|
|
220
|
-
<
|
|
221
|
-
<
|
|
222
|
-
</
|
|
216
|
+
<odac:field name="username" type="text" unique>
|
|
217
|
+
<odac:validate rule="required" message="Username is required"/>
|
|
218
|
+
<odac:validate rule="minlen:4" message="Username must be at least {min} characters"/>
|
|
219
|
+
<odac:validate rule="maxlen:20" message="Username cannot exceed {max} characters"/>
|
|
220
|
+
<odac:validate rule="alphanumeric" message="Username can only contain letters and numbers"/>
|
|
221
|
+
<odac:validate rule="unique" message="Username '{value}' is already taken"/>
|
|
222
|
+
</odac:field>
|
|
223
223
|
```
|
|
224
224
|
|
|
225
225
|
Or combine rules in a single tag:
|
|
226
226
|
|
|
227
227
|
```html
|
|
228
|
-
<
|
|
229
|
-
<
|
|
228
|
+
<odac:field name="username" type="text" unique>
|
|
229
|
+
<odac:validate
|
|
230
230
|
rule="required|minlen:4|maxlen:20|alphanumeric"
|
|
231
231
|
message="Username must be 4-20 alphanumeric characters"/>
|
|
232
|
-
<
|
|
233
|
-
</
|
|
232
|
+
<odac:validate rule="unique" message="Username '{value}' is already taken"/>
|
|
233
|
+
</odac:field>
|
|
234
234
|
```
|
|
235
235
|
|
|
236
236
|
## Message Placeholders
|
|
@@ -238,17 +238,17 @@ Or combine rules in a single tag:
|
|
|
238
238
|
Use placeholders in error messages for dynamic values:
|
|
239
239
|
|
|
240
240
|
```html
|
|
241
|
-
<
|
|
242
|
-
<
|
|
241
|
+
<odac:field name="username" type="text">
|
|
242
|
+
<odac:validate
|
|
243
243
|
rule="minlen:4"
|
|
244
244
|
message="Username '{value}' is too short. Minimum {min} characters required"/>
|
|
245
|
-
</
|
|
245
|
+
</odac:field>
|
|
246
246
|
|
|
247
|
-
<
|
|
248
|
-
<
|
|
247
|
+
<odac:field name="age" type="number">
|
|
248
|
+
<odac:validate
|
|
249
249
|
rule="min:18|max:120"
|
|
250
250
|
message="Age must be between {min} and {max} years"/>
|
|
251
|
-
</
|
|
251
|
+
</odac:field>
|
|
252
252
|
```
|
|
253
253
|
|
|
254
254
|
**Available Placeholders:**
|
|
@@ -262,25 +262,25 @@ Use placeholders in error messages for dynamic values:
|
|
|
262
262
|
|
|
263
263
|
## Backend-Only Values
|
|
264
264
|
|
|
265
|
-
### `<
|
|
265
|
+
### `<odac:set>`
|
|
266
266
|
|
|
267
267
|
Set values that are processed only on the backend (not visible in HTML):
|
|
268
268
|
|
|
269
269
|
```html
|
|
270
|
-
<
|
|
270
|
+
<odac:register redirect="/dashboard">
|
|
271
271
|
<!-- User input fields -->
|
|
272
|
-
<
|
|
273
|
-
<
|
|
274
|
-
</
|
|
272
|
+
<odac:field name="email" type="email" unique>
|
|
273
|
+
<odac:validate rule="required|email"/>
|
|
274
|
+
</odac:field>
|
|
275
275
|
|
|
276
276
|
<!-- Backend-only values -->
|
|
277
|
-
<
|
|
278
|
-
<
|
|
279
|
-
<
|
|
280
|
-
<
|
|
277
|
+
<odac:set name="role" value="user"/>
|
|
278
|
+
<odac:set name="status" value="pending"/>
|
|
279
|
+
<odac:set name="registered_at" compute="now"/>
|
|
280
|
+
<odac:set name="ip_address" compute="ip"/>
|
|
281
281
|
|
|
282
|
-
<
|
|
283
|
-
</
|
|
282
|
+
<odac:submit>Register</odac:submit>
|
|
283
|
+
</odac:register>
|
|
284
284
|
```
|
|
285
285
|
|
|
286
286
|
**Attributes:**
|
|
@@ -295,13 +295,13 @@ Set values that are processed only on the backend (not visible in HTML):
|
|
|
295
295
|
Use `compute` attribute for dynamic values:
|
|
296
296
|
|
|
297
297
|
```html
|
|
298
|
-
<
|
|
299
|
-
<
|
|
300
|
-
<
|
|
301
|
-
<
|
|
302
|
-
<
|
|
303
|
-
<
|
|
304
|
-
<
|
|
298
|
+
<odac:set name="registered_at" compute="now"/> <!-- Unix timestamp -->
|
|
299
|
+
<odac:set name="date" compute="date"/> <!-- 2025-01-20 -->
|
|
300
|
+
<odac:set name="datetime" compute="datetime"/> <!-- ISO 8601 -->
|
|
301
|
+
<odac:set name="timestamp" compute="timestamp"/> <!-- Milliseconds -->
|
|
302
|
+
<odac:set name="ip_address" compute="ip"/> <!-- User's IP -->
|
|
303
|
+
<odac:set name="user_agent" compute="user_agent"/> <!-- Browser info -->
|
|
304
|
+
<odac:set name="uuid" compute="uuid"/> <!-- UUID v4 -->
|
|
305
305
|
```
|
|
306
306
|
|
|
307
307
|
### Conditional Values
|
|
@@ -309,103 +309,103 @@ Use `compute` attribute for dynamic values:
|
|
|
309
309
|
Use `if-empty` to set a default only if the user didn't provide a value:
|
|
310
310
|
|
|
311
311
|
```html
|
|
312
|
-
<
|
|
312
|
+
<odac:field name="country" type="text" placeholder="Country (optional)">
|
|
313
313
|
<!-- User can optionally fill this -->
|
|
314
|
-
</
|
|
314
|
+
</odac:field>
|
|
315
315
|
|
|
316
|
-
<
|
|
316
|
+
<odac:set name="country" value="TR" if-empty/>
|
|
317
317
|
<!-- If user leaves it empty, set to "TR" -->
|
|
318
318
|
```
|
|
319
319
|
|
|
320
320
|
## Submit Button
|
|
321
321
|
|
|
322
|
-
### `<
|
|
322
|
+
### `<odac:submit>`
|
|
323
323
|
|
|
324
324
|
Defines the submit button:
|
|
325
325
|
|
|
326
326
|
```html
|
|
327
|
-
<
|
|
327
|
+
<odac:submit
|
|
328
328
|
text="Create Account" <!-- Button text -->
|
|
329
329
|
loading="Creating account..."> <!-- Loading state text -->
|
|
330
|
-
</
|
|
330
|
+
</odac:submit>
|
|
331
331
|
```
|
|
332
332
|
|
|
333
333
|
Or use content as button text:
|
|
334
334
|
|
|
335
335
|
```html
|
|
336
|
-
<
|
|
336
|
+
<odac:submit>Create Account</odac:submit>
|
|
337
337
|
```
|
|
338
338
|
|
|
339
339
|
## Complete Example
|
|
340
340
|
|
|
341
341
|
```html
|
|
342
|
-
<
|
|
342
|
+
<odac:register redirect="/dashboard" autologin="true">
|
|
343
343
|
|
|
344
344
|
<!-- Email Field -->
|
|
345
|
-
<
|
|
346
|
-
<
|
|
347
|
-
<
|
|
348
|
-
<
|
|
349
|
-
</
|
|
345
|
+
<odac:field name="email" type="email" placeholder="Email Address" unique>
|
|
346
|
+
<odac:validate rule="required" message="Email is required"/>
|
|
347
|
+
<odac:validate rule="email" message="Please enter a valid email address"/>
|
|
348
|
+
<odac:validate rule="unique" message="The email '{value}' is already registered"/>
|
|
349
|
+
</odac:field>
|
|
350
350
|
|
|
351
351
|
<!-- Username Field -->
|
|
352
|
-
<
|
|
353
|
-
<
|
|
354
|
-
<
|
|
355
|
-
<
|
|
356
|
-
<
|
|
357
|
-
<
|
|
358
|
-
</
|
|
352
|
+
<odac:field name="username" type="text" placeholder="Username" unique>
|
|
353
|
+
<odac:validate rule="required" message="Username is required"/>
|
|
354
|
+
<odac:validate rule="minlen:4" message="Username must be at least {min} characters"/>
|
|
355
|
+
<odac:validate rule="maxlen:20" message="Username cannot exceed {max} characters"/>
|
|
356
|
+
<odac:validate rule="alphanumeric" message="Only letters and numbers allowed"/>
|
|
357
|
+
<odac:validate rule="unique" message="Username '{value}' is already taken"/>
|
|
358
|
+
</odac:field>
|
|
359
359
|
|
|
360
360
|
<!-- Password Field -->
|
|
361
|
-
<
|
|
362
|
-
<
|
|
363
|
-
<
|
|
364
|
-
</
|
|
361
|
+
<odac:field name="password" type="password" placeholder="Password">
|
|
362
|
+
<odac:validate rule="required" message="Password is required"/>
|
|
363
|
+
<odac:validate rule="minlen:8" message="Password must be at least {min} characters"/>
|
|
364
|
+
</odac:field>
|
|
365
365
|
|
|
366
366
|
<!-- Password Confirmation -->
|
|
367
|
-
<
|
|
368
|
-
<
|
|
369
|
-
<
|
|
370
|
-
</
|
|
367
|
+
<odac:field name="password_confirm" type="password" placeholder="Confirm Password" skip>
|
|
368
|
+
<odac:validate rule="required" message="Please confirm your password"/>
|
|
369
|
+
<odac:validate rule="same:password" message="Passwords do not match"/>
|
|
370
|
+
</odac:field>
|
|
371
371
|
|
|
372
372
|
<!-- Full Name -->
|
|
373
|
-
<
|
|
374
|
-
<
|
|
375
|
-
<
|
|
376
|
-
<
|
|
377
|
-
</
|
|
373
|
+
<odac:field name="name" type="text" placeholder="Full Name">
|
|
374
|
+
<odac:validate rule="required" message="Name is required"/>
|
|
375
|
+
<odac:validate rule="alphaspace" message="Name can only contain letters and spaces"/>
|
|
376
|
+
<odac:validate rule="minlen:3" message="Name must be at least {min} characters"/>
|
|
377
|
+
</odac:field>
|
|
378
378
|
|
|
379
379
|
<!-- Age -->
|
|
380
|
-
<
|
|
381
|
-
<
|
|
382
|
-
<
|
|
383
|
-
<
|
|
384
|
-
</
|
|
380
|
+
<odac:field name="age" type="number" placeholder="Age">
|
|
381
|
+
<odac:validate rule="required" message="Age is required"/>
|
|
382
|
+
<odac:validate rule="min:18" message="You must be at least {min} years old"/>
|
|
383
|
+
<odac:validate rule="max:120" message="Please enter a valid age"/>
|
|
384
|
+
</odac:field>
|
|
385
385
|
|
|
386
386
|
<!-- Terms Checkbox -->
|
|
387
|
-
<
|
|
388
|
-
<
|
|
389
|
-
</
|
|
387
|
+
<odac:field name="terms" type="checkbox" label="I agree to the terms and conditions" skip>
|
|
388
|
+
<odac:validate rule="accepted" message="You must accept the terms to continue"/>
|
|
389
|
+
</odac:field>
|
|
390
390
|
|
|
391
391
|
<!-- Backend-only values -->
|
|
392
|
-
<
|
|
393
|
-
<
|
|
394
|
-
<
|
|
395
|
-
<
|
|
396
|
-
<
|
|
392
|
+
<odac:set name="role" value="user"/>
|
|
393
|
+
<odac:set name="status" value="active"/>
|
|
394
|
+
<odac:set name="registered_at" compute="now"/>
|
|
395
|
+
<odac:set name="ip_address" compute="ip"/>
|
|
396
|
+
<odac:set name="user_agent" compute="user_agent"/>
|
|
397
397
|
|
|
398
398
|
<!-- Submit Button -->
|
|
399
|
-
<
|
|
399
|
+
<odac:submit text="Create Account" loading="Creating your account..."/>
|
|
400
400
|
|
|
401
|
-
</
|
|
401
|
+
</odac:register>
|
|
402
402
|
```
|
|
403
403
|
|
|
404
404
|
## Security Features
|
|
405
405
|
|
|
406
406
|
### Automatic Security
|
|
407
407
|
|
|
408
|
-
|
|
408
|
+
Odac automatically handles:
|
|
409
409
|
|
|
410
410
|
1. **CSRF Protection** - Form tokens prevent cross-site attacks
|
|
411
411
|
2. **Password Hashing** - Passwords are hashed with bcrypt
|
|
@@ -420,29 +420,29 @@ Each form gets a unique token when rendered:
|
|
|
420
420
|
- Token is stored server-side with field whitelist
|
|
421
421
|
- Token expires after 30 minutes
|
|
422
422
|
- Only fields defined in the view are accepted
|
|
423
|
-
- Backend-only values (`<
|
|
423
|
+
- Backend-only values (`<odac:set>`) are never exposed to HTML
|
|
424
424
|
|
|
425
425
|
### Unique Field Checking
|
|
426
426
|
|
|
427
427
|
Fields marked with `unique` attribute are checked against the database:
|
|
428
428
|
|
|
429
429
|
```html
|
|
430
|
-
<
|
|
431
|
-
<
|
|
432
|
-
</
|
|
430
|
+
<odac:field name="email" type="email" unique>
|
|
431
|
+
<odac:validate rule="unique" message="Email already exists"/>
|
|
432
|
+
</odac:field>
|
|
433
433
|
```
|
|
434
434
|
|
|
435
435
|
The system automatically queries the auth table to check for duplicates.
|
|
436
436
|
|
|
437
437
|
## HTML5 Validation
|
|
438
438
|
|
|
439
|
-
|
|
439
|
+
Odac automatically adds HTML5 validation attributes for better UX:
|
|
440
440
|
|
|
441
441
|
```html
|
|
442
442
|
<!-- This field -->
|
|
443
|
-
<
|
|
444
|
-
<
|
|
445
|
-
</
|
|
443
|
+
<odac:field name="username" type="text">
|
|
444
|
+
<odac:validate rule="required|minlen:4|maxlen:20|alphanumeric"/>
|
|
445
|
+
</odac:field>
|
|
446
446
|
|
|
447
447
|
<!-- Generates this HTML -->
|
|
448
448
|
<input
|
|
@@ -506,7 +506,7 @@ Customize table names and primary key if needed:
|
|
|
506
506
|
|
|
507
507
|
**Auto-Creation (Recommended):**
|
|
508
508
|
|
|
509
|
-
The users table is created automatically on first registration!
|
|
509
|
+
The users table is created automatically on first registration! Odac analyzes your form fields and creates the appropriate table structure:
|
|
510
510
|
|
|
511
511
|
- Fields with `unique` attribute → `VARCHAR(255) NOT NULL UNIQUE`
|
|
512
512
|
- Password field → `VARCHAR(255) NOT NULL` (for bcrypt hashes)
|
|
@@ -564,20 +564,20 @@ CREATE TABLE `candy_auth` (
|
|
|
564
564
|
|
|
565
565
|
### Display Errors
|
|
566
566
|
|
|
567
|
-
Error messages are automatically displayed in `<span>` elements with `
|
|
567
|
+
Error messages are automatically displayed in `<span>` elements with `odac-form-error` attribute:
|
|
568
568
|
|
|
569
569
|
```html
|
|
570
570
|
<!-- Errors appear here automatically -->
|
|
571
|
-
<span class="
|
|
571
|
+
<span class="odac-form-error" odac-form-error="email" style="display:none;"></span>
|
|
572
572
|
```
|
|
573
573
|
|
|
574
574
|
### Success Messages
|
|
575
575
|
|
|
576
|
-
Success messages appear in elements with `
|
|
576
|
+
Success messages appear in elements with `odac-form-success` class:
|
|
577
577
|
|
|
578
578
|
```html
|
|
579
579
|
<!-- Success message appears here -->
|
|
580
|
-
<span class="
|
|
580
|
+
<span class="odac-form-success" style="display:none;"></span>
|
|
581
581
|
```
|
|
582
582
|
|
|
583
583
|
### Custom Styling
|
|
@@ -585,13 +585,13 @@ Success messages appear in elements with `candy-form-success` class:
|
|
|
585
585
|
Style error and success messages with CSS:
|
|
586
586
|
|
|
587
587
|
```css
|
|
588
|
-
.
|
|
588
|
+
.odac-form-error {
|
|
589
589
|
color: red;
|
|
590
590
|
font-size: 0.875rem;
|
|
591
591
|
margin-top: 0.25rem;
|
|
592
592
|
}
|
|
593
593
|
|
|
594
|
-
.
|
|
594
|
+
.odac-form-success {
|
|
595
595
|
color: green;
|
|
596
596
|
font-size: 1rem;
|
|
597
597
|
padding: 1rem;
|
|
@@ -600,11 +600,11 @@ Style error and success messages with CSS:
|
|
|
600
600
|
border-radius: 0.25rem;
|
|
601
601
|
}
|
|
602
602
|
|
|
603
|
-
.
|
|
603
|
+
.odac-field {
|
|
604
604
|
margin-bottom: 1rem;
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
-
input.
|
|
607
|
+
input._odac_error {
|
|
608
608
|
border-color: red;
|
|
609
609
|
}
|
|
610
610
|
```
|
|
@@ -617,13 +617,13 @@ You can define custom callbacks for computed values:
|
|
|
617
617
|
|
|
618
618
|
```javascript
|
|
619
619
|
// In your page controller or global script
|
|
620
|
-
|
|
620
|
+
Odac.fn.generateReferralCode = async (Odac) => {
|
|
621
621
|
return Math.random().toString(36).substring(2, 10).toUpperCase()
|
|
622
622
|
}
|
|
623
623
|
```
|
|
624
624
|
|
|
625
625
|
```html
|
|
626
|
-
<
|
|
626
|
+
<odac:set name="referral_code" callback="generateReferralCode"/>
|
|
627
627
|
```
|
|
628
628
|
|
|
629
629
|
### Conditional Registration
|
|
@@ -631,21 +631,21 @@ Candy.fn.generateReferralCode = async (Candy) => {
|
|
|
631
631
|
Disable auto-login and handle redirect manually:
|
|
632
632
|
|
|
633
633
|
```html
|
|
634
|
-
<
|
|
634
|
+
<odac:register autologin="false">
|
|
635
635
|
<!-- fields -->
|
|
636
|
-
</
|
|
636
|
+
</odac:register>
|
|
637
637
|
```
|
|
638
638
|
|
|
639
639
|
Then handle the response in JavaScript if needed (though not required for basic usage).
|
|
640
640
|
|
|
641
641
|
## Best Practices
|
|
642
642
|
|
|
643
|
-
1. **Always validate on both client and server** -
|
|
643
|
+
1. **Always validate on both client and server** - Odac does this automatically
|
|
644
644
|
2. **Use unique attribute for email/username** - Prevents duplicate accounts
|
|
645
645
|
3. **Set minimum password length** - Use `minlen:8` or higher
|
|
646
646
|
4. **Use password confirmation** - Add a `password_confirm` field with `same:password` rule
|
|
647
647
|
5. **Add terms checkbox** - Use `accepted` rule for legal compliance
|
|
648
|
-
6. **Use backend-only values** - Store metadata with `<
|
|
648
|
+
6. **Use backend-only values** - Store metadata with `<odac:set>`
|
|
649
649
|
7. **Provide clear error messages** - Use placeholders for dynamic values
|
|
650
650
|
8. **Test form expiration** - Forms expire after 30 minutes
|
|
651
651
|
|
|
@@ -660,7 +660,7 @@ Then handle the response in JavaScript if needed (though not required for basic
|
|
|
660
660
|
### Validation Not Working
|
|
661
661
|
|
|
662
662
|
- Ensure validation rules are spelled correctly
|
|
663
|
-
- Check that field names match between `<
|
|
663
|
+
- Check that field names match between `<odac:field>` and validation
|
|
664
664
|
- Verify HTML5 validation isn't blocking submission
|
|
665
665
|
|
|
666
666
|
### Unique Check Failing
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
## ⏰ Session Management
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Odac uses a secure cookie-based session system with automatic expiration and cleanup.
|
|
4
4
|
|
|
5
5
|
### How Sessions Work
|
|
6
6
|
|
|
7
|
-
When a user logs in,
|
|
7
|
+
When a user logs in, Odac creates a session token stored in secure cookies:
|
|
8
8
|
|
|
9
9
|
```javascript
|
|
10
10
|
// Login creates a session
|
|
11
|
-
await
|
|
11
|
+
await Odac.Auth.login({email, password})
|
|
12
12
|
|
|
13
13
|
// Session is automatically checked on each request
|
|
14
|
-
if (await
|
|
15
|
-
const user =
|
|
14
|
+
if (await Odac.Auth.check()) {
|
|
15
|
+
const user = Odac.Auth.user(null)
|
|
16
16
|
}
|
|
17
17
|
```
|
|
18
18
|
|
|
@@ -116,18 +116,18 @@ Sessions are protected with:
|
|
|
116
116
|
|
|
117
117
|
**Logout current session:**
|
|
118
118
|
```javascript
|
|
119
|
-
await
|
|
119
|
+
await Odac.Auth.logout()
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
**Check session status:**
|
|
123
123
|
```javascript
|
|
124
|
-
const isLoggedIn = await
|
|
124
|
+
const isLoggedIn = await Odac.Auth.check()
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
**Get user info:**
|
|
128
128
|
```javascript
|
|
129
|
-
const user =
|
|
130
|
-
const email =
|
|
129
|
+
const user = Odac.Auth.user(null) // Full user object
|
|
130
|
+
const email = Odac.Auth.user('email') // Specific field
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
### Best Practices
|
|
@@ -153,7 +153,7 @@ const email = Candy.Auth.user('email') // Specific field
|
|
|
153
153
|
- Manually clean old sessions if needed:
|
|
154
154
|
```javascript
|
|
155
155
|
const cutoffDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
|
|
156
|
-
await
|
|
156
|
+
await Odac.Mysql.table('user_tokens')
|
|
157
157
|
.where('active', '<', cutoffDate)
|
|
158
158
|
.delete()
|
|
159
159
|
```
|