@orieljs/framework 0.1.0-alpha.1 → 0.1.0-alpha.10

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 (87) hide show
  1. package/NOTICE +7 -0
  2. package/README.md +10 -1
  3. package/TRADEMARKS.md +33 -0
  4. package/dist/chunk-7ZQZYDOC.js +3253 -0
  5. package/dist/chunk-7ZQZYDOC.js.map +1 -0
  6. package/dist/{chunk-K6MAA3RM.js → chunk-GVNLZZTN.js} +7 -1
  7. package/dist/chunk-GVNLZZTN.js.map +1 -0
  8. package/dist/chunk-OXAATQA6.js +8433 -0
  9. package/dist/chunk-OXAATQA6.js.map +1 -0
  10. package/dist/{chunk-WI7E7Q46.js → chunk-VOYW3R5J.js} +8 -4
  11. package/dist/chunk-VOYW3R5J.js.map +1 -0
  12. package/dist/contracts.d.ts +841 -168
  13. package/dist/contracts.js +7 -1
  14. package/dist/index.d-WQpfdIbG.d.ts +630 -0
  15. package/dist/index.d.ts +2916 -5178
  16. package/dist/index.js +7357 -2609
  17. package/dist/index.js.map +1 -1
  18. package/dist/{jsx-runtime-B8J6xq-7.d.ts → jsx-runtime-6um4Mwfb.d.ts} +99 -149
  19. package/dist/jsx-runtime.d.ts +3 -1
  20. package/dist/jsx-runtime.js +3 -3
  21. package/dist/testing-CKwfWJGn.d.ts +1586 -0
  22. package/dist/testing.d.ts +3 -1408
  23. package/dist/testing.js +29 -5
  24. package/docs/authentication.md +487 -0
  25. package/docs/authorization.md +435 -0
  26. package/docs/cache.md +647 -0
  27. package/docs/collections.md +2270 -0
  28. package/docs/configuration.md +334 -0
  29. package/docs/console.md +652 -0
  30. package/docs/container.md +430 -0
  31. package/docs/controllers.md +406 -0
  32. package/docs/csrf.md +126 -0
  33. package/docs/database-testing.md +144 -0
  34. package/docs/database.md +236 -0
  35. package/docs/deployment.md +276 -0
  36. package/docs/eloquent-collections.md +218 -0
  37. package/docs/eloquent-factories.md +255 -0
  38. package/docs/eloquent-mutators.md +254 -0
  39. package/docs/eloquent-observers.md +145 -0
  40. package/docs/eloquent-relationships.md +557 -0
  41. package/docs/eloquent.md +494 -0
  42. package/docs/encryption.md +104 -0
  43. package/docs/errors.md +318 -0
  44. package/docs/events.md +336 -0
  45. package/docs/facades.md +278 -0
  46. package/docs/hashing.md +118 -0
  47. package/docs/helpers.md +1281 -0
  48. package/docs/http-tests.md +386 -0
  49. package/docs/inertia.md +485 -0
  50. package/docs/installation.md +209 -0
  51. package/docs/lifecycle.md +234 -0
  52. package/docs/live-tests.md +226 -0
  53. package/docs/live.md +910 -0
  54. package/docs/logging.md +255 -0
  55. package/docs/mail.md +619 -0
  56. package/docs/middleware.md +384 -0
  57. package/docs/migrations.md +416 -0
  58. package/docs/mocking.md +264 -0
  59. package/docs/navigation.json +273 -0
  60. package/docs/notifications.md +225 -0
  61. package/docs/pagination.md +247 -0
  62. package/docs/passwords.md +207 -0
  63. package/docs/providers.md +187 -0
  64. package/docs/queries.md +600 -0
  65. package/docs/queues.md +330 -0
  66. package/docs/requests.md +533 -0
  67. package/docs/responses.md +444 -0
  68. package/docs/routing.md +738 -0
  69. package/docs/scheduling.md +277 -0
  70. package/docs/seeding.md +122 -0
  71. package/docs/session.md +409 -0
  72. package/docs/starter-kits.md +396 -0
  73. package/docs/storage.md +192 -0
  74. package/docs/structure.md +264 -0
  75. package/docs/testing.md +165 -0
  76. package/docs/time-travel.md +138 -0
  77. package/docs/validation.md +1792 -0
  78. package/docs/verification.md +152 -0
  79. package/docs/views.md +566 -0
  80. package/docs/vite.md +322 -0
  81. package/package.json +35 -30
  82. package/dist/chunk-AI2RFMBT.js +0 -745
  83. package/dist/chunk-AI2RFMBT.js.map +0 -1
  84. package/dist/chunk-BZPCRKFQ.js +0 -2941
  85. package/dist/chunk-BZPCRKFQ.js.map +0 -1
  86. package/dist/chunk-K6MAA3RM.js.map +0 -1
  87. package/dist/chunk-WI7E7Q46.js.map +0 -1
@@ -0,0 +1,152 @@
1
+ # Email verification
2
+
3
+ Ask new users to confirm their email address with a signed link before they reach the parts of your app that need it.
4
+ The starter kits with pages do this already.
5
+
6
+ ## Introduction
7
+
8
+ When a user registers, Oriel mails them a link. Opening it, while signed in, marks their address as verified, and the
9
+ `verified` middleware keeps unverified users out of the routes you give it. The kits with pages use it for the
10
+ dashboard (see [Email verification](starter-kits.md#email-verification) in the kits).
11
+
12
+ ### Model preparation
13
+
14
+ A model built on `AuthenticatableModel`, as a new app's `User` is, can verify its email:
15
+
16
+ - `hasVerifiedEmail()` tells you whether `email_verified_at` is set;
17
+ - `markEmailAsVerified()` sets it to now and saves the model;
18
+ - `getEmailForVerification()` returns the `email` attribute;
19
+ - `sendEmailVerificationNotification()` mails the user the verification link.
20
+
21
+ > [!NOTE]
22
+ > In Laravel, only a `User` model that implements `MustVerifyEmail` gets the mail and is held back by `verified`, and
23
+ > a new Laravel app's doesn't. In Oriel, every user model built on `AuthenticatableModel` can verify its email, so a
24
+ > new user always gets the mail. Take `verified` off a route to let unverified users in.
25
+
26
+ ### Database preparation
27
+
28
+ The `users` table needs an `email_verified_at` column, a nullable timestamp, which a new app's first migration has.
29
+
30
+ ## Routing
31
+
32
+ Verification takes three routes, which the Inertia kits define in `routes/auth.ts`, behind the `auth` middleware: the
33
+ notice that asks the user to verify, the link's handler, and a route that sends the link again.
34
+
35
+ ### The email verification notice
36
+
37
+ The notice is the page a user sees when `verified` stops them. It is the `verification.notice` route,
38
+ `/verify-email` in the kits:
39
+
40
+ ```ts title="routes/auth.ts"
41
+ import { inertia, Route } from '@orieljs/framework'
42
+
43
+ Route.middleware('auth').group(() => {
44
+ Route.get('verify-email', () => inertia('Auth/VerifyEmail')).name('verification.notice')
45
+ })
46
+ ```
47
+
48
+ The kits' notice sends a user who has verified on to the dashboard, and shows a "Resend verification email" button.
49
+
50
+ ### The email verification handler
51
+
52
+ The link in the mail opens the `verification.verify` route, `/verify-email/{id}/{hash}`: the user's id, and the
53
+ SHA-1 of their email address. The link is signed, and works for 60 minutes. Its route checks the signature with the
54
+ `signed` middleware, and `EmailVerificationRequest` checks the `id` and `hash` against the signed-in user:
55
+
56
+ ```ts title="routes/auth.ts"
57
+ import { EmailVerificationRequest, redirect, Route } from '@orieljs/framework'
58
+
59
+ Route.get('verify-email/{id}/{hash}', async () => {
60
+ await EmailVerificationRequest.validate()
61
+ await new EmailVerificationRequest().fulfill()
62
+
63
+ return redirect().intended('/dashboard')
64
+ })
65
+ .middleware(['auth', 'signed', 'throttle:6,1'])
66
+ .name('verification.verify')
67
+ ```
68
+
69
+ `validate()` answers 403 when the link is for another user. `fulfill()` marks the email as verified and dispatches
70
+ the `Verified` event, unless it was verified already. A link opened after it expired, or changed, gets a 403 from
71
+ `signed`. The user must be signed in, so a user who opens the link in another browser signs in first, and is then sent
72
+ back to it.
73
+
74
+ The kits' handler is `VerifyEmailController`, which does the same and redirects to the dashboard with `?verified=1`.
75
+
76
+ ### Resending the verification email
77
+
78
+ A user who lost the mail can ask for it again: the kits' `verification.send` route sends it, at most six times a
79
+ minute:
80
+
81
+ ```ts title="routes/auth.ts"
82
+ import { back, request, Route } from '@orieljs/framework'
83
+ import type { User } from '../app/Models/User'
84
+
85
+ Route.post('email/verification-notification', async () => {
86
+ const user = (await request().user<User>())!
87
+
88
+ await user.sendEmailVerificationNotification()
89
+
90
+ return back().with('status', 'verification-link-sent')
91
+ })
92
+ .middleware(['auth', 'throttle:6,1'])
93
+ .name('verification.send')
94
+ ```
95
+
96
+ In the Live kit, the `VerifyEmail` component's action sends it, with no rate limit of its own.
97
+
98
+ ### Protecting routes
99
+
100
+ The `verified` middleware lets only verified users through:
101
+
102
+ ```ts title="routes/web.ts"
103
+ import { Route, view } from '@orieljs/framework'
104
+
105
+ Route.get('profile', () => view('profile')).middleware(['auth', 'verified'])
106
+ ```
107
+
108
+ An unverified user is redirected to the `verification.notice` route, and to the page they wanted once they have
109
+ verified. A request that wants JSON gets a 403, "Your email address is not verified.", instead. `verified:<route>`
110
+ redirects to another named route, and with no `verification.notice` route the redirect goes to `/email/verify`. A
111
+ guest gets the same redirect, so put `auth` first, as above.
112
+
113
+ ## Customization
114
+
115
+ #### Verification email customization
116
+
117
+ The mail is the `VerifyEmail` notification's: "Verify Email Address", a line asking the user to click the button, the
118
+ button, and a closing line. It is sent in the styled template of [mail notifications](notifications.md), with a
119
+ plain-text part. `VerifyEmail.toMailUsing()` builds the mail yourself, in a service provider's `boot()`. Its function
120
+ receives the user and the signed link:
121
+
122
+ ```ts title="app/Providers/AppServiceProvider.ts"
123
+ import { MailMessage, ServiceProvider, VerifyEmail } from '@orieljs/framework'
124
+
125
+ export class AppServiceProvider extends ServiceProvider {
126
+ override boot(): void {
127
+ VerifyEmail.toMailUsing((notifiable, url) =>
128
+ new MailMessage()
129
+ .subject('Verify Email Address')
130
+ .line('Click the button below to verify your email address.')
131
+ .action('Verify Email Address', url),
132
+ )
133
+ }
134
+ }
135
+ ```
136
+
137
+ `VerifyEmail.createUrlUsing()` builds the link instead, for example for a client app on another domain, and
138
+ `sendEmailVerificationUsing()` replaces the whole sending, with a function that receives the user.
139
+
140
+ The link works for `auth.verification.expire` minutes, 60 unless your `config/auth.ts` sets it:
141
+
142
+ ```ts
143
+ const auth = {
144
+ verification: { expire: 120 },
145
+ }
146
+ ```
147
+
148
+ ## Events
149
+
150
+ `Registered`, which the kits dispatch when a user signs up, sends the verification mail: Oriel listens for it with
151
+ `SendEmailVerificationNotification`, which mails a user who hasn't verified. `fulfill()` and the kits' handler
152
+ dispatch `Verified` once an address is verified. Listen for either, as for any [event](events.md).