odac 0.9.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/.editorconfig +21 -0
- package/.github/workflows/auto-pr-description.yml +49 -0
- package/.github/workflows/release.yml +32 -0
- package/.github/workflows/test-coverage.yml +58 -0
- package/.husky/pre-commit +2 -0
- package/.kiro/steering/code-style.md +56 -0
- package/.kiro/steering/product.md +20 -0
- package/.kiro/steering/structure.md +77 -0
- package/.kiro/steering/tech.md +87 -0
- package/.prettierrc +10 -0
- package/.releaserc.js +134 -0
- package/AGENTS.md +84 -0
- package/CHANGELOG.md +181 -0
- package/CODE_OF_CONDUCT.md +83 -0
- package/CONTRIBUTING.md +63 -0
- package/LICENSE +661 -0
- package/README.md +57 -0
- package/SECURITY.md +26 -0
- package/bin/candy +10 -0
- package/bin/candypack +10 -0
- package/cli/index.js +3 -0
- package/cli/src/Cli.js +348 -0
- package/cli/src/Connector.js +93 -0
- package/cli/src/Monitor.js +416 -0
- package/core/Candy.js +87 -0
- package/core/Commands.js +239 -0
- package/core/Config.js +1094 -0
- package/core/Lang.js +52 -0
- package/core/Log.js +43 -0
- package/core/Process.js +26 -0
- package/docs/backend/01-overview/01-whats-in-the-candy-box.md +9 -0
- package/docs/backend/01-overview/02-super-handy-helper-functions.md +9 -0
- package/docs/backend/01-overview/03-development-server.md +79 -0
- package/docs/backend/02-structure/01-typical-project-layout.md +39 -0
- package/docs/backend/03-config/00-configuration-overview.md +214 -0
- package/docs/backend/03-config/01-database-connection.md +60 -0
- package/docs/backend/03-config/02-static-route-mapping-optional.md +20 -0
- package/docs/backend/03-config/03-request-timeout.md +11 -0
- package/docs/backend/03-config/04-environment-variables.md +227 -0
- package/docs/backend/03-config/05-early-hints.md +352 -0
- package/docs/backend/04-routing/01-basic-page-routes.md +28 -0
- package/docs/backend/04-routing/02-controller-less-view-routes.md +43 -0
- package/docs/backend/04-routing/03-api-and-data-routes.md +20 -0
- package/docs/backend/04-routing/04-authentication-aware-routes.md +48 -0
- package/docs/backend/04-routing/05-advanced-routing.md +14 -0
- package/docs/backend/04-routing/06-error-pages.md +101 -0
- package/docs/backend/04-routing/07-cron-jobs.md +149 -0
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +17 -0
- package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +20 -0
- package/docs/backend/05-controllers/03-controller-classes.md +93 -0
- package/docs/backend/05-forms/01-custom-forms.md +395 -0
- package/docs/backend/05-forms/02-automatic-database-insert.md +297 -0
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +96 -0
- package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +40 -0
- package/docs/backend/07-views/01-the-view-directory.md +73 -0
- package/docs/backend/07-views/02-rendering-a-view.md +179 -0
- package/docs/backend/07-views/03-template-syntax.md +181 -0
- package/docs/backend/07-views/03-variables.md +328 -0
- package/docs/backend/07-views/04-request-data.md +231 -0
- package/docs/backend/07-views/05-conditionals.md +290 -0
- package/docs/backend/07-views/06-loops.md +353 -0
- package/docs/backend/07-views/07-translations.md +358 -0
- package/docs/backend/07-views/08-backend-javascript.md +398 -0
- package/docs/backend/07-views/09-comments.md +297 -0
- package/docs/backend/08-database/01-database-connection.md +99 -0
- package/docs/backend/08-database/02-using-mysql.md +322 -0
- package/docs/backend/09-validation/01-the-validator-service.md +424 -0
- package/docs/backend/10-authentication/01-user-logins-with-authjs.md +53 -0
- package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +55 -0
- package/docs/backend/10-authentication/03-register.md +134 -0
- package/docs/backend/10-authentication/04-candy-register-forms.md +676 -0
- package/docs/backend/10-authentication/05-session-management.md +159 -0
- package/docs/backend/10-authentication/06-candy-login-forms.md +596 -0
- package/docs/backend/11-mail/01-the-mail-service.md +42 -0
- package/docs/backend/12-streaming/01-streaming-overview.md +300 -0
- package/docs/backend/13-utilities/01-candy-var.md +504 -0
- package/docs/frontend/01-overview/01-introduction.md +146 -0
- package/docs/frontend/02-ajax-navigation/01-quick-start.md +608 -0
- package/docs/frontend/02-ajax-navigation/02-configuration.md +370 -0
- package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +519 -0
- package/docs/frontend/03-forms/01-form-handling.md +420 -0
- package/docs/frontend/04-api-requests/01-get-post.md +443 -0
- package/docs/frontend/05-streaming/01-client-streaming.md +163 -0
- package/docs/index.json +452 -0
- package/docs/server/01-installation/01-quick-install.md +19 -0
- package/docs/server/01-installation/02-manual-installation-via-npm.md +9 -0
- package/docs/server/02-get-started/01-core-concepts.md +7 -0
- package/docs/server/02-get-started/02-basic-commands.md +57 -0
- package/docs/server/02-get-started/03-cli-reference.md +276 -0
- package/docs/server/02-get-started/04-cli-quick-reference.md +102 -0
- package/docs/server/03-service/01-start-a-new-service.md +57 -0
- package/docs/server/03-service/02-delete-a-service.md +48 -0
- package/docs/server/04-web/01-create-a-website.md +36 -0
- package/docs/server/04-web/02-list-websites.md +9 -0
- package/docs/server/04-web/03-delete-a-website.md +29 -0
- package/docs/server/05-subdomain/01-create-a-subdomain.md +32 -0
- package/docs/server/05-subdomain/02-list-subdomains.md +33 -0
- package/docs/server/05-subdomain/03-delete-a-subdomain.md +41 -0
- package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +34 -0
- package/docs/server/07-mail/01-create-a-mail-account.md +23 -0
- package/docs/server/07-mail/02-delete-a-mail-account.md +20 -0
- package/docs/server/07-mail/03-list-mail-accounts.md +20 -0
- package/docs/server/07-mail/04-change-account-password.md +23 -0
- package/eslint.config.mjs +120 -0
- package/framework/index.js +4 -0
- package/framework/src/Auth.js +309 -0
- package/framework/src/Candy.js +81 -0
- package/framework/src/Config.js +79 -0
- package/framework/src/Env.js +60 -0
- package/framework/src/Lang.js +57 -0
- package/framework/src/Mail.js +83 -0
- package/framework/src/Mysql.js +575 -0
- package/framework/src/Request.js +301 -0
- package/framework/src/Route/Cron.js +128 -0
- package/framework/src/Route/Internal.js +439 -0
- package/framework/src/Route.js +455 -0
- package/framework/src/Server.js +15 -0
- package/framework/src/Stream.js +163 -0
- package/framework/src/Token.js +37 -0
- package/framework/src/Validator.js +271 -0
- package/framework/src/Var.js +211 -0
- package/framework/src/View/EarlyHints.js +190 -0
- package/framework/src/View/Form.js +600 -0
- package/framework/src/View.js +513 -0
- package/framework/web/candy.js +838 -0
- package/jest.config.js +22 -0
- package/locale/de-DE.json +80 -0
- package/locale/en-US.json +79 -0
- package/locale/es-ES.json +80 -0
- package/locale/fr-FR.json +80 -0
- package/locale/pt-BR.json +80 -0
- package/locale/ru-RU.json +80 -0
- package/locale/tr-TR.json +85 -0
- package/locale/zh-CN.json +80 -0
- package/package.json +86 -0
- package/server/index.js +5 -0
- package/server/src/Api.js +88 -0
- package/server/src/DNS.js +940 -0
- package/server/src/Hub.js +535 -0
- package/server/src/Mail.js +571 -0
- package/server/src/SSL.js +180 -0
- package/server/src/Server.js +27 -0
- package/server/src/Service.js +248 -0
- package/server/src/Subdomain.js +64 -0
- package/server/src/Web/Firewall.js +170 -0
- package/server/src/Web/Proxy.js +134 -0
- package/server/src/Web.js +451 -0
- package/server/src/mail/imap.js +1091 -0
- package/server/src/mail/server.js +32 -0
- package/server/src/mail/smtp.js +786 -0
- package/test/cli/Cli.test.js +36 -0
- package/test/core/Candy.test.js +234 -0
- package/test/core/Commands.test.js +538 -0
- package/test/core/Config.test.js +1435 -0
- package/test/core/Lang.test.js +250 -0
- package/test/core/Process.test.js +156 -0
- package/test/framework/Route.test.js +239 -0
- package/test/framework/View/EarlyHints.test.js +282 -0
- package/test/scripts/check-coverage.js +132 -0
- package/test/server/Api.test.js +647 -0
- package/test/server/Client.test.js +338 -0
- package/test/server/DNS.test.js +2050 -0
- package/test/server/DNS.test.js.bak +2084 -0
- package/test/server/Log.test.js +73 -0
- package/test/server/Mail.account.test_.js +460 -0
- package/test/server/Mail.init.test_.js +411 -0
- package/test/server/Mail.test_.js +1340 -0
- package/test/server/SSL.test_.js +1491 -0
- package/test/server/Server.test.js +765 -0
- package/test/server/Service.test_.js +1127 -0
- package/test/server/Subdomain.test.js +440 -0
- package/test/server/Web/Firewall.test.js +175 -0
- package/test/server/Web.test_.js +1562 -0
- package/test/server/__mocks__/acme-client.js +17 -0
- package/test/server/__mocks__/bcrypt.js +50 -0
- package/test/server/__mocks__/child_process.js +389 -0
- package/test/server/__mocks__/crypto.js +432 -0
- package/test/server/__mocks__/fs.js +450 -0
- package/test/server/__mocks__/globalCandy.js +227 -0
- package/test/server/__mocks__/http-proxy.js +105 -0
- package/test/server/__mocks__/http.js +575 -0
- package/test/server/__mocks__/https.js +272 -0
- package/test/server/__mocks__/index.js +249 -0
- package/test/server/__mocks__/mail/server.js +100 -0
- package/test/server/__mocks__/mail/smtp.js +31 -0
- package/test/server/__mocks__/mailparser.js +81 -0
- package/test/server/__mocks__/net.js +369 -0
- package/test/server/__mocks__/node-forge.js +328 -0
- package/test/server/__mocks__/os.js +320 -0
- package/test/server/__mocks__/path.js +291 -0
- package/test/server/__mocks__/selfsigned.js +8 -0
- package/test/server/__mocks__/server/src/mail/server.js +100 -0
- package/test/server/__mocks__/server/src/mail/smtp.js +31 -0
- package/test/server/__mocks__/smtp-server.js +106 -0
- package/test/server/__mocks__/sqlite3.js +394 -0
- package/test/server/__mocks__/testFactories.js +299 -0
- package/test/server/__mocks__/testHelpers.js +363 -0
- package/test/server/__mocks__/tls.js +229 -0
- package/watchdog/index.js +3 -0
- package/watchdog/src/Watchdog.js +156 -0
- package/web/config.json +5 -0
- package/web/controller/page/about.js +27 -0
- package/web/controller/page/index.js +34 -0
- package/web/package.json +18 -0
- package/web/public/assets/css/style.css +1835 -0
- package/web/public/assets/js/app.js +96 -0
- package/web/route/www.js +19 -0
- package/web/skeleton/main.html +22 -0
- package/web/view/content/about.html +65 -0
- package/web/view/content/home.html +205 -0
- package/web/view/footer/main.html +11 -0
- package/web/view/head/main.html +5 -0
- package/web/view/header/main.html +14 -0
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
# Candy Register Forms
|
|
2
|
+
|
|
3
|
+
The `<candy:register>` component provides a zero-configuration way to create secure registration forms. Simply write HTML, and CandyPack handles validation, security, database operations, and auto-login automatically.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### 1. Configure Database (config.json)
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"mysql": {
|
|
12
|
+
"host": "localhost",
|
|
13
|
+
"user": "root",
|
|
14
|
+
"password": "",
|
|
15
|
+
"database": "your_database"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
That's all you need! The `auth` configuration is optional.
|
|
21
|
+
|
|
22
|
+
### 2. Create Your Form (view/content/register.html)
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<candy:register redirect="/dashboard">
|
|
26
|
+
<candy:field name="email" type="email" placeholder="Email" unique>
|
|
27
|
+
<candy:validate rule="required|email" message="Please enter a valid email"/>
|
|
28
|
+
</candy:field>
|
|
29
|
+
|
|
30
|
+
<candy:field name="username" type="text" placeholder="Username" unique>
|
|
31
|
+
<candy:validate rule="required|minlen:4" message="Username must be at least 4 characters"/>
|
|
32
|
+
</candy:field>
|
|
33
|
+
|
|
34
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
35
|
+
<candy:validate rule="required|minlen:8" message="Password must be at least 8 characters"/>
|
|
36
|
+
</candy:field>
|
|
37
|
+
|
|
38
|
+
<candy:submit>Create Account</candy:submit>
|
|
39
|
+
</candy:register>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
That's it! No JavaScript, no controller code, no SQL needed. The form automatically:
|
|
43
|
+
- Creates the database table (if it doesn't exist)
|
|
44
|
+
- Validates input (client-side and server-side)
|
|
45
|
+
- Checks for unique email/username
|
|
46
|
+
- Hashes passwords with bcrypt
|
|
47
|
+
- Creates the user account
|
|
48
|
+
- Logs in the user
|
|
49
|
+
- Redirects to dashboard
|
|
50
|
+
|
|
51
|
+
### 3. Optional: Customize Auth Configuration
|
|
52
|
+
|
|
53
|
+
If you want to customize table names or primary key:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"mysql": {
|
|
58
|
+
"host": "localhost",
|
|
59
|
+
"user": "root",
|
|
60
|
+
"password": "",
|
|
61
|
+
"database": "your_database"
|
|
62
|
+
},
|
|
63
|
+
"auth": {
|
|
64
|
+
"table": "users", // Optional: User table name (default: "users")
|
|
65
|
+
"key": "id", // Optional: Primary key (default: "id")
|
|
66
|
+
"token": "candy_auth" // Optional: Token table (default: "candy_auth")
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**If you don't specify `auth` config:**
|
|
72
|
+
- Table name defaults to `users`
|
|
73
|
+
- Primary key defaults to `id`
|
|
74
|
+
- Token table defaults to `candy_auth`
|
|
75
|
+
- Table is created automatically based on your form fields
|
|
76
|
+
|
|
77
|
+
## Form Attributes
|
|
78
|
+
|
|
79
|
+
### `<candy:register>`
|
|
80
|
+
|
|
81
|
+
Main form container with configuration options:
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<candy:register
|
|
85
|
+
redirect="/dashboard" <!-- Redirect URL after successful registration -->
|
|
86
|
+
autologin="true"> <!-- Auto-login after registration (default: true) -->
|
|
87
|
+
<!-- fields here -->
|
|
88
|
+
</candy:register>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Attributes:**
|
|
92
|
+
- `redirect` - URL to redirect after successful registration
|
|
93
|
+
- `autologin` - Whether to automatically log in the user (default: `true`)
|
|
94
|
+
|
|
95
|
+
## Field Types
|
|
96
|
+
|
|
97
|
+
### `<candy:field>`
|
|
98
|
+
|
|
99
|
+
Defines an input field with validation rules:
|
|
100
|
+
|
|
101
|
+
```html
|
|
102
|
+
<candy:field
|
|
103
|
+
name="email" <!-- Field name (required) -->
|
|
104
|
+
type="email" <!-- Input type (default: text) -->
|
|
105
|
+
placeholder="Email" <!-- Placeholder text -->
|
|
106
|
+
label="Email Address" <!-- Label text (optional) -->
|
|
107
|
+
unique> <!-- Check uniqueness in database -->
|
|
108
|
+
|
|
109
|
+
<candy:validate rule="required|email" message="Valid email required"/>
|
|
110
|
+
</candy:field>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Attributes:**
|
|
114
|
+
- `name` - Field name (required)
|
|
115
|
+
- `type` - Input type: text, email, password, number, checkbox, textarea
|
|
116
|
+
- `placeholder` - Placeholder text
|
|
117
|
+
- `label` - Label text (for checkbox or explicit labels)
|
|
118
|
+
- `unique` - Check if value already exists in database
|
|
119
|
+
- `skip` - Validate field but don't save to database (useful for password confirmation, terms acceptance)
|
|
120
|
+
|
|
121
|
+
**Supported Input Types:**
|
|
122
|
+
- `text` - Text input
|
|
123
|
+
- `email` - Email input (with HTML5 validation)
|
|
124
|
+
- `password` - Password input
|
|
125
|
+
- `number` - Number input
|
|
126
|
+
- `checkbox` - Checkbox input
|
|
127
|
+
- `textarea` - Textarea
|
|
128
|
+
|
|
129
|
+
### Skip Attribute
|
|
130
|
+
|
|
131
|
+
Use the `skip` attribute for fields that should be validated but not saved to the database:
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<!-- Password confirmation - validate but don't save -->
|
|
135
|
+
<candy:field name="confirm_password" type="password" placeholder="Confirm Password" skip>
|
|
136
|
+
<candy:validate rule="required|same:password" message="Passwords must match"/>
|
|
137
|
+
</candy:field>
|
|
138
|
+
|
|
139
|
+
<!-- Terms acceptance - validate but don't save -->
|
|
140
|
+
<candy:field name="terms" type="checkbox" label="I accept the terms" skip>
|
|
141
|
+
<candy:validate rule="accepted" message="You must accept the terms"/>
|
|
142
|
+
</candy:field>
|
|
143
|
+
|
|
144
|
+
<!-- Captcha verification - validate but don't save -->
|
|
145
|
+
<candy:field name="captcha" type="text" placeholder="Enter captcha" skip>
|
|
146
|
+
<candy:validate rule="required" message="Please complete the captcha"/>
|
|
147
|
+
</candy:field>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Common Use Cases:**
|
|
151
|
+
- Password confirmation fields
|
|
152
|
+
- Terms and conditions checkboxes
|
|
153
|
+
- Privacy policy acceptance
|
|
154
|
+
- Captcha verification
|
|
155
|
+
- Temporary validation fields
|
|
156
|
+
|
|
157
|
+
## Validation Rules
|
|
158
|
+
|
|
159
|
+
### `<candy:validate>`
|
|
160
|
+
|
|
161
|
+
Defines validation rules for a field:
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<candy:validate
|
|
165
|
+
rule="required|minlen:4|alphanumeric"
|
|
166
|
+
message="Username must be 4+ alphanumeric characters"/>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Attributes:**
|
|
170
|
+
- `rule` - Validation rules (pipe-separated)
|
|
171
|
+
- `message` - Error message to display
|
|
172
|
+
|
|
173
|
+
### Available Rules
|
|
174
|
+
|
|
175
|
+
**Basic Rules:**
|
|
176
|
+
- `required` - Field is required
|
|
177
|
+
- `email` - Valid email format
|
|
178
|
+
- `url` - Valid URL format
|
|
179
|
+
- `numeric` - Only numbers
|
|
180
|
+
- `alpha` - Only letters
|
|
181
|
+
- `alphanumeric` - Letters and numbers only
|
|
182
|
+
- `alphaspace` - Letters and spaces only
|
|
183
|
+
- `alphanumericspace` - Letters, numbers, and spaces
|
|
184
|
+
- `accepted` - Must be accepted (for checkboxes)
|
|
185
|
+
|
|
186
|
+
**Length Rules:**
|
|
187
|
+
- `minlen:X` - Minimum length
|
|
188
|
+
- `maxlen:X` - Maximum length
|
|
189
|
+
- `len:X` - Exact length
|
|
190
|
+
|
|
191
|
+
**Number Rules:**
|
|
192
|
+
- `min:X` - Minimum value
|
|
193
|
+
- `max:X` - Maximum value
|
|
194
|
+
|
|
195
|
+
**Comparison Rules:**
|
|
196
|
+
- `same:field` - Must match another field
|
|
197
|
+
- `different:field` - Must be different from another field
|
|
198
|
+
- `equal:value` - Must equal specific value
|
|
199
|
+
- `not:value` - Must not equal specific value
|
|
200
|
+
|
|
201
|
+
**Pattern Rules:**
|
|
202
|
+
- `regex:pattern` - Custom regex pattern
|
|
203
|
+
- `domain` - Valid domain name
|
|
204
|
+
- `ip` - Valid IP address
|
|
205
|
+
- `mac` - Valid MAC address
|
|
206
|
+
|
|
207
|
+
**Special Rules:**
|
|
208
|
+
- `unique` - Check uniqueness in database (use with `unique` attribute on field)
|
|
209
|
+
- `xss` - Check for XSS attempts
|
|
210
|
+
|
|
211
|
+
### Multiple Validation Rules
|
|
212
|
+
|
|
213
|
+
You can add multiple `<candy:validate>` tags for different error messages:
|
|
214
|
+
|
|
215
|
+
```html
|
|
216
|
+
<candy:field name="username" type="text" unique>
|
|
217
|
+
<candy:validate rule="required" message="Username is required"/>
|
|
218
|
+
<candy:validate rule="minlen:4" message="Username must be at least {min} characters"/>
|
|
219
|
+
<candy:validate rule="maxlen:20" message="Username cannot exceed {max} characters"/>
|
|
220
|
+
<candy:validate rule="alphanumeric" message="Username can only contain letters and numbers"/>
|
|
221
|
+
<candy:validate rule="unique" message="Username '{value}' is already taken"/>
|
|
222
|
+
</candy:field>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Or combine rules in a single tag:
|
|
226
|
+
|
|
227
|
+
```html
|
|
228
|
+
<candy:field name="username" type="text" unique>
|
|
229
|
+
<candy:validate
|
|
230
|
+
rule="required|minlen:4|maxlen:20|alphanumeric"
|
|
231
|
+
message="Username must be 4-20 alphanumeric characters"/>
|
|
232
|
+
<candy:validate rule="unique" message="Username '{value}' is already taken"/>
|
|
233
|
+
</candy:field>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Message Placeholders
|
|
237
|
+
|
|
238
|
+
Use placeholders in error messages for dynamic values:
|
|
239
|
+
|
|
240
|
+
```html
|
|
241
|
+
<candy:field name="username" type="text">
|
|
242
|
+
<candy:validate
|
|
243
|
+
rule="minlen:4"
|
|
244
|
+
message="Username '{value}' is too short. Minimum {min} characters required"/>
|
|
245
|
+
</candy:field>
|
|
246
|
+
|
|
247
|
+
<candy:field name="age" type="number">
|
|
248
|
+
<candy:validate
|
|
249
|
+
rule="min:18|max:120"
|
|
250
|
+
message="Age must be between {min} and {max} years"/>
|
|
251
|
+
</candy:field>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Available Placeholders:**
|
|
255
|
+
- `{value}` - User's input value
|
|
256
|
+
- `{field}` - Field name
|
|
257
|
+
- `{label}` - Field label or placeholder
|
|
258
|
+
- `{min}` - Minimum value (for minlen, min rules)
|
|
259
|
+
- `{max}` - Maximum value (for maxlen, max rules)
|
|
260
|
+
- `{len}` - Required length (for len rule)
|
|
261
|
+
- `{other}` - Other field name (for same, different rules)
|
|
262
|
+
|
|
263
|
+
## Backend-Only Values
|
|
264
|
+
|
|
265
|
+
### `<candy:set>`
|
|
266
|
+
|
|
267
|
+
Set values that are processed only on the backend (not visible in HTML):
|
|
268
|
+
|
|
269
|
+
```html
|
|
270
|
+
<candy:register redirect="/dashboard">
|
|
271
|
+
<!-- User input fields -->
|
|
272
|
+
<candy:field name="email" type="email" unique>
|
|
273
|
+
<candy:validate rule="required|email"/>
|
|
274
|
+
</candy:field>
|
|
275
|
+
|
|
276
|
+
<!-- Backend-only values -->
|
|
277
|
+
<candy:set name="role" value="user"/>
|
|
278
|
+
<candy:set name="status" value="pending"/>
|
|
279
|
+
<candy:set name="registered_at" compute="now"/>
|
|
280
|
+
<candy:set name="ip_address" compute="ip"/>
|
|
281
|
+
|
|
282
|
+
<candy:submit>Register</candy:submit>
|
|
283
|
+
</candy:register>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Attributes:**
|
|
287
|
+
- `name` - Field name (required)
|
|
288
|
+
- `value` - Static value
|
|
289
|
+
- `compute` - Computed value (see below)
|
|
290
|
+
- `callback` - Custom callback function
|
|
291
|
+
- `if-empty` - Only set if user didn't provide a value
|
|
292
|
+
|
|
293
|
+
### Computed Values
|
|
294
|
+
|
|
295
|
+
Use `compute` attribute for dynamic values:
|
|
296
|
+
|
|
297
|
+
```html
|
|
298
|
+
<candy:set name="registered_at" compute="now"/> <!-- Unix timestamp -->
|
|
299
|
+
<candy:set name="date" compute="date"/> <!-- 2025-01-20 -->
|
|
300
|
+
<candy:set name="datetime" compute="datetime"/> <!-- ISO 8601 -->
|
|
301
|
+
<candy:set name="timestamp" compute="timestamp"/> <!-- Milliseconds -->
|
|
302
|
+
<candy:set name="ip_address" compute="ip"/> <!-- User's IP -->
|
|
303
|
+
<candy:set name="user_agent" compute="user_agent"/> <!-- Browser info -->
|
|
304
|
+
<candy:set name="uuid" compute="uuid"/> <!-- UUID v4 -->
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Conditional Values
|
|
308
|
+
|
|
309
|
+
Use `if-empty` to set a default only if the user didn't provide a value:
|
|
310
|
+
|
|
311
|
+
```html
|
|
312
|
+
<candy:field name="country" type="text" placeholder="Country (optional)">
|
|
313
|
+
<!-- User can optionally fill this -->
|
|
314
|
+
</candy:field>
|
|
315
|
+
|
|
316
|
+
<candy:set name="country" value="TR" if-empty/>
|
|
317
|
+
<!-- If user leaves it empty, set to "TR" -->
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Submit Button
|
|
321
|
+
|
|
322
|
+
### `<candy:submit>`
|
|
323
|
+
|
|
324
|
+
Defines the submit button:
|
|
325
|
+
|
|
326
|
+
```html
|
|
327
|
+
<candy:submit
|
|
328
|
+
text="Create Account" <!-- Button text -->
|
|
329
|
+
loading="Creating account..."> <!-- Loading state text -->
|
|
330
|
+
</candy:submit>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Or use content as button text:
|
|
334
|
+
|
|
335
|
+
```html
|
|
336
|
+
<candy:submit>Create Account</candy:submit>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Complete Example
|
|
340
|
+
|
|
341
|
+
```html
|
|
342
|
+
<candy:register redirect="/dashboard" autologin="true">
|
|
343
|
+
|
|
344
|
+
<!-- Email Field -->
|
|
345
|
+
<candy:field name="email" type="email" placeholder="Email Address" unique>
|
|
346
|
+
<candy:validate rule="required" message="Email is required"/>
|
|
347
|
+
<candy:validate rule="email" message="Please enter a valid email address"/>
|
|
348
|
+
<candy:validate rule="unique" message="The email '{value}' is already registered"/>
|
|
349
|
+
</candy:field>
|
|
350
|
+
|
|
351
|
+
<!-- Username Field -->
|
|
352
|
+
<candy:field name="username" type="text" placeholder="Username" unique>
|
|
353
|
+
<candy:validate rule="required" message="Username is required"/>
|
|
354
|
+
<candy:validate rule="minlen:4" message="Username must be at least {min} characters"/>
|
|
355
|
+
<candy:validate rule="maxlen:20" message="Username cannot exceed {max} characters"/>
|
|
356
|
+
<candy:validate rule="alphanumeric" message="Only letters and numbers allowed"/>
|
|
357
|
+
<candy:validate rule="unique" message="Username '{value}' is already taken"/>
|
|
358
|
+
</candy:field>
|
|
359
|
+
|
|
360
|
+
<!-- Password Field -->
|
|
361
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
362
|
+
<candy:validate rule="required" message="Password is required"/>
|
|
363
|
+
<candy:validate rule="minlen:8" message="Password must be at least {min} characters"/>
|
|
364
|
+
</candy:field>
|
|
365
|
+
|
|
366
|
+
<!-- Password Confirmation -->
|
|
367
|
+
<candy:field name="password_confirm" type="password" placeholder="Confirm Password" skip>
|
|
368
|
+
<candy:validate rule="required" message="Please confirm your password"/>
|
|
369
|
+
<candy:validate rule="same:password" message="Passwords do not match"/>
|
|
370
|
+
</candy:field>
|
|
371
|
+
|
|
372
|
+
<!-- Full Name -->
|
|
373
|
+
<candy:field name="name" type="text" placeholder="Full Name">
|
|
374
|
+
<candy:validate rule="required" message="Name is required"/>
|
|
375
|
+
<candy:validate rule="alphaspace" message="Name can only contain letters and spaces"/>
|
|
376
|
+
<candy:validate rule="minlen:3" message="Name must be at least {min} characters"/>
|
|
377
|
+
</candy:field>
|
|
378
|
+
|
|
379
|
+
<!-- Age -->
|
|
380
|
+
<candy:field name="age" type="number" placeholder="Age">
|
|
381
|
+
<candy:validate rule="required" message="Age is required"/>
|
|
382
|
+
<candy:validate rule="min:18" message="You must be at least {min} years old"/>
|
|
383
|
+
<candy:validate rule="max:120" message="Please enter a valid age"/>
|
|
384
|
+
</candy:field>
|
|
385
|
+
|
|
386
|
+
<!-- Terms Checkbox -->
|
|
387
|
+
<candy:field name="terms" type="checkbox" label="I agree to the terms and conditions" skip>
|
|
388
|
+
<candy:validate rule="accepted" message="You must accept the terms to continue"/>
|
|
389
|
+
</candy:field>
|
|
390
|
+
|
|
391
|
+
<!-- Backend-only values -->
|
|
392
|
+
<candy:set name="role" value="user"/>
|
|
393
|
+
<candy:set name="status" value="active"/>
|
|
394
|
+
<candy:set name="registered_at" compute="now"/>
|
|
395
|
+
<candy:set name="ip_address" compute="ip"/>
|
|
396
|
+
<candy:set name="user_agent" compute="user_agent"/>
|
|
397
|
+
|
|
398
|
+
<!-- Submit Button -->
|
|
399
|
+
<candy:submit text="Create Account" loading="Creating your account..."/>
|
|
400
|
+
|
|
401
|
+
</candy:register>
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Security Features
|
|
405
|
+
|
|
406
|
+
### Automatic Security
|
|
407
|
+
|
|
408
|
+
CandyPack automatically handles:
|
|
409
|
+
|
|
410
|
+
1. **CSRF Protection** - Form tokens prevent cross-site attacks
|
|
411
|
+
2. **Password Hashing** - Passwords are hashed with bcrypt
|
|
412
|
+
3. **SQL Injection Prevention** - All queries are parameterized
|
|
413
|
+
4. **XSS Protection** - Input is sanitized
|
|
414
|
+
5. **Field Whitelisting** - Only defined fields are processed
|
|
415
|
+
6. **Token Expiration** - Form tokens expire after 30 minutes
|
|
416
|
+
|
|
417
|
+
### Token System
|
|
418
|
+
|
|
419
|
+
Each form gets a unique token when rendered:
|
|
420
|
+
- Token is stored server-side with field whitelist
|
|
421
|
+
- Token expires after 30 minutes
|
|
422
|
+
- Only fields defined in the view are accepted
|
|
423
|
+
- Backend-only values (`<candy:set>`) are never exposed to HTML
|
|
424
|
+
|
|
425
|
+
### Unique Field Checking
|
|
426
|
+
|
|
427
|
+
Fields marked with `unique` attribute are checked against the database:
|
|
428
|
+
|
|
429
|
+
```html
|
|
430
|
+
<candy:field name="email" type="email" unique>
|
|
431
|
+
<candy:validate rule="unique" message="Email already exists"/>
|
|
432
|
+
</candy:field>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
The system automatically queries the auth table to check for duplicates.
|
|
436
|
+
|
|
437
|
+
## HTML5 Validation
|
|
438
|
+
|
|
439
|
+
CandyPack automatically adds HTML5 validation attributes for better UX:
|
|
440
|
+
|
|
441
|
+
```html
|
|
442
|
+
<!-- This field -->
|
|
443
|
+
<candy:field name="username" type="text">
|
|
444
|
+
<candy:validate rule="required|minlen:4|maxlen:20|alphanumeric"/>
|
|
445
|
+
</candy:field>
|
|
446
|
+
|
|
447
|
+
<!-- Generates this HTML -->
|
|
448
|
+
<input
|
|
449
|
+
type="text"
|
|
450
|
+
name="username"
|
|
451
|
+
required
|
|
452
|
+
minlength="4"
|
|
453
|
+
maxlength="20"
|
|
454
|
+
pattern="[a-zA-Z0-9]+">
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Automatic HTML5 Attributes:**
|
|
458
|
+
- `required` - For required fields
|
|
459
|
+
- `minlength` / `maxlength` - For length validation
|
|
460
|
+
- `min` / `max` - For number validation
|
|
461
|
+
- `pattern` - For alphanumeric, numeric, alpha rules
|
|
462
|
+
- `type="email"` - Native email validation
|
|
463
|
+
- `type="url"` - Native URL validation
|
|
464
|
+
|
|
465
|
+
This provides instant feedback to users before form submission.
|
|
466
|
+
|
|
467
|
+
## Configuration Reference
|
|
468
|
+
|
|
469
|
+
### Required Configuration
|
|
470
|
+
|
|
471
|
+
Only MySQL configuration is required:
|
|
472
|
+
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"mysql": {
|
|
476
|
+
"host": "localhost",
|
|
477
|
+
"user": "root",
|
|
478
|
+
"password": "",
|
|
479
|
+
"database": "your_database"
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Optional Auth Configuration
|
|
485
|
+
|
|
486
|
+
Customize table names and primary key if needed:
|
|
487
|
+
|
|
488
|
+
```json
|
|
489
|
+
{
|
|
490
|
+
"auth": {
|
|
491
|
+
"table": "users", // User table name (default: "users")
|
|
492
|
+
"key": "id", // Primary key column (default: "id")
|
|
493
|
+
"token": "candy_auth" // Session token table (default: "candy_auth")
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**Default Values:**
|
|
499
|
+
- If `auth` is not specified, defaults are used
|
|
500
|
+
- Table: `users`
|
|
501
|
+
- Primary key: `id`
|
|
502
|
+
- Token table: `candy_auth`
|
|
503
|
+
- All tables are created automatically if they don't exist
|
|
504
|
+
|
|
505
|
+
### Database Schema
|
|
506
|
+
|
|
507
|
+
**Auto-Creation (Recommended):**
|
|
508
|
+
|
|
509
|
+
The users table is created automatically on first registration! CandyPack analyzes your form fields and creates the appropriate table structure:
|
|
510
|
+
|
|
511
|
+
- Fields with `unique` attribute → `VARCHAR(255) NOT NULL UNIQUE`
|
|
512
|
+
- Password field → `VARCHAR(255) NOT NULL` (for bcrypt hashes)
|
|
513
|
+
- Number fields → `INT` or `BIGINT`
|
|
514
|
+
- Text fields → `VARCHAR(255)` or `TEXT` (if > 255 chars)
|
|
515
|
+
- Boolean fields → `TINYINT(1)`
|
|
516
|
+
- Timestamps → `created_at` and `updated_at` added automatically
|
|
517
|
+
|
|
518
|
+
**Manual Creation (Optional):**
|
|
519
|
+
|
|
520
|
+
If you prefer to create the table manually:
|
|
521
|
+
|
|
522
|
+
```sql
|
|
523
|
+
CREATE TABLE `users` (
|
|
524
|
+
`id` INT NOT NULL AUTO_INCREMENT,
|
|
525
|
+
`email` VARCHAR(255) NOT NULL UNIQUE,
|
|
526
|
+
`username` VARCHAR(255) NOT NULL UNIQUE,
|
|
527
|
+
`password` VARCHAR(255) NOT NULL,
|
|
528
|
+
`name` VARCHAR(255) NULL,
|
|
529
|
+
`role` VARCHAR(50) DEFAULT 'user',
|
|
530
|
+
`status` VARCHAR(50) DEFAULT 'active',
|
|
531
|
+
`registered_at` INT NULL,
|
|
532
|
+
`ip_address` VARCHAR(45) NULL,
|
|
533
|
+
`user_agent` TEXT NULL,
|
|
534
|
+
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
535
|
+
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
536
|
+
PRIMARY KEY (`id`)
|
|
537
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**Important:**
|
|
541
|
+
- Password field must be `VARCHAR(255)` to store bcrypt hashes (60 chars + future-proofing)
|
|
542
|
+
- Fields marked with `unique` attribute should have `UNIQUE` constraint
|
|
543
|
+
- Auto-creation uses `utf8mb4_unicode_ci` collation for full Unicode support
|
|
544
|
+
|
|
545
|
+
### Token Table
|
|
546
|
+
|
|
547
|
+
The token table is created automatically on first login, but you can create it manually:
|
|
548
|
+
|
|
549
|
+
```sql
|
|
550
|
+
CREATE TABLE `candy_auth` (
|
|
551
|
+
`id` INT NOT NULL AUTO_INCREMENT,
|
|
552
|
+
`user` INT NOT NULL,
|
|
553
|
+
`token_x` VARCHAR(255) NOT NULL,
|
|
554
|
+
`token_y` VARCHAR(255) NOT NULL,
|
|
555
|
+
`browser` VARCHAR(255) NOT NULL,
|
|
556
|
+
`ip` VARCHAR(255) NOT NULL,
|
|
557
|
+
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
558
|
+
`active` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
559
|
+
PRIMARY KEY (`id`)
|
|
560
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
## Error Handling
|
|
564
|
+
|
|
565
|
+
### Display Errors
|
|
566
|
+
|
|
567
|
+
Error messages are automatically displayed in `<span>` elements with `candy-form-error` attribute:
|
|
568
|
+
|
|
569
|
+
```html
|
|
570
|
+
<!-- Errors appear here automatically -->
|
|
571
|
+
<span class="candy-form-error" candy-form-error="email" style="display:none;"></span>
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Success Messages
|
|
575
|
+
|
|
576
|
+
Success messages appear in elements with `candy-form-success` class:
|
|
577
|
+
|
|
578
|
+
```html
|
|
579
|
+
<!-- Success message appears here -->
|
|
580
|
+
<span class="candy-form-success" style="display:none;"></span>
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Custom Styling
|
|
584
|
+
|
|
585
|
+
Style error and success messages with CSS:
|
|
586
|
+
|
|
587
|
+
```css
|
|
588
|
+
.candy-form-error {
|
|
589
|
+
color: red;
|
|
590
|
+
font-size: 0.875rem;
|
|
591
|
+
margin-top: 0.25rem;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.candy-form-success {
|
|
595
|
+
color: green;
|
|
596
|
+
font-size: 1rem;
|
|
597
|
+
padding: 1rem;
|
|
598
|
+
background: #d4edda;
|
|
599
|
+
border: 1px solid #c3e6cb;
|
|
600
|
+
border-radius: 0.25rem;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.candy-field {
|
|
604
|
+
margin-bottom: 1rem;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
input._candy_error {
|
|
608
|
+
border-color: red;
|
|
609
|
+
}
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
## Advanced Usage
|
|
613
|
+
|
|
614
|
+
### Custom Callbacks
|
|
615
|
+
|
|
616
|
+
You can define custom callbacks for computed values:
|
|
617
|
+
|
|
618
|
+
```javascript
|
|
619
|
+
// In your page controller or global script
|
|
620
|
+
Candy.fn.generateReferralCode = async (Candy) => {
|
|
621
|
+
return Math.random().toString(36).substring(2, 10).toUpperCase()
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
```html
|
|
626
|
+
<candy:set name="referral_code" callback="generateReferralCode"/>
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### Conditional Registration
|
|
630
|
+
|
|
631
|
+
Disable auto-login and handle redirect manually:
|
|
632
|
+
|
|
633
|
+
```html
|
|
634
|
+
<candy:register autologin="false">
|
|
635
|
+
<!-- fields -->
|
|
636
|
+
</candy:register>
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Then handle the response in JavaScript if needed (though not required for basic usage).
|
|
640
|
+
|
|
641
|
+
## Best Practices
|
|
642
|
+
|
|
643
|
+
1. **Always validate on both client and server** - CandyPack does this automatically
|
|
644
|
+
2. **Use unique attribute for email/username** - Prevents duplicate accounts
|
|
645
|
+
3. **Set minimum password length** - Use `minlen:8` or higher
|
|
646
|
+
4. **Use password confirmation** - Add a `password_confirm` field with `same:password` rule
|
|
647
|
+
5. **Add terms checkbox** - Use `accepted` rule for legal compliance
|
|
648
|
+
6. **Use backend-only values** - Store metadata with `<candy:set>`
|
|
649
|
+
7. **Provide clear error messages** - Use placeholders for dynamic values
|
|
650
|
+
8. **Test form expiration** - Forms expire after 30 minutes
|
|
651
|
+
|
|
652
|
+
## Troubleshooting
|
|
653
|
+
|
|
654
|
+
### Form Not Submitting
|
|
655
|
+
|
|
656
|
+
- Check that `config.json` has auth configuration
|
|
657
|
+
- Verify database table exists
|
|
658
|
+
- Check browser console for JavaScript errors
|
|
659
|
+
|
|
660
|
+
### Validation Not Working
|
|
661
|
+
|
|
662
|
+
- Ensure validation rules are spelled correctly
|
|
663
|
+
- Check that field names match between `<candy:field>` and validation
|
|
664
|
+
- Verify HTML5 validation isn't blocking submission
|
|
665
|
+
|
|
666
|
+
### Unique Check Failing
|
|
667
|
+
|
|
668
|
+
- Verify `unique` attribute is on the field
|
|
669
|
+
- Check that auth table name in config matches your database
|
|
670
|
+
- Ensure the field exists in your database table
|
|
671
|
+
|
|
672
|
+
### Token Expired
|
|
673
|
+
|
|
674
|
+
- Forms expire after 30 minutes
|
|
675
|
+
- User needs to refresh the page to get a new token
|
|
676
|
+
- Consider adding a message about session expiration
|