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,596 @@
|
|
|
1
|
+
# Candy Login Forms
|
|
2
|
+
|
|
3
|
+
The `<candy:login>` component provides a zero-configuration way to create secure login forms. Simply write HTML, and CandyPack handles validation, security, authentication, and session management 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/login.html)
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<candy:login redirect="/dashboard">
|
|
26
|
+
<candy:field name="email" type="email" placeholder="Email">
|
|
27
|
+
<candy:validate rule="required|email" message="Please enter a valid email"/>
|
|
28
|
+
</candy:field>
|
|
29
|
+
|
|
30
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
31
|
+
<candy:validate rule="required" message="Password is required"/>
|
|
32
|
+
</candy:field>
|
|
33
|
+
|
|
34
|
+
<candy:submit>Login</candy:submit>
|
|
35
|
+
</candy:login>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
That's it! No JavaScript, no controller code needed. The form automatically:
|
|
39
|
+
- Validates input (client-side and server-side)
|
|
40
|
+
- Authenticates the user
|
|
41
|
+
- Creates a secure session
|
|
42
|
+
- Redirects to the specified page
|
|
43
|
+
|
|
44
|
+
### 3. Optional: Customize Auth Configuration
|
|
45
|
+
|
|
46
|
+
If you want to customize table names or primary key:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mysql": {
|
|
51
|
+
"host": "localhost",
|
|
52
|
+
"user": "root",
|
|
53
|
+
"password": "",
|
|
54
|
+
"database": "your_database"
|
|
55
|
+
},
|
|
56
|
+
"auth": {
|
|
57
|
+
"table": "users", // Optional: User table name (default: "users")
|
|
58
|
+
"key": "id", // Optional: Primary key (default: "id")
|
|
59
|
+
"token": "candy_auth" // Optional: Token table (default: "candy_auth")
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Form Attributes
|
|
65
|
+
|
|
66
|
+
### `<candy:login>`
|
|
67
|
+
|
|
68
|
+
Main form container with configuration options:
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<candy:login
|
|
72
|
+
redirect="/dashboard"> <!-- Redirect URL after successful login -->
|
|
73
|
+
<!-- fields here -->
|
|
74
|
+
</candy:login>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Attributes:**
|
|
78
|
+
- `redirect` - URL to redirect after successful login (required)
|
|
79
|
+
|
|
80
|
+
## Field Types
|
|
81
|
+
|
|
82
|
+
### `<candy:field>`
|
|
83
|
+
|
|
84
|
+
Defines an input field with validation rules:
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<candy:field
|
|
88
|
+
name="email" <!-- Field name (required) -->
|
|
89
|
+
type="email" <!-- Input type (default: text) -->
|
|
90
|
+
placeholder="Email" <!-- Placeholder text -->
|
|
91
|
+
label="Email Address" <!-- Label text (optional) -->
|
|
92
|
+
class="form-input" <!-- CSS class (optional) -->
|
|
93
|
+
id="email-field"> <!-- HTML ID (optional) -->
|
|
94
|
+
|
|
95
|
+
<candy:validate rule="required|email" message="Valid email required"/>
|
|
96
|
+
</candy:field>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Attributes:**
|
|
100
|
+
- `name` - Field name (required)
|
|
101
|
+
- `type` - Input type: text, email, password, number, checkbox
|
|
102
|
+
- `placeholder` - Placeholder text
|
|
103
|
+
- `label` - Label text
|
|
104
|
+
- `class` - CSS class for styling
|
|
105
|
+
- `id` - HTML ID attribute
|
|
106
|
+
|
|
107
|
+
**Supported Input Types:**
|
|
108
|
+
- `text` - Text input
|
|
109
|
+
- `email` - Email input (with HTML5 validation)
|
|
110
|
+
- `password` - Password input
|
|
111
|
+
- `number` - Number input
|
|
112
|
+
- `checkbox` - Checkbox input (for "remember me" functionality)
|
|
113
|
+
|
|
114
|
+
## Validation Rules
|
|
115
|
+
|
|
116
|
+
### `<candy:validate>`
|
|
117
|
+
|
|
118
|
+
Defines validation rules for a field:
|
|
119
|
+
|
|
120
|
+
```html
|
|
121
|
+
<candy:validate
|
|
122
|
+
rule="required|minlen:4"
|
|
123
|
+
message="This field is required and must be at least 4 characters"/>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Attributes:**
|
|
127
|
+
- `rule` - Validation rules (pipe-separated)
|
|
128
|
+
- `message` - Error message to display
|
|
129
|
+
|
|
130
|
+
### Available Rules
|
|
131
|
+
|
|
132
|
+
**Basic Rules:**
|
|
133
|
+
- `required` - Field is required
|
|
134
|
+
- `email` - Valid email format
|
|
135
|
+
- `numeric` - Only numbers
|
|
136
|
+
- `alpha` - Only letters
|
|
137
|
+
- `alphanumeric` - Letters and numbers only
|
|
138
|
+
|
|
139
|
+
**Length Rules:**
|
|
140
|
+
- `minlen:X` - Minimum length
|
|
141
|
+
- `maxlen:X` - Maximum length
|
|
142
|
+
- `len:X` - Exact length
|
|
143
|
+
|
|
144
|
+
**Number Rules:**
|
|
145
|
+
- `min:X` - Minimum value
|
|
146
|
+
- `max:X` - Maximum value
|
|
147
|
+
|
|
148
|
+
**Pattern Rules:**
|
|
149
|
+
- `regex:pattern` - Custom regex pattern
|
|
150
|
+
|
|
151
|
+
### Multiple Validation Rules
|
|
152
|
+
|
|
153
|
+
You can add multiple `<candy:validate>` tags for different error messages:
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<candy:field name="email" type="email">
|
|
157
|
+
<candy:validate rule="required" message="Email is required"/>
|
|
158
|
+
<candy:validate rule="email" message="Please enter a valid email address"/>
|
|
159
|
+
</candy:field>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Or combine rules in a single tag:
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<candy:field name="email" type="email">
|
|
166
|
+
<candy:validate
|
|
167
|
+
rule="required|email"
|
|
168
|
+
message="Please enter a valid email address"/>
|
|
169
|
+
</candy:field>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Message Placeholders
|
|
173
|
+
|
|
174
|
+
Use placeholders in error messages for dynamic values:
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<candy:field name="username" type="text">
|
|
178
|
+
<candy:validate
|
|
179
|
+
rule="minlen:4"
|
|
180
|
+
message="Username '{value}' is too short. Minimum {min} characters required"/>
|
|
181
|
+
</candy:field>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Available Placeholders:**
|
|
185
|
+
- `{value}` - User's input value
|
|
186
|
+
- `{field}` - Field name
|
|
187
|
+
- `{label}` - Field label or placeholder
|
|
188
|
+
- `{min}` - Minimum value (for minlen, min rules)
|
|
189
|
+
- `{max}` - Maximum value (for maxlen, max rules)
|
|
190
|
+
- `{len}` - Required length (for len rule)
|
|
191
|
+
|
|
192
|
+
## Submit Button
|
|
193
|
+
|
|
194
|
+
### `<candy:submit>`
|
|
195
|
+
|
|
196
|
+
Defines the submit button:
|
|
197
|
+
|
|
198
|
+
```html
|
|
199
|
+
<candy:submit
|
|
200
|
+
text="Login" <!-- Button text -->
|
|
201
|
+
loading="Logging in..." <!-- Loading state text -->
|
|
202
|
+
class="btn btn-primary" <!-- CSS class -->
|
|
203
|
+
id="login-button"> <!-- HTML ID -->
|
|
204
|
+
</candy:submit>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Or use content as button text:
|
|
208
|
+
|
|
209
|
+
```html
|
|
210
|
+
<candy:submit>Login</candy:submit>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Complete Examples
|
|
214
|
+
|
|
215
|
+
### Basic Login Form
|
|
216
|
+
|
|
217
|
+
```html
|
|
218
|
+
<candy:login redirect="/dashboard">
|
|
219
|
+
|
|
220
|
+
<!-- Email Field -->
|
|
221
|
+
<candy:field name="email" type="email" placeholder="Email Address">
|
|
222
|
+
<candy:validate rule="required" message="Email is required"/>
|
|
223
|
+
<candy:validate rule="email" message="Please enter a valid email address"/>
|
|
224
|
+
</candy:field>
|
|
225
|
+
|
|
226
|
+
<!-- Password Field -->
|
|
227
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
228
|
+
<candy:validate rule="required" message="Password is required"/>
|
|
229
|
+
</candy:field>
|
|
230
|
+
|
|
231
|
+
<!-- Submit Button -->
|
|
232
|
+
<candy:submit text="Login" loading="Logging in..."/>
|
|
233
|
+
|
|
234
|
+
</candy:login>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Login with Username
|
|
238
|
+
|
|
239
|
+
```html
|
|
240
|
+
<candy:login redirect="/dashboard">
|
|
241
|
+
|
|
242
|
+
<!-- Username Field -->
|
|
243
|
+
<candy:field name="username" type="text" placeholder="Username">
|
|
244
|
+
<candy:validate rule="required" message="Username is required"/>
|
|
245
|
+
<candy:validate rule="minlen:4" message="Username must be at least {min} characters"/>
|
|
246
|
+
</candy:field>
|
|
247
|
+
|
|
248
|
+
<!-- Password Field -->
|
|
249
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
250
|
+
<candy:validate rule="required" message="Password is required"/>
|
|
251
|
+
</candy:field>
|
|
252
|
+
|
|
253
|
+
<!-- Submit Button -->
|
|
254
|
+
<candy:submit>Login</candy:submit>
|
|
255
|
+
|
|
256
|
+
</candy:login>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Login with Remember Me
|
|
260
|
+
|
|
261
|
+
```html
|
|
262
|
+
<candy:login redirect="/dashboard">
|
|
263
|
+
|
|
264
|
+
<!-- Email Field -->
|
|
265
|
+
<candy:field name="email" type="email" placeholder="Email">
|
|
266
|
+
<candy:validate rule="required|email" message="Please enter a valid email"/>
|
|
267
|
+
</candy:field>
|
|
268
|
+
|
|
269
|
+
<!-- Password Field -->
|
|
270
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
271
|
+
<candy:validate rule="required" message="Password is required"/>
|
|
272
|
+
</candy:field>
|
|
273
|
+
|
|
274
|
+
<!-- Remember Me Checkbox -->
|
|
275
|
+
<candy:field name="remember" type="checkbox" label="Remember me">
|
|
276
|
+
</candy:field>
|
|
277
|
+
|
|
278
|
+
<!-- Submit Button -->
|
|
279
|
+
<candy:submit>Login</candy:submit>
|
|
280
|
+
|
|
281
|
+
</candy:login>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Styled Login Form
|
|
285
|
+
|
|
286
|
+
```html
|
|
287
|
+
<div class="login-container">
|
|
288
|
+
<h2>Welcome Back</h2>
|
|
289
|
+
|
|
290
|
+
<candy:login redirect="/dashboard">
|
|
291
|
+
|
|
292
|
+
<div class="form-group">
|
|
293
|
+
<candy:field
|
|
294
|
+
name="email"
|
|
295
|
+
type="email"
|
|
296
|
+
placeholder="Email Address"
|
|
297
|
+
class="form-control">
|
|
298
|
+
<candy:validate rule="required|email" message="Please enter a valid email"/>
|
|
299
|
+
</candy:field>
|
|
300
|
+
<span class="candy-form-error" candy-form-error="email"></span>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div class="form-group">
|
|
304
|
+
<candy:field
|
|
305
|
+
name="password"
|
|
306
|
+
type="password"
|
|
307
|
+
placeholder="Password"
|
|
308
|
+
class="form-control">
|
|
309
|
+
<candy:validate rule="required" message="Password is required"/>
|
|
310
|
+
</candy:field>
|
|
311
|
+
<span class="candy-form-error" candy-form-error="password"></span>
|
|
312
|
+
</div>
|
|
313
|
+
|
|
314
|
+
<div class="form-group">
|
|
315
|
+
<candy:field name="remember" type="checkbox" label="Remember me" class="form-check-input">
|
|
316
|
+
</candy:field>
|
|
317
|
+
</div>
|
|
318
|
+
|
|
319
|
+
<candy:submit class="btn btn-primary btn-block" text="Login" loading="Logging in..."/>
|
|
320
|
+
|
|
321
|
+
<span class="candy-form-error" candy-form-error="_candy_form"></span>
|
|
322
|
+
|
|
323
|
+
</candy:login>
|
|
324
|
+
|
|
325
|
+
<p class="text-center mt-3">
|
|
326
|
+
<a href="/forgot-password">Forgot password?</a>
|
|
327
|
+
</p>
|
|
328
|
+
</div>
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Security Features
|
|
332
|
+
|
|
333
|
+
### Automatic Security
|
|
334
|
+
|
|
335
|
+
CandyPack automatically handles:
|
|
336
|
+
|
|
337
|
+
1. **CSRF Protection** - Form tokens prevent cross-site attacks
|
|
338
|
+
2. **Password Verification** - Passwords are verified against bcrypt hashes
|
|
339
|
+
3. **SQL Injection Prevention** - All queries are parameterized
|
|
340
|
+
4. **XSS Protection** - Input is sanitized
|
|
341
|
+
5. **Field Whitelisting** - Only defined fields are processed
|
|
342
|
+
6. **Token Expiration** - Form tokens expire after 30 minutes
|
|
343
|
+
7. **Session Security** - Secure session management with token rotation
|
|
344
|
+
|
|
345
|
+
### Token System
|
|
346
|
+
|
|
347
|
+
Each form gets a unique token when rendered:
|
|
348
|
+
- Token is stored server-side with field whitelist
|
|
349
|
+
- Token expires after 30 minutes
|
|
350
|
+
- Only fields defined in the view are accepted
|
|
351
|
+
- Session validation prevents token hijacking
|
|
352
|
+
|
|
353
|
+
## HTML5 Validation
|
|
354
|
+
|
|
355
|
+
CandyPack automatically adds HTML5 validation attributes for better UX:
|
|
356
|
+
|
|
357
|
+
```html
|
|
358
|
+
<!-- This field -->
|
|
359
|
+
<candy:field name="email" type="email">
|
|
360
|
+
<candy:validate rule="required|email"/>
|
|
361
|
+
</candy:field>
|
|
362
|
+
|
|
363
|
+
<!-- Generates this HTML -->
|
|
364
|
+
<input
|
|
365
|
+
type="email"
|
|
366
|
+
name="email"
|
|
367
|
+
required>
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**Automatic HTML5 Attributes:**
|
|
371
|
+
- `required` - For required fields
|
|
372
|
+
- `minlength` / `maxlength` - For length validation
|
|
373
|
+
- `min` / `max` - For number validation
|
|
374
|
+
- `pattern` - For alphanumeric, numeric, alpha rules
|
|
375
|
+
- `type="email"` - Native email validation
|
|
376
|
+
|
|
377
|
+
This provides instant feedback to users before form submission.
|
|
378
|
+
|
|
379
|
+
## Error Handling
|
|
380
|
+
|
|
381
|
+
### Display Errors
|
|
382
|
+
|
|
383
|
+
Error messages are automatically displayed in `<span>` elements with `candy-form-error` attribute:
|
|
384
|
+
|
|
385
|
+
```html
|
|
386
|
+
<!-- Errors appear here automatically -->
|
|
387
|
+
<span class="candy-form-error" candy-form-error="email" style="display:none;"></span>
|
|
388
|
+
<span class="candy-form-error" candy-form-error="password" style="display:none;"></span>
|
|
389
|
+
<span class="candy-form-error" candy-form-error="_candy_form" style="display:none;"></span>
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Success Messages
|
|
393
|
+
|
|
394
|
+
Success messages appear in elements with `candy-form-success` class:
|
|
395
|
+
|
|
396
|
+
```html
|
|
397
|
+
<!-- Success message appears here -->
|
|
398
|
+
<span class="candy-form-success" style="display:none;"></span>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Custom Styling
|
|
402
|
+
|
|
403
|
+
Style error and success messages with CSS:
|
|
404
|
+
|
|
405
|
+
```css
|
|
406
|
+
.candy-form-error {
|
|
407
|
+
color: red;
|
|
408
|
+
font-size: 0.875rem;
|
|
409
|
+
margin-top: 0.25rem;
|
|
410
|
+
display: block;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.candy-form-success {
|
|
414
|
+
color: green;
|
|
415
|
+
font-size: 1rem;
|
|
416
|
+
padding: 1rem;
|
|
417
|
+
background: #d4edda;
|
|
418
|
+
border: 1px solid #c3e6cb;
|
|
419
|
+
border-radius: 0.25rem;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
input._candy_error {
|
|
423
|
+
border-color: red;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Configuration Reference
|
|
428
|
+
|
|
429
|
+
### Required Configuration
|
|
430
|
+
|
|
431
|
+
Only MySQL configuration is required:
|
|
432
|
+
|
|
433
|
+
```json
|
|
434
|
+
{
|
|
435
|
+
"mysql": {
|
|
436
|
+
"host": "localhost",
|
|
437
|
+
"user": "root",
|
|
438
|
+
"password": "",
|
|
439
|
+
"database": "your_database"
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Optional Auth Configuration
|
|
445
|
+
|
|
446
|
+
Customize table names and primary key if needed:
|
|
447
|
+
|
|
448
|
+
```json
|
|
449
|
+
{
|
|
450
|
+
"auth": {
|
|
451
|
+
"table": "users", // User table name (default: "users")
|
|
452
|
+
"key": "id", // Primary key column (default: "id")
|
|
453
|
+
"token": "user_tokens" // Session token table (default: "user_tokens")
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
**Default Values:**
|
|
459
|
+
- If `auth` is not specified, defaults are used
|
|
460
|
+
- Table: `users`
|
|
461
|
+
- Primary key: `id`
|
|
462
|
+
- Token table: `candy_auth`
|
|
463
|
+
|
|
464
|
+
### Database Schema
|
|
465
|
+
|
|
466
|
+
The users table should have been created during registration. If you need to create it manually:
|
|
467
|
+
|
|
468
|
+
```sql
|
|
469
|
+
CREATE TABLE `users` (
|
|
470
|
+
`id` INT NOT NULL AUTO_INCREMENT,
|
|
471
|
+
`email` VARCHAR(255) NOT NULL UNIQUE,
|
|
472
|
+
`username` VARCHAR(255) NULL UNIQUE,
|
|
473
|
+
`password` VARCHAR(255) NOT NULL,
|
|
474
|
+
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
475
|
+
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
476
|
+
PRIMARY KEY (`id`)
|
|
477
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**Important:**
|
|
481
|
+
- Password field must be `VARCHAR(255)` to store bcrypt hashes
|
|
482
|
+
- Email or username should have `UNIQUE` constraint
|
|
483
|
+
|
|
484
|
+
### Token Table
|
|
485
|
+
|
|
486
|
+
The token table is created automatically on first login, but you can create it manually:
|
|
487
|
+
|
|
488
|
+
```sql
|
|
489
|
+
CREATE TABLE `candy_auth` (
|
|
490
|
+
`id` INT NOT NULL AUTO_INCREMENT,
|
|
491
|
+
`user` INT NOT NULL,
|
|
492
|
+
`token_x` VARCHAR(255) NOT NULL,
|
|
493
|
+
`token_y` VARCHAR(255) NOT NULL,
|
|
494
|
+
`browser` VARCHAR(255) NOT NULL,
|
|
495
|
+
`ip` VARCHAR(255) NOT NULL,
|
|
496
|
+
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
497
|
+
`active` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
498
|
+
PRIMARY KEY (`id`)
|
|
499
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## Authentication Methods
|
|
503
|
+
|
|
504
|
+
The login form supports multiple authentication methods:
|
|
505
|
+
|
|
506
|
+
### Email + Password
|
|
507
|
+
|
|
508
|
+
```html
|
|
509
|
+
<candy:login redirect="/dashboard">
|
|
510
|
+
<candy:field name="email" type="email" placeholder="Email">
|
|
511
|
+
<candy:validate rule="required|email"/>
|
|
512
|
+
</candy:field>
|
|
513
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
514
|
+
<candy:validate rule="required"/>
|
|
515
|
+
</candy:field>
|
|
516
|
+
<candy:submit>Login</candy:submit>
|
|
517
|
+
</candy:login>
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### Username + Password
|
|
521
|
+
|
|
522
|
+
```html
|
|
523
|
+
<candy:login redirect="/dashboard">
|
|
524
|
+
<candy:field name="username" type="text" placeholder="Username">
|
|
525
|
+
<candy:validate rule="required"/>
|
|
526
|
+
</candy:field>
|
|
527
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
528
|
+
<candy:validate rule="required"/>
|
|
529
|
+
</candy:field>
|
|
530
|
+
<candy:submit>Login</candy:submit>
|
|
531
|
+
</candy:login>
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Email or Username + Password
|
|
535
|
+
|
|
536
|
+
```html
|
|
537
|
+
<candy:login redirect="/dashboard">
|
|
538
|
+
<candy:field name="identifier" type="text" placeholder="Email or Username">
|
|
539
|
+
<candy:validate rule="required"/>
|
|
540
|
+
</candy:field>
|
|
541
|
+
<candy:field name="password" type="password" placeholder="Password">
|
|
542
|
+
<candy:validate rule="required"/>
|
|
543
|
+
</candy:field>
|
|
544
|
+
<candy:submit>Login</candy:submit>
|
|
545
|
+
</candy:login>
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
## Best Practices
|
|
549
|
+
|
|
550
|
+
1. **Always use HTTPS** - Login forms should only be served over HTTPS
|
|
551
|
+
2. **Validate on both client and server** - CandyPack does this automatically
|
|
552
|
+
3. **Provide clear error messages** - Don't reveal whether email/username exists
|
|
553
|
+
4. **Add "Forgot Password" link** - Help users recover their accounts
|
|
554
|
+
5. **Consider rate limiting** - Prevent brute force attacks (implement in controller)
|
|
555
|
+
6. **Use strong password requirements** - Enforce during registration
|
|
556
|
+
7. **Test form expiration** - Forms expire after 30 minutes
|
|
557
|
+
|
|
558
|
+
## Troubleshooting
|
|
559
|
+
|
|
560
|
+
### Form Not Submitting
|
|
561
|
+
|
|
562
|
+
- Check that `config.json` has MySQL configuration
|
|
563
|
+
- Verify database table exists
|
|
564
|
+
- Check browser console for JavaScript errors
|
|
565
|
+
- Ensure CSRF token is valid
|
|
566
|
+
|
|
567
|
+
### Validation Not Working
|
|
568
|
+
|
|
569
|
+
- Ensure validation rules are spelled correctly
|
|
570
|
+
- Check that field names match between `<candy:field>` and validation
|
|
571
|
+
- Verify HTML5 validation isn't blocking submission
|
|
572
|
+
|
|
573
|
+
### Login Failing
|
|
574
|
+
|
|
575
|
+
- Verify user exists in database
|
|
576
|
+
- Check that password was hashed with bcrypt during registration
|
|
577
|
+
- Ensure auth table name in config matches your database
|
|
578
|
+
- Check that credentials match exactly (case-sensitive)
|
|
579
|
+
|
|
580
|
+
### Token Expired
|
|
581
|
+
|
|
582
|
+
- Forms expire after 30 minutes
|
|
583
|
+
- User needs to refresh the page to get a new token
|
|
584
|
+
- Consider adding a message about session expiration
|
|
585
|
+
|
|
586
|
+
### Redirect Not Working
|
|
587
|
+
|
|
588
|
+
- Ensure `redirect` attribute is set on `<candy:login>`
|
|
589
|
+
- Check that the redirect URL is valid
|
|
590
|
+
- Verify user has permission to access the redirect page
|
|
591
|
+
|
|
592
|
+
## Related Documentation
|
|
593
|
+
|
|
594
|
+
- [Candy Register Forms](04-candy-register-forms.md) - Create registration forms
|
|
595
|
+
- [Session Management](05-session-management.md) - Understanding sessions
|
|
596
|
+
- [Authentication Overview](00-authentication-overview.md) - Auth system basics
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
## ✉️ The `Mail` Service
|
|
2
|
+
|
|
3
|
+
The `Candy.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 CandyPack core.
|
|
4
|
+
|
|
5
|
+
#### How to Send an Email
|
|
6
|
+
|
|
7
|
+
`Candy.Mail.send(to, subject, htmlBody)`
|
|
8
|
+
|
|
9
|
+
* `to`: The email address of the person you're sending it to.
|
|
10
|
+
* `subject`: The subject line for your email.
|
|
11
|
+
* `htmlBody`: The main content of your email. You can even use HTML tags to make it look fancy!
|
|
12
|
+
|
|
13
|
+
Just like the database service, `send` is an `async` method, so using it with `async/await` is the way to go.
|
|
14
|
+
|
|
15
|
+
#### Example: A Simple Contact Form
|
|
16
|
+
|
|
17
|
+
Let's imagine you have a controller that handles a contact form on your website.
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
module.exports = async function (Candy) {
|
|
21
|
+
const { recipient, subject, message } = Candy.Request.post;
|
|
22
|
+
|
|
23
|
+
// It's always a good idea to check your data first!
|
|
24
|
+
if (!recipient || !subject || !message) {
|
|
25
|
+
return { error: 'Oops! You missed a required field.' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// Let's try to send the email
|
|
30
|
+
await Candy.Mail.send(recipient, subject, `<p>${message}</p>`);
|
|
31
|
+
|
|
32
|
+
// If we get here, it worked!
|
|
33
|
+
return { success: true, message: 'Email sent successfully!' };
|
|
34
|
+
} catch (error) {
|
|
35
|
+
// If something went wrong...
|
|
36
|
+
console.error('Oh no, the email failed to send:', error);
|
|
37
|
+
return { error: 'Something went wrong while trying to send the email.' };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
And that's all there is to it. You're now a master of email!
|