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.
Files changed (213) hide show
  1. package/.editorconfig +21 -0
  2. package/.github/workflows/auto-pr-description.yml +49 -0
  3. package/.github/workflows/release.yml +32 -0
  4. package/.github/workflows/test-coverage.yml +58 -0
  5. package/.husky/pre-commit +2 -0
  6. package/.kiro/steering/code-style.md +56 -0
  7. package/.kiro/steering/product.md +20 -0
  8. package/.kiro/steering/structure.md +77 -0
  9. package/.kiro/steering/tech.md +87 -0
  10. package/.prettierrc +10 -0
  11. package/.releaserc.js +134 -0
  12. package/AGENTS.md +84 -0
  13. package/CHANGELOG.md +181 -0
  14. package/CODE_OF_CONDUCT.md +83 -0
  15. package/CONTRIBUTING.md +63 -0
  16. package/LICENSE +661 -0
  17. package/README.md +57 -0
  18. package/SECURITY.md +26 -0
  19. package/bin/candy +10 -0
  20. package/bin/candypack +10 -0
  21. package/cli/index.js +3 -0
  22. package/cli/src/Cli.js +348 -0
  23. package/cli/src/Connector.js +93 -0
  24. package/cli/src/Monitor.js +416 -0
  25. package/core/Candy.js +87 -0
  26. package/core/Commands.js +239 -0
  27. package/core/Config.js +1094 -0
  28. package/core/Lang.js +52 -0
  29. package/core/Log.js +43 -0
  30. package/core/Process.js +26 -0
  31. package/docs/backend/01-overview/01-whats-in-the-candy-box.md +9 -0
  32. package/docs/backend/01-overview/02-super-handy-helper-functions.md +9 -0
  33. package/docs/backend/01-overview/03-development-server.md +79 -0
  34. package/docs/backend/02-structure/01-typical-project-layout.md +39 -0
  35. package/docs/backend/03-config/00-configuration-overview.md +214 -0
  36. package/docs/backend/03-config/01-database-connection.md +60 -0
  37. package/docs/backend/03-config/02-static-route-mapping-optional.md +20 -0
  38. package/docs/backend/03-config/03-request-timeout.md +11 -0
  39. package/docs/backend/03-config/04-environment-variables.md +227 -0
  40. package/docs/backend/03-config/05-early-hints.md +352 -0
  41. package/docs/backend/04-routing/01-basic-page-routes.md +28 -0
  42. package/docs/backend/04-routing/02-controller-less-view-routes.md +43 -0
  43. package/docs/backend/04-routing/03-api-and-data-routes.md +20 -0
  44. package/docs/backend/04-routing/04-authentication-aware-routes.md +48 -0
  45. package/docs/backend/04-routing/05-advanced-routing.md +14 -0
  46. package/docs/backend/04-routing/06-error-pages.md +101 -0
  47. package/docs/backend/04-routing/07-cron-jobs.md +149 -0
  48. package/docs/backend/05-controllers/01-how-to-build-a-controller.md +17 -0
  49. package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +20 -0
  50. package/docs/backend/05-controllers/03-controller-classes.md +93 -0
  51. package/docs/backend/05-forms/01-custom-forms.md +395 -0
  52. package/docs/backend/05-forms/02-automatic-database-insert.md +297 -0
  53. package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +96 -0
  54. package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +40 -0
  55. package/docs/backend/07-views/01-the-view-directory.md +73 -0
  56. package/docs/backend/07-views/02-rendering-a-view.md +179 -0
  57. package/docs/backend/07-views/03-template-syntax.md +181 -0
  58. package/docs/backend/07-views/03-variables.md +328 -0
  59. package/docs/backend/07-views/04-request-data.md +231 -0
  60. package/docs/backend/07-views/05-conditionals.md +290 -0
  61. package/docs/backend/07-views/06-loops.md +353 -0
  62. package/docs/backend/07-views/07-translations.md +358 -0
  63. package/docs/backend/07-views/08-backend-javascript.md +398 -0
  64. package/docs/backend/07-views/09-comments.md +297 -0
  65. package/docs/backend/08-database/01-database-connection.md +99 -0
  66. package/docs/backend/08-database/02-using-mysql.md +322 -0
  67. package/docs/backend/09-validation/01-the-validator-service.md +424 -0
  68. package/docs/backend/10-authentication/01-user-logins-with-authjs.md +53 -0
  69. package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +55 -0
  70. package/docs/backend/10-authentication/03-register.md +134 -0
  71. package/docs/backend/10-authentication/04-candy-register-forms.md +676 -0
  72. package/docs/backend/10-authentication/05-session-management.md +159 -0
  73. package/docs/backend/10-authentication/06-candy-login-forms.md +596 -0
  74. package/docs/backend/11-mail/01-the-mail-service.md +42 -0
  75. package/docs/backend/12-streaming/01-streaming-overview.md +300 -0
  76. package/docs/backend/13-utilities/01-candy-var.md +504 -0
  77. package/docs/frontend/01-overview/01-introduction.md +146 -0
  78. package/docs/frontend/02-ajax-navigation/01-quick-start.md +608 -0
  79. package/docs/frontend/02-ajax-navigation/02-configuration.md +370 -0
  80. package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +519 -0
  81. package/docs/frontend/03-forms/01-form-handling.md +420 -0
  82. package/docs/frontend/04-api-requests/01-get-post.md +443 -0
  83. package/docs/frontend/05-streaming/01-client-streaming.md +163 -0
  84. package/docs/index.json +452 -0
  85. package/docs/server/01-installation/01-quick-install.md +19 -0
  86. package/docs/server/01-installation/02-manual-installation-via-npm.md +9 -0
  87. package/docs/server/02-get-started/01-core-concepts.md +7 -0
  88. package/docs/server/02-get-started/02-basic-commands.md +57 -0
  89. package/docs/server/02-get-started/03-cli-reference.md +276 -0
  90. package/docs/server/02-get-started/04-cli-quick-reference.md +102 -0
  91. package/docs/server/03-service/01-start-a-new-service.md +57 -0
  92. package/docs/server/03-service/02-delete-a-service.md +48 -0
  93. package/docs/server/04-web/01-create-a-website.md +36 -0
  94. package/docs/server/04-web/02-list-websites.md +9 -0
  95. package/docs/server/04-web/03-delete-a-website.md +29 -0
  96. package/docs/server/05-subdomain/01-create-a-subdomain.md +32 -0
  97. package/docs/server/05-subdomain/02-list-subdomains.md +33 -0
  98. package/docs/server/05-subdomain/03-delete-a-subdomain.md +41 -0
  99. package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +34 -0
  100. package/docs/server/07-mail/01-create-a-mail-account.md +23 -0
  101. package/docs/server/07-mail/02-delete-a-mail-account.md +20 -0
  102. package/docs/server/07-mail/03-list-mail-accounts.md +20 -0
  103. package/docs/server/07-mail/04-change-account-password.md +23 -0
  104. package/eslint.config.mjs +120 -0
  105. package/framework/index.js +4 -0
  106. package/framework/src/Auth.js +309 -0
  107. package/framework/src/Candy.js +81 -0
  108. package/framework/src/Config.js +79 -0
  109. package/framework/src/Env.js +60 -0
  110. package/framework/src/Lang.js +57 -0
  111. package/framework/src/Mail.js +83 -0
  112. package/framework/src/Mysql.js +575 -0
  113. package/framework/src/Request.js +301 -0
  114. package/framework/src/Route/Cron.js +128 -0
  115. package/framework/src/Route/Internal.js +439 -0
  116. package/framework/src/Route.js +455 -0
  117. package/framework/src/Server.js +15 -0
  118. package/framework/src/Stream.js +163 -0
  119. package/framework/src/Token.js +37 -0
  120. package/framework/src/Validator.js +271 -0
  121. package/framework/src/Var.js +211 -0
  122. package/framework/src/View/EarlyHints.js +190 -0
  123. package/framework/src/View/Form.js +600 -0
  124. package/framework/src/View.js +513 -0
  125. package/framework/web/candy.js +838 -0
  126. package/jest.config.js +22 -0
  127. package/locale/de-DE.json +80 -0
  128. package/locale/en-US.json +79 -0
  129. package/locale/es-ES.json +80 -0
  130. package/locale/fr-FR.json +80 -0
  131. package/locale/pt-BR.json +80 -0
  132. package/locale/ru-RU.json +80 -0
  133. package/locale/tr-TR.json +85 -0
  134. package/locale/zh-CN.json +80 -0
  135. package/package.json +86 -0
  136. package/server/index.js +5 -0
  137. package/server/src/Api.js +88 -0
  138. package/server/src/DNS.js +940 -0
  139. package/server/src/Hub.js +535 -0
  140. package/server/src/Mail.js +571 -0
  141. package/server/src/SSL.js +180 -0
  142. package/server/src/Server.js +27 -0
  143. package/server/src/Service.js +248 -0
  144. package/server/src/Subdomain.js +64 -0
  145. package/server/src/Web/Firewall.js +170 -0
  146. package/server/src/Web/Proxy.js +134 -0
  147. package/server/src/Web.js +451 -0
  148. package/server/src/mail/imap.js +1091 -0
  149. package/server/src/mail/server.js +32 -0
  150. package/server/src/mail/smtp.js +786 -0
  151. package/test/cli/Cli.test.js +36 -0
  152. package/test/core/Candy.test.js +234 -0
  153. package/test/core/Commands.test.js +538 -0
  154. package/test/core/Config.test.js +1435 -0
  155. package/test/core/Lang.test.js +250 -0
  156. package/test/core/Process.test.js +156 -0
  157. package/test/framework/Route.test.js +239 -0
  158. package/test/framework/View/EarlyHints.test.js +282 -0
  159. package/test/scripts/check-coverage.js +132 -0
  160. package/test/server/Api.test.js +647 -0
  161. package/test/server/Client.test.js +338 -0
  162. package/test/server/DNS.test.js +2050 -0
  163. package/test/server/DNS.test.js.bak +2084 -0
  164. package/test/server/Log.test.js +73 -0
  165. package/test/server/Mail.account.test_.js +460 -0
  166. package/test/server/Mail.init.test_.js +411 -0
  167. package/test/server/Mail.test_.js +1340 -0
  168. package/test/server/SSL.test_.js +1491 -0
  169. package/test/server/Server.test.js +765 -0
  170. package/test/server/Service.test_.js +1127 -0
  171. package/test/server/Subdomain.test.js +440 -0
  172. package/test/server/Web/Firewall.test.js +175 -0
  173. package/test/server/Web.test_.js +1562 -0
  174. package/test/server/__mocks__/acme-client.js +17 -0
  175. package/test/server/__mocks__/bcrypt.js +50 -0
  176. package/test/server/__mocks__/child_process.js +389 -0
  177. package/test/server/__mocks__/crypto.js +432 -0
  178. package/test/server/__mocks__/fs.js +450 -0
  179. package/test/server/__mocks__/globalCandy.js +227 -0
  180. package/test/server/__mocks__/http-proxy.js +105 -0
  181. package/test/server/__mocks__/http.js +575 -0
  182. package/test/server/__mocks__/https.js +272 -0
  183. package/test/server/__mocks__/index.js +249 -0
  184. package/test/server/__mocks__/mail/server.js +100 -0
  185. package/test/server/__mocks__/mail/smtp.js +31 -0
  186. package/test/server/__mocks__/mailparser.js +81 -0
  187. package/test/server/__mocks__/net.js +369 -0
  188. package/test/server/__mocks__/node-forge.js +328 -0
  189. package/test/server/__mocks__/os.js +320 -0
  190. package/test/server/__mocks__/path.js +291 -0
  191. package/test/server/__mocks__/selfsigned.js +8 -0
  192. package/test/server/__mocks__/server/src/mail/server.js +100 -0
  193. package/test/server/__mocks__/server/src/mail/smtp.js +31 -0
  194. package/test/server/__mocks__/smtp-server.js +106 -0
  195. package/test/server/__mocks__/sqlite3.js +394 -0
  196. package/test/server/__mocks__/testFactories.js +299 -0
  197. package/test/server/__mocks__/testHelpers.js +363 -0
  198. package/test/server/__mocks__/tls.js +229 -0
  199. package/watchdog/index.js +3 -0
  200. package/watchdog/src/Watchdog.js +156 -0
  201. package/web/config.json +5 -0
  202. package/web/controller/page/about.js +27 -0
  203. package/web/controller/page/index.js +34 -0
  204. package/web/package.json +18 -0
  205. package/web/public/assets/css/style.css +1835 -0
  206. package/web/public/assets/js/app.js +96 -0
  207. package/web/route/www.js +19 -0
  208. package/web/skeleton/main.html +22 -0
  209. package/web/view/content/about.html +65 -0
  210. package/web/view/content/home.html +205 -0
  211. package/web/view/footer/main.html +11 -0
  212. package/web/view/head/main.html +5 -0
  213. 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!