hazo_auth 1.6.6 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +212 -12
- package/SETUP_CHECKLIST.md +81 -1
- package/dist/app/api/hazo_auth/login/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/login/route.js +25 -0
- package/dist/app/api/hazo_auth/logout/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/logout/route.js +5 -0
- package/dist/components/layouts/email_verification/hooks/use_email_verification.d.ts.map +1 -1
- package/dist/components/layouts/email_verification/hooks/use_email_verification.js +5 -3
- package/dist/components/layouts/email_verification/index.d.ts +2 -1
- package/dist/components/layouts/email_verification/index.d.ts.map +1 -1
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts.map +1 -1
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.js +3 -1
- package/dist/components/layouts/forgot_password/index.d.ts +2 -1
- package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
- package/dist/components/layouts/login/hooks/use_login_form.d.ts.map +1 -1
- package/dist/components/layouts/login/hooks/use_login_form.js +3 -1
- package/dist/components/layouts/login/index.d.ts +2 -1
- package/dist/components/layouts/login/index.d.ts.map +1 -1
- package/dist/components/layouts/my_settings/components/profile_picture_dialog.d.ts.map +1 -1
- package/dist/components/layouts/my_settings/components/profile_picture_dialog.js +3 -1
- package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts.map +1 -1
- package/dist/components/layouts/my_settings/components/profile_picture_library_tab.js +4 -2
- package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts.map +1 -1
- package/dist/components/layouts/my_settings/hooks/use_my_settings.js +7 -5
- package/dist/components/layouts/my_settings/index.d.ts +2 -1
- package/dist/components/layouts/my_settings/index.d.ts.map +1 -1
- package/dist/components/layouts/my_settings/index.js +3 -2
- package/dist/components/layouts/register/hooks/use_register_form.d.ts.map +1 -1
- package/dist/components/layouts/register/hooks/use_register_form.js +37 -7
- package/dist/components/layouts/register/index.d.ts +2 -1
- package/dist/components/layouts/register/index.d.ts.map +1 -1
- package/dist/components/layouts/reset_password/hooks/use_reset_password_form.d.ts.map +1 -1
- package/dist/components/layouts/reset_password/hooks/use_reset_password_form.js +4 -2
- package/dist/components/layouts/reset_password/index.d.ts +2 -1
- package/dist/components/layouts/reset_password/index.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts +2 -1
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/logout_button.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/logout_button.js +3 -1
- package/dist/components/layouts/shared/components/profile_pic_menu.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/profile_pic_menu.js +8 -4
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts +2 -1
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/visual_panel.d.ts +2 -1
- package/dist/components/layouts/shared/components/visual_panel.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/visual_panel.js +2 -1
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -1
- package/dist/components/layouts/shared/hooks/use_auth_status.js +4 -2
- package/dist/components/layouts/shared/hooks/use_hazo_auth.d.ts.map +1 -1
- package/dist/components/layouts/shared/hooks/use_hazo_auth.js +4 -2
- package/dist/components/layouts/shared/index.d.ts +0 -2
- package/dist/components/layouts/shared/index.d.ts.map +1 -1
- package/dist/components/layouts/shared/index.js +2 -2
- package/dist/components/layouts/user_management/components/roles_matrix.d.ts.map +1 -1
- package/dist/components/layouts/user_management/components/roles_matrix.js +8 -6
- package/dist/components/layouts/user_management/index.d.ts.map +1 -1
- package/dist/components/layouts/user_management/index.js +15 -13
- package/dist/contexts/hazo_auth_config.d.ts +18 -0
- package/dist/contexts/hazo_auth_config.d.ts.map +1 -0
- package/dist/contexts/hazo_auth_config.js +10 -0
- package/dist/contexts/hazo_auth_provider.d.ts +73 -0
- package/dist/contexts/hazo_auth_provider.d.ts.map +1 -0
- package/dist/contexts/hazo_auth_provider.js +82 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_auth.server.js +31 -3
- package/dist/lib/auth/session_token_validator.edge.d.ts +15 -0
- package/dist/lib/auth/session_token_validator.edge.d.ts.map +1 -0
- package/dist/lib/auth/session_token_validator.edge.js +64 -0
- package/dist/lib/config/default_config.d.ts +237 -0
- package/dist/lib/config/default_config.d.ts.map +1 -0
- package/dist/lib/config/default_config.js +159 -0
- package/dist/lib/email_verification_config.server.d.ts +4 -0
- package/dist/lib/email_verification_config.server.d.ts.map +1 -1
- package/dist/lib/email_verification_config.server.js +12 -0
- package/dist/lib/forgot_password_config.server.d.ts +4 -0
- package/dist/lib/forgot_password_config.server.d.ts.map +1 -1
- package/dist/lib/forgot_password_config.server.js +12 -0
- package/dist/lib/login_config.server.d.ts +4 -0
- package/dist/lib/login_config.server.d.ts.map +1 -1
- package/dist/lib/login_config.server.js +10 -0
- package/dist/lib/password_requirements_config.server.d.ts +1 -1
- package/dist/lib/password_requirements_config.server.d.ts.map +1 -1
- package/dist/lib/password_requirements_config.server.js +8 -7
- package/dist/lib/register_config.server.d.ts +4 -0
- package/dist/lib/register_config.server.d.ts.map +1 -1
- package/dist/lib/register_config.server.js +10 -0
- package/dist/lib/reset_password_config.server.d.ts +4 -0
- package/dist/lib/reset_password_config.server.d.ts.map +1 -1
- package/dist/lib/reset_password_config.server.js +10 -0
- package/dist/lib/services/session_token_service.d.ts +27 -0
- package/dist/lib/services/session_token_service.d.ts.map +1 -0
- package/dist/lib/services/session_token_service.js +130 -0
- package/dist/page_components/forgot_password.d.ts.map +1 -1
- package/dist/page_components/forgot_password.js +14 -0
- package/dist/page_components/login.d.ts +4 -0
- package/dist/page_components/login.d.ts.map +1 -1
- package/dist/page_components/login.js +14 -0
- package/dist/page_components/register.d.ts.map +1 -1
- package/dist/page_components/register.js +14 -0
- package/dist/page_components/reset_password.d.ts.map +1 -1
- package/dist/page_components/reset_password.js +14 -0
- package/dist/page_components/verify_email.d.ts.map +1 -1
- package/dist/page_components/verify_email.js +14 -0
- package/dist/pages/forgot_password.d.ts +52 -0
- package/dist/pages/forgot_password.d.ts.map +1 -0
- package/dist/pages/forgot_password.js +41 -0
- package/dist/pages/index.d.ts +33 -0
- package/dist/pages/index.d.ts.map +1 -0
- package/dist/pages/index.js +28 -0
- package/dist/pages/login.d.ts +43 -0
- package/dist/pages/login.d.ts.map +1 -0
- package/dist/pages/login.js +45 -0
- package/dist/pages/my_settings.d.ts +54 -0
- package/dist/pages/my_settings.d.ts.map +1 -0
- package/dist/pages/my_settings.js +57 -0
- package/dist/pages/register.d.ts +44 -0
- package/dist/pages/register.d.ts.map +1 -0
- package/dist/pages/register.js +46 -0
- package/dist/pages/reset_password.d.ts +43 -0
- package/dist/pages/reset_password.d.ts.map +1 -0
- package/dist/pages/reset_password.js +42 -0
- package/dist/pages/verify_email.d.ts +52 -0
- package/dist/pages/verify_email.d.ts.map +1 -0
- package/dist/pages/verify_email.js +41 -0
- package/dist/server/middleware.d.ts +3 -0
- package/dist/server/middleware.d.ts.map +1 -0
- package/dist/server/middleware.js +5 -0
- package/dist/server_pages/forgot_password.d.ts +53 -0
- package/dist/server_pages/forgot_password.d.ts.map +1 -0
- package/dist/server_pages/forgot_password.js +40 -0
- package/dist/server_pages/forgot_password_client_wrapper.d.ts +15 -0
- package/dist/server_pages/forgot_password_client_wrapper.d.ts.map +1 -0
- package/dist/server_pages/forgot_password_client_wrapper.js +27 -0
- package/dist/server_pages/index.d.ts +13 -0
- package/dist/server_pages/index.d.ts.map +1 -0
- package/dist/server_pages/index.js +7 -0
- package/dist/server_pages/login.d.ts +43 -0
- package/dist/server_pages/login.d.ts.map +1 -0
- package/dist/server_pages/login.js +39 -0
- package/dist/server_pages/login_client_wrapper.d.ts +13 -0
- package/dist/server_pages/login_client_wrapper.d.ts.map +1 -0
- package/dist/server_pages/login_client_wrapper.js +29 -0
- package/dist/server_pages/my_settings.d.ts +53 -0
- package/dist/server_pages/my_settings.d.ts.map +1 -0
- package/dist/server_pages/my_settings.js +57 -0
- package/dist/server_pages/register.d.ts +45 -0
- package/dist/server_pages/register.d.ts.map +1 -0
- package/dist/server_pages/register.js +41 -0
- package/dist/server_pages/register_client_wrapper.d.ts +13 -0
- package/dist/server_pages/register_client_wrapper.d.ts.map +1 -0
- package/dist/server_pages/register_client_wrapper.js +27 -0
- package/dist/server_pages/reset_password.d.ts +44 -0
- package/dist/server_pages/reset_password.d.ts.map +1 -0
- package/dist/server_pages/reset_password.js +40 -0
- package/dist/server_pages/reset_password_client_wrapper.d.ts +13 -0
- package/dist/server_pages/reset_password_client_wrapper.d.ts.map +1 -0
- package/dist/server_pages/reset_password_client_wrapper.js +27 -0
- package/dist/server_pages/verify_email.d.ts +53 -0
- package/dist/server_pages/verify_email.d.ts.map +1 -0
- package/dist/server_pages/verify_email.js +40 -0
- package/dist/server_pages/verify_email_client_wrapper.d.ts +15 -0
- package/dist/server_pages/verify_email_client_wrapper.d.ts.map +1 -0
- package/dist/server_pages/verify_email_client_wrapper.js +27 -0
- package/package.json +39 -10
package/README.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
A reusable authentication UI component package powered by Next.js, TailwindCSS, and shadcn. It integrates `hazo_config` for configuration management and `hazo_connect` for data access, enabling future components to stay aligned with platform conventions.
|
|
4
4
|
|
|
5
|
+
### What's New in v2.0 🚀
|
|
6
|
+
|
|
7
|
+
**Zero-Config Server Components** - Authentication pages now work out-of-the-box with ZERO configuration required!
|
|
8
|
+
|
|
9
|
+
- ✅ **True "Drop In and Use"** - Pages initialize everything server-side, no loading state
|
|
10
|
+
- ✅ **Better Performance** - Smaller JS bundles, faster page loads, immediate rendering
|
|
11
|
+
- ✅ **Flexible API Paths** - Customize endpoints globally via `HazoAuthProvider` context
|
|
12
|
+
- ✅ **Embeddable Components** - MySettings and UserManagement adapt to any layout
|
|
13
|
+
- ✅ **Sensible Defaults** - INI files are now optional, defaults built-in
|
|
14
|
+
|
|
15
|
+
**Migrating from v1.x?** See [MIGRATION.md](./MIGRATION.md) for a complete upgrade guide.
|
|
16
|
+
|
|
17
|
+
### Also Includes (v1.6.6+)
|
|
18
|
+
|
|
19
|
+
- **JWT Session Tokens for Edge-Compatible Authentication**: Secure Edge Runtime authentication in Next.js proxy/middleware files. See [Proxy/Middleware Authentication](#proxymiddleware-authentication) for details.
|
|
20
|
+
|
|
5
21
|
## Table of Contents
|
|
6
22
|
|
|
7
23
|
- [Installation](#installation)
|
|
@@ -10,6 +26,7 @@ A reusable authentication UI component package powered by Next.js, TailwindCSS,
|
|
|
10
26
|
- [Database Setup](#database-setup)
|
|
11
27
|
- [Using Components](#using-components)
|
|
12
28
|
- [Authentication Service](#authentication-service)
|
|
29
|
+
- [Proxy/Middleware Authentication](#proxymiddleware-authentication)
|
|
13
30
|
- [Profile Picture Menu Widget](#profile-picture-menu-widget)
|
|
14
31
|
- [User Profile Service](#user-profile-service)
|
|
15
32
|
- [Local Development](#local-development)
|
|
@@ -58,25 +75,113 @@ npx hazo_auth validate # Check your setup and configuration
|
|
|
58
75
|
npx hazo_auth --help # Show all commands
|
|
59
76
|
```
|
|
60
77
|
|
|
61
|
-
### Using Zero-Config Page Components
|
|
78
|
+
### Using Zero-Config Page Components (v2.0+)
|
|
79
|
+
|
|
80
|
+
**NEW in v2.0:** All pages are now React Server Components that initialize everything on the server. No configuration, no loading state, no hassle!
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// app/login/page.tsx - That's literally it!
|
|
84
|
+
import { LoginPage } from "hazo_auth/pages/login";
|
|
85
|
+
|
|
86
|
+
export default function Page() {
|
|
87
|
+
return <LoginPage />;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**What happens behind the scenes:**
|
|
92
|
+
- ✅ Database connection initialized server-side via hazo_connect singleton
|
|
93
|
+
- ✅ Configuration loaded from hazo_auth_config.ini (or uses sensible defaults)
|
|
94
|
+
- ✅ All props automatically configured
|
|
95
|
+
- ✅ Page renders immediately - NO loading state!
|
|
96
|
+
|
|
97
|
+
**Available zero-config pages:**
|
|
98
|
+
|
|
99
|
+
| Page | Import | Description |
|
|
100
|
+
|------|--------|-------------|
|
|
101
|
+
| **LoginPage** | `hazo_auth/pages/login` | Login form with forgot password link |
|
|
102
|
+
| **RegisterPage** | `hazo_auth/pages/register` | Registration with password validation |
|
|
103
|
+
| **ForgotPasswordPage** | `hazo_auth/pages/forgot_password` | Request password reset email |
|
|
104
|
+
| **ResetPasswordPage** | `hazo_auth/pages/reset_password` | Set new password with token |
|
|
105
|
+
| **VerifyEmailPage** | `hazo_auth/pages/verify_email` | Email verification handler |
|
|
106
|
+
| **MySettingsPage** | `hazo_auth/pages/my_settings` | User profile and password change |
|
|
107
|
+
|
|
108
|
+
**Example - Complete Auth Flow:**
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// app/login/page.tsx
|
|
112
|
+
import { LoginPage } from "hazo_auth/pages/login";
|
|
113
|
+
export default function Page() {
|
|
114
|
+
return <LoginPage />;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// app/register/page.tsx
|
|
118
|
+
import { RegisterPage } from "hazo_auth/pages/register";
|
|
119
|
+
export default function Page() {
|
|
120
|
+
return <RegisterPage />;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// app/settings/page.tsx
|
|
124
|
+
import { MySettingsPage } from "hazo_auth/pages/my_settings";
|
|
125
|
+
export default function Page() {
|
|
126
|
+
return <MySettingsPage />;
|
|
127
|
+
}
|
|
128
|
+
```
|
|
62
129
|
|
|
63
|
-
|
|
130
|
+
**Customizing Visual Appearance (Optional):**
|
|
64
131
|
|
|
65
132
|
```typescript
|
|
66
|
-
//
|
|
133
|
+
// All pages accept optional visual props
|
|
67
134
|
import { LoginPage } from "hazo_auth/pages/login";
|
|
68
|
-
|
|
135
|
+
|
|
136
|
+
export default function Page() {
|
|
137
|
+
return (
|
|
138
|
+
<LoginPage
|
|
139
|
+
image_src="/custom-login-image.jpg"
|
|
140
|
+
image_alt="My company logo"
|
|
141
|
+
image_background_color="#f0f0f0"
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
69
145
|
```
|
|
70
146
|
|
|
71
|
-
|
|
72
|
-
- `LoginPage` - Login form with sensible defaults
|
|
73
|
-
- `RegisterPage` - Registration with password requirements
|
|
74
|
-
- `ForgotPasswordPage` - Password reset request
|
|
75
|
-
- `ResetPasswordPage` - Set new password
|
|
76
|
-
- `VerifyEmailPage` - Email verification
|
|
77
|
-
- `MySettingsPage` - User profile and settings
|
|
147
|
+
**Embedding MySettings in Your Dashboard:**
|
|
78
148
|
|
|
79
|
-
|
|
149
|
+
```typescript
|
|
150
|
+
// MySettings is now container-agnostic!
|
|
151
|
+
import { MySettingsPage } from "hazo_auth/pages/my_settings";
|
|
152
|
+
|
|
153
|
+
export default function DashboardPage() {
|
|
154
|
+
return (
|
|
155
|
+
<DashboardLayout>
|
|
156
|
+
<Sidebar />
|
|
157
|
+
<main className="p-6">
|
|
158
|
+
<MySettingsPage className="max-w-4xl mx-auto" />
|
|
159
|
+
</main>
|
|
160
|
+
</DashboardLayout>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Custom API Paths:**
|
|
166
|
+
|
|
167
|
+
If you use custom API endpoints (not `/api/hazo_auth/`), wrap your app with `HazoAuthProvider`:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// app/layout.tsx
|
|
171
|
+
import { HazoAuthProvider } from "hazo_auth";
|
|
172
|
+
|
|
173
|
+
export default function RootLayout({ children }) {
|
|
174
|
+
return (
|
|
175
|
+
<html>
|
|
176
|
+
<body>
|
|
177
|
+
<HazoAuthProvider apiBasePath="/api/v1/auth">
|
|
178
|
+
{children}
|
|
179
|
+
</HazoAuthProvider>
|
|
180
|
+
</body>
|
|
181
|
+
</html>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
```
|
|
80
185
|
|
|
81
186
|
### Manual Setup (Advanced)
|
|
82
187
|
|
|
@@ -108,6 +213,8 @@ import { hazo_get_auth } from "hazo_auth/lib/auth/hazo_get_auth.server";
|
|
|
108
213
|
|
|
109
214
|
## Required Dependencies
|
|
110
215
|
|
|
216
|
+
**Note:** The `jose` package is now included as a dependency for Edge-compatible JWT operations. This is automatically installed when you run `npm install hazo_auth`.
|
|
217
|
+
|
|
111
218
|
hazo_auth uses shadcn/ui components. Install the required dependencies in your project:
|
|
112
219
|
|
|
113
220
|
```bash
|
|
@@ -252,8 +359,11 @@ cp node_modules/hazo_auth/hazo_notify_config.example.ini ./hazo_notify_config.in
|
|
|
252
359
|
|
|
253
360
|
- Create a `.env.local` file in your project root
|
|
254
361
|
- Add `ZEPTOMAIL_API_KEY=your_api_key_here` (if using Zeptomail)
|
|
362
|
+
- Add `JWT_SECRET=your_secure_random_string_at_least_32_characters` (required for JWT session tokens)
|
|
255
363
|
- Add other sensitive configuration values as needed
|
|
256
364
|
|
|
365
|
+
**Note:** `JWT_SECRET` is required for JWT session token functionality (used for Edge-compatible proxy/middleware authentication). Generate a secure random string at least 32 characters long.
|
|
366
|
+
|
|
257
367
|
**Important:** The configuration files must be located in your project root directory (where `process.cwd()` points to), not inside `node_modules`. The package reads configuration from `process.cwd()` at runtime, so storing them elsewhere (including `node_modules/hazo_auth`) will break runtime access.
|
|
258
368
|
|
|
259
369
|
---
|
|
@@ -611,6 +721,9 @@ import { hazo_get_auth } from "hazo_auth/lib/auth/hazo_get_auth.server";
|
|
|
611
721
|
|
|
612
722
|
// Server utilities
|
|
613
723
|
import { ... } from "hazo_auth/server";
|
|
724
|
+
|
|
725
|
+
// Edge-compatible proxy/middleware authentication (v1.6.6+)
|
|
726
|
+
import { validate_session_cookie } from "hazo_auth/server/middleware";
|
|
614
727
|
```
|
|
615
728
|
|
|
616
729
|
**Note:** The package uses relative imports internally. Consumers should only import from the exposed entry points listed above. Do not import from internal paths like `hazo_auth/components/ui/*` - these are internal modules.
|
|
@@ -795,6 +908,93 @@ if (data.authenticated) {
|
|
|
795
908
|
|
|
796
909
|
**Note:** The `use_auth_status` hook automatically uses this endpoint and includes permissions in its return value.
|
|
797
910
|
|
|
911
|
+
### Proxy/Middleware Authentication
|
|
912
|
+
|
|
913
|
+
hazo_auth provides Edge-compatible authentication for Next.js proxy/middleware files. **Note:** Next.js is migrating from `middleware.ts` to `proxy.ts` (see [Next.js documentation](https://nextjs.org/docs/messages/middleware-to-proxy)), but the functionality remains the same.
|
|
914
|
+
|
|
915
|
+
#### Edge Runtime Limitations
|
|
916
|
+
|
|
917
|
+
Next.js proxy/middleware runs in Edge Runtime, which cannot use Node.js APIs (like SQLite). Therefore, `hazo_get_auth` cannot be used directly in proxy/middleware because it requires database access.
|
|
918
|
+
|
|
919
|
+
#### JWT Session Tokens
|
|
920
|
+
|
|
921
|
+
**New in v1.6.6+:** hazo_auth now issues JWT session tokens on login that can be validated in Edge Runtime:
|
|
922
|
+
|
|
923
|
+
- **Cookie Name:** `hazo_auth_session`
|
|
924
|
+
- **Token Type:** JWT (signed with `JWT_SECRET`)
|
|
925
|
+
- **Expiry:** 30 days (configurable)
|
|
926
|
+
- **Validation:** Signature and expiry checked without database access
|
|
927
|
+
- **Backward Compatible:** Existing `hazo_auth_user_id` and `hazo_auth_user_email` cookies still work
|
|
928
|
+
|
|
929
|
+
**Requirements:**
|
|
930
|
+
- `JWT_SECRET` environment variable must be set (see [Configuration Setup](#configuration-setup))
|
|
931
|
+
- The `jose` package is included as a dependency (Edge-compatible JWT library)
|
|
932
|
+
|
|
933
|
+
#### Using in Proxy/Middleware
|
|
934
|
+
|
|
935
|
+
**Recommended: Use JWT validation (Edge-compatible)**
|
|
936
|
+
|
|
937
|
+
```typescript
|
|
938
|
+
// proxy.ts (or middleware.ts - both work)
|
|
939
|
+
import { NextResponse } from "next/server";
|
|
940
|
+
import type { NextRequest } from "next/server";
|
|
941
|
+
import { validate_session_cookie } from "hazo_auth/server/middleware";
|
|
942
|
+
|
|
943
|
+
export async function proxy(request: NextRequest) {
|
|
944
|
+
const { pathname } = request.nextUrl;
|
|
945
|
+
|
|
946
|
+
// Protect routes
|
|
947
|
+
if (pathname.startsWith("/members")) {
|
|
948
|
+
const { valid } = await validate_session_cookie(request);
|
|
949
|
+
|
|
950
|
+
if (!valid) {
|
|
951
|
+
const login_url = new URL("/hazo_auth/login", request.url);
|
|
952
|
+
login_url.searchParams.set("redirect", pathname);
|
|
953
|
+
return NextResponse.redirect(login_url);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
return NextResponse.next();
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
export const config = {
|
|
961
|
+
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
|
|
962
|
+
};
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
**Fallback: Simple cookie check (less secure, but works)**
|
|
966
|
+
|
|
967
|
+
If JWT validation fails or you need a simpler check:
|
|
968
|
+
|
|
969
|
+
```typescript
|
|
970
|
+
// proxy.ts
|
|
971
|
+
import { NextResponse } from "next/server";
|
|
972
|
+
import type { NextRequest } from "next/server";
|
|
973
|
+
|
|
974
|
+
export async function proxy(request: NextRequest) {
|
|
975
|
+
const { pathname } = request.nextUrl;
|
|
976
|
+
|
|
977
|
+
if (pathname.startsWith("/members")) {
|
|
978
|
+
const user_id = request.cookies.get("hazo_auth_user_id")?.value;
|
|
979
|
+
const user_email = request.cookies.get("hazo_auth_user_email")?.value;
|
|
980
|
+
|
|
981
|
+
if (!user_id || !user_email) {
|
|
982
|
+
const login_url = new URL("/hazo_auth/login", request.url);
|
|
983
|
+
login_url.searchParams.set("redirect", pathname);
|
|
984
|
+
return NextResponse.redirect(login_url);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
return NextResponse.next();
|
|
989
|
+
}
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
**Important Notes:**
|
|
993
|
+
- JWT validation provides better security (signature validation, tamper detection)
|
|
994
|
+
- Simple cookie check is faster but doesn't validate token integrity
|
|
995
|
+
- Full user status checks (e.g., deactivated accounts) happen in API routes/layouts
|
|
996
|
+
- Both approaches work - JWT is recommended for production
|
|
997
|
+
|
|
798
998
|
### Server-Side Functions
|
|
799
999
|
|
|
800
1000
|
#### `hazo_get_auth` (Recommended)
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -196,6 +196,7 @@ HAZO_CONNECT_POSTGREST_API_KEY=your_postgrest_api_key_here
|
|
|
196
196
|
|
|
197
197
|
# Required for JWT authentication
|
|
198
198
|
JWT_SECRET=your_secure_random_string_at_least_32_characters
|
|
199
|
+
# Note: JWT_SECRET is required for JWT session token functionality (Edge-compatible proxy/middleware authentication)
|
|
199
200
|
```
|
|
200
201
|
|
|
201
202
|
**Generate a secure JWT secret:**
|
|
@@ -216,7 +217,7 @@ from_name = Your App Name
|
|
|
216
217
|
**Checklist:**
|
|
217
218
|
- [ ] `.env.local` file created
|
|
218
219
|
- [ ] `ZEPTOMAIL_API_KEY` set (or email will not work)
|
|
219
|
-
- [ ] `JWT_SECRET` set
|
|
220
|
+
- [ ] `JWT_SECRET` set (required for JWT session tokens - Edge-compatible proxy/middleware authentication)
|
|
220
221
|
- [ ] `from_email` configured in `hazo_notify_config.ini`
|
|
221
222
|
|
|
222
223
|
---
|
|
@@ -678,6 +679,85 @@ export default function CustomLoginPage() {
|
|
|
678
679
|
|
|
679
680
|
---
|
|
680
681
|
|
|
682
|
+
## Phase 5.1: Proxy/Middleware Setup (Optional)
|
|
683
|
+
|
|
684
|
+
**Note:** Next.js is migrating from `middleware.ts` to `proxy.ts` (see [Next.js documentation](https://nextjs.org/docs/messages/middleware-to-proxy)). The functionality remains the same - both work, but `proxy.ts` is the new convention.
|
|
685
|
+
|
|
686
|
+
If you want to protect routes at the Edge Runtime level (before pages load), create a proxy/middleware file:
|
|
687
|
+
|
|
688
|
+
### Step 5.1.1: Create Proxy File (Recommended)
|
|
689
|
+
|
|
690
|
+
Create `proxy.ts` in your project root (or `middleware.ts` - both work):
|
|
691
|
+
|
|
692
|
+
```typescript
|
|
693
|
+
// proxy.ts (or middleware.ts)
|
|
694
|
+
import { NextResponse } from "next/server";
|
|
695
|
+
import type { NextRequest } from "next/server";
|
|
696
|
+
import { validate_session_cookie } from "hazo_auth/server/middleware";
|
|
697
|
+
|
|
698
|
+
export async function proxy(request: NextRequest) {
|
|
699
|
+
const { pathname } = request.nextUrl;
|
|
700
|
+
|
|
701
|
+
// Protect your routes (e.g., /members, /dashboard, etc.)
|
|
702
|
+
if (pathname.startsWith("/members")) {
|
|
703
|
+
const { valid } = await validate_session_cookie(request);
|
|
704
|
+
|
|
705
|
+
if (!valid) {
|
|
706
|
+
const login_url = new URL("/hazo_auth/login", request.url);
|
|
707
|
+
login_url.searchParams.set("redirect", pathname);
|
|
708
|
+
return NextResponse.redirect(login_url);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
return NextResponse.next();
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
export const config = {
|
|
716
|
+
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
|
|
717
|
+
};
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
### Step 5.1.2: Simple Cookie Check (Alternative)
|
|
721
|
+
|
|
722
|
+
If you prefer a simpler approach without JWT validation:
|
|
723
|
+
|
|
724
|
+
```typescript
|
|
725
|
+
// proxy.ts
|
|
726
|
+
import { NextResponse } from "next/server";
|
|
727
|
+
import type { NextRequest } from "next/server";
|
|
728
|
+
|
|
729
|
+
export async function proxy(request: NextRequest) {
|
|
730
|
+
const { pathname } = request.nextUrl;
|
|
731
|
+
|
|
732
|
+
if (pathname.startsWith("/members")) {
|
|
733
|
+
const user_id = request.cookies.get("hazo_auth_user_id")?.value;
|
|
734
|
+
const user_email = request.cookies.get("hazo_auth_user_email")?.value;
|
|
735
|
+
|
|
736
|
+
if (!user_id || !user_email) {
|
|
737
|
+
const login_url = new URL("/hazo_auth/login", request.url);
|
|
738
|
+
login_url.searchParams.set("redirect", pathname);
|
|
739
|
+
return NextResponse.redirect(login_url);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
return NextResponse.next();
|
|
744
|
+
}
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
**Important Notes:**
|
|
748
|
+
- Proxy/middleware runs in Edge Runtime (cannot use Node.js APIs like SQLite)
|
|
749
|
+
- JWT validation (`validate_session_cookie`) provides better security
|
|
750
|
+
- Simple cookie check is faster but doesn't validate token integrity
|
|
751
|
+
- Full user validation (e.g., deactivated accounts) happens in API routes/layouts
|
|
752
|
+
- Both `proxy.ts` and `middleware.ts` work - Next.js recommends `proxy.ts`
|
|
753
|
+
|
|
754
|
+
**Checklist:**
|
|
755
|
+
- [ ] Proxy/middleware file created (optional - only if you need route protection)
|
|
756
|
+
- [ ] Protected routes configured
|
|
757
|
+
- [ ] JWT validation used (recommended) or simple cookie check
|
|
758
|
+
|
|
759
|
+
---
|
|
760
|
+
|
|
681
761
|
## Phase 6: Verification Tests
|
|
682
762
|
|
|
683
763
|
Run these tests to verify your setup is working correctly.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/login/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/login/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAUxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;;;;IAgM9C"}
|
|
@@ -7,6 +7,7 @@ import { authenticate_user } from "../../../../lib/services/login_service";
|
|
|
7
7
|
import { createCrudService } from "hazo_connect/server";
|
|
8
8
|
import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
|
|
9
9
|
import { get_login_config } from "../../../../lib/login_config.server";
|
|
10
|
+
import { create_session_token } from "../../../../lib/services/session_token_service";
|
|
10
11
|
// section: api_handler
|
|
11
12
|
export async function POST(request) {
|
|
12
13
|
const logger = create_app_logger();
|
|
@@ -124,6 +125,30 @@ export async function POST(request) {
|
|
|
124
125
|
path: "/",
|
|
125
126
|
maxAge: 60 * 60 * 24 * 30, // 30 days
|
|
126
127
|
});
|
|
128
|
+
// Create and set JWT session token (for Edge-compatible proxy/middleware)
|
|
129
|
+
try {
|
|
130
|
+
const session_token = await create_session_token(user_id, email);
|
|
131
|
+
response.cookies.set("hazo_auth_session", session_token, {
|
|
132
|
+
httpOnly: true,
|
|
133
|
+
secure: process.env.NODE_ENV === "production",
|
|
134
|
+
sameSite: "lax",
|
|
135
|
+
path: "/",
|
|
136
|
+
maxAge: 60 * 60 * 24 * 30, // 30 days
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch (token_error) {
|
|
140
|
+
// Log error but don't fail login if token creation fails
|
|
141
|
+
// Backward compatibility: existing cookies still work
|
|
142
|
+
const token_error_message = token_error instanceof Error ? token_error.message : "Unknown error";
|
|
143
|
+
logger.warn("login_session_token_creation_failed", {
|
|
144
|
+
filename: get_filename(),
|
|
145
|
+
line_number: get_line_number(),
|
|
146
|
+
user_id,
|
|
147
|
+
email,
|
|
148
|
+
error: token_error_message,
|
|
149
|
+
note: "Login succeeded but session token creation failed - using legacy cookies",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
127
152
|
return response;
|
|
128
153
|
}
|
|
129
154
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/logout/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAOxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/logout/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAOxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;IAmF9C"}
|
|
@@ -27,6 +27,11 @@ export async function POST(request) {
|
|
|
27
27
|
expires: new Date(0),
|
|
28
28
|
path: "/",
|
|
29
29
|
});
|
|
30
|
+
// Clear JWT session token cookie
|
|
31
|
+
response.cookies.set("hazo_auth_session", "", {
|
|
32
|
+
expires: new Date(0),
|
|
33
|
+
path: "/",
|
|
34
|
+
});
|
|
30
35
|
// Invalidate user cache
|
|
31
36
|
if (user_id) {
|
|
32
37
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_email_verification.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/email_verification/hooks/use_email_verification.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAgC,KAAK,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"use_email_verification.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/email_verification/hooks/use_email_verification.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAgC,KAAK,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAKxH,MAAM,MAAM,2BAA2B,GAAG,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC;AACnF,MAAM,MAAM,2BAA2B,GAAG,OAAO,CAAC,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC,GAAG;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,OAAO,GAAG,OAAO,IAAI;IAC1D,UAAU,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,2BAA2B,CAAC;IACpC,MAAM,EAAE,2BAA2B,CAAC;IACpC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,CAAC,OAAO,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9E,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,kBAAkB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACtE,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAQF,eAAO,MAAM,sBAAsB,GAAI,OAAO,EAAG,2CAI9C,0BAA0B,CAAC,OAAO,CAAC,KAAG,0BAsPxC,CAAC"}
|
|
@@ -5,12 +5,14 @@ import { useRouter, useSearchParams } from "next/navigation";
|
|
|
5
5
|
import { toast } from "sonner";
|
|
6
6
|
import { EMAIL_VERIFICATION_FIELD_IDS } from "../config/email_verification_field_config";
|
|
7
7
|
import { validateEmail } from "../../shared/utils/validation";
|
|
8
|
+
import { useHazoAuthConfig } from "../../../../contexts/hazo_auth_provider";
|
|
8
9
|
// section: helpers
|
|
9
10
|
const buildInitialValues = (initialEmail) => ({
|
|
10
11
|
[EMAIL_VERIFICATION_FIELD_IDS.EMAIL]: initialEmail || "",
|
|
11
12
|
});
|
|
12
13
|
// section: hook
|
|
13
14
|
export const use_email_verification = ({ dataClient, redirectDelay = 5, loginPath = "/hazo_auth/login", }) => {
|
|
15
|
+
const { apiBasePath } = useHazoAuthConfig();
|
|
14
16
|
const router = useRouter();
|
|
15
17
|
const searchParams = useSearchParams();
|
|
16
18
|
const token = searchParams.get("token");
|
|
@@ -48,7 +50,7 @@ export const use_email_verification = ({ dataClient, redirectDelay = 5, loginPat
|
|
|
48
50
|
setIsError(false);
|
|
49
51
|
setErrorMessage(undefined);
|
|
50
52
|
try {
|
|
51
|
-
const response = await fetch(
|
|
53
|
+
const response = await fetch(`${apiBasePath}/verify_email?token=${encodeURIComponent(token)}`, {
|
|
52
54
|
method: "GET",
|
|
53
55
|
});
|
|
54
56
|
const data = await response.json();
|
|
@@ -79,7 +81,7 @@ export const use_email_verification = ({ dataClient, redirectDelay = 5, loginPat
|
|
|
79
81
|
setErrorMessage(errorMessage);
|
|
80
82
|
// Try to extract email from error response if available
|
|
81
83
|
try {
|
|
82
|
-
const response = await fetch(
|
|
84
|
+
const response = await fetch(`${apiBasePath}/verify_email?token=${encodeURIComponent(token)}`, {
|
|
83
85
|
method: "GET",
|
|
84
86
|
});
|
|
85
87
|
const data = await response.json();
|
|
@@ -155,7 +157,7 @@ export const use_email_verification = ({ dataClient, redirectDelay = 5, loginPat
|
|
|
155
157
|
setIsSubmitting(true);
|
|
156
158
|
setErrors({});
|
|
157
159
|
try {
|
|
158
|
-
const response = await fetch(
|
|
160
|
+
const response = await fetch(`${apiBasePath}/resend_verification`, {
|
|
159
161
|
method: "POST",
|
|
160
162
|
headers: {
|
|
161
163
|
"Content-Type": "application/json",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { StaticImageData } from "next/image";
|
|
1
2
|
import { type ButtonPaletteOverrides, type LayoutFieldMapOverrides, type LayoutLabelOverrides } from "../shared/config/layout_customization";
|
|
2
3
|
import { type EmailVerificationSuccessLabels, type EmailVerificationErrorLabels } from "./config/email_verification_field_config";
|
|
3
4
|
import { type LayoutDataClient } from "../shared/data/layout_data_client";
|
|
4
5
|
export type EmailVerificationLayoutProps<TClient = unknown> = {
|
|
5
|
-
image_src: string;
|
|
6
|
+
image_src: string | StaticImageData;
|
|
6
7
|
image_alt: string;
|
|
7
8
|
image_background_color?: string;
|
|
8
9
|
field_overrides?: LayoutFieldMapOverrides;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/email_verification/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/email_verification/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAOL,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EAClC,MAAM,0CAA0C,CAAC;AAKlD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAM1E,MAAM,MAAM,4BAA4B,CAAC,OAAO,GAAG,OAAO,IAAI;IAC5D,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC,8BAA8B,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CACxC,CAAC;AASF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,OAAO,EAAE,EACzD,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,cAAc,EACd,YAAY,EACZ,cAAkB,EAClB,UAA+B,EAC/B,aAAyB,EACzB,WAAW,EACX,yBAAyB,EACzB,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,GACrB,EAAE,4BAA4B,CAAC,OAAO,CAAC,2CAkOvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_forgot_password_form.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAA6B,KAAK,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"use_forgot_password_form.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAA6B,KAAK,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAK/G,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAC7E,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,GAAG;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,OAAO,GAAG,OAAO,IAAI;IAC3D,UAAU,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,wBAAwB,CAAC;IACjC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IAChE,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAQF,eAAO,MAAM,wBAAwB,GAAI,OAAO,EAAG,iBAEhD,2BAA2B,CAAC,OAAO,CAAC,KAAG,2BA4IzC,CAAC"}
|
|
@@ -4,12 +4,14 @@ import { useCallback, useMemo, useState } from "react";
|
|
|
4
4
|
import { toast } from "sonner";
|
|
5
5
|
import { FORGOT_PASSWORD_FIELD_IDS } from "../config/forgot_password_field_config";
|
|
6
6
|
import { validateEmail } from "../../shared/utils/validation";
|
|
7
|
+
import { useHazoAuthConfig } from "../../../../contexts/hazo_auth_provider";
|
|
7
8
|
// section: helpers
|
|
8
9
|
const buildInitialValues = () => ({
|
|
9
10
|
[FORGOT_PASSWORD_FIELD_IDS.EMAIL]: "",
|
|
10
11
|
});
|
|
11
12
|
// section: hook
|
|
12
13
|
export const use_forgot_password_form = ({ dataClient, }) => {
|
|
14
|
+
const { apiBasePath } = useHazoAuthConfig();
|
|
13
15
|
const [values, setValues] = useState(buildInitialValues);
|
|
14
16
|
const [errors, setErrors] = useState({});
|
|
15
17
|
const [emailTouched, setEmailTouched] = useState(false);
|
|
@@ -71,7 +73,7 @@ export const use_forgot_password_form = ({ dataClient, }) => {
|
|
|
71
73
|
setIsSubmitting(true);
|
|
72
74
|
setErrors({});
|
|
73
75
|
try {
|
|
74
|
-
const response = await fetch(
|
|
76
|
+
const response = await fetch(`${apiBasePath}/forgot_password`, {
|
|
75
77
|
method: "POST",
|
|
76
78
|
headers: {
|
|
77
79
|
"Content-Type": "application/json",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { StaticImageData } from "next/image";
|
|
1
2
|
import { type ButtonPaletteOverrides, type LayoutFieldMapOverrides, type LayoutLabelOverrides } from "../shared/config/layout_customization";
|
|
2
3
|
import { type LayoutDataClient } from "../shared/data/layout_data_client";
|
|
3
4
|
export type ForgotPasswordLayoutProps<TClient = unknown> = {
|
|
4
|
-
image_src: string;
|
|
5
|
+
image_src: string | StaticImageData;
|
|
5
6
|
image_alt: string;
|
|
6
7
|
image_background_color?: string;
|
|
7
8
|
field_overrides?: LayoutFieldMapOverrides;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/forgot_password/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/forgot_password/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMlD,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAI1E,MAAM,MAAM,yBAAyB,CAAC,OAAO,GAAG,OAAO,IAAI;IACzD,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AASF,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,OAAO,EAAE,EACtD,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,WAAW,EACX,YAAiC,EACjC,aAAyB,EACzB,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,GACrB,EAAE,yBAAyB,CAAC,OAAO,CAAC,2CA+GpC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_login_form.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/login/hooks/use_login_form.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"use_login_form.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/login/hooks/use_login_form.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAOlF,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAC3D,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;AACpE,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,OAAO,GAAG,OAAO,IAAI;IAClD,UAAU,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QACjE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,kBAAkB,EAAE,uBAAuB,CAAC;IAC5C,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClE,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,wBAAwB,EAAE,MAAM,IAAI,CAAC;IACrC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IAChE,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAkBF,eAAO,MAAM,cAAc,GAAI,OAAO,EAAG,oEAMtC,kBAAkB,CAAC,OAAO,CAAC,KAAG,kBA2NhC,CAAC"}
|
|
@@ -6,6 +6,7 @@ import { LOGIN_FIELD_IDS } from "../config/login_field_config";
|
|
|
6
6
|
import { validateEmail } from "../../shared/utils/validation";
|
|
7
7
|
import { get_client_ip } from "../../shared/utils/ip_address";
|
|
8
8
|
import { trigger_auth_status_refresh } from "../../shared/hooks/use_auth_status";
|
|
9
|
+
import { useHazoAuthConfig } from "../../../../contexts/hazo_auth_provider";
|
|
9
10
|
// section: helpers
|
|
10
11
|
const buildInitialValues = () => ({
|
|
11
12
|
[LOGIN_FIELD_IDS.EMAIL]: "",
|
|
@@ -21,6 +22,7 @@ const get_line_number = () => {
|
|
|
21
22
|
// section: hook
|
|
22
23
|
export const use_login_form = ({ dataClient, logger, redirectRoute, successMessage = "Successfully logged in", urlOnLogon, }) => {
|
|
23
24
|
const router = useRouter();
|
|
25
|
+
const { apiBasePath } = useHazoAuthConfig();
|
|
24
26
|
const [values, setValues] = useState(buildInitialValues);
|
|
25
27
|
const [errors, setErrors] = useState({});
|
|
26
28
|
const [passwordVisibility, setPasswordVisibility] = useState({
|
|
@@ -110,7 +112,7 @@ export const use_login_form = ({ dataClient, logger, redirectRoute, successMessa
|
|
|
110
112
|
const currentIp = clientIp === "unknown" ? await get_client_ip() : clientIp;
|
|
111
113
|
setClientIp(currentIp);
|
|
112
114
|
// Attempt login via API route
|
|
113
|
-
const response = await fetch(
|
|
115
|
+
const response = await fetch(`${apiBasePath}/login`, {
|
|
114
116
|
method: "POST",
|
|
115
117
|
headers: {
|
|
116
118
|
"Content-Type": "application/json",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { StaticImageData } from "next/image";
|
|
1
2
|
import { type ButtonPaletteOverrides, type LayoutFieldMapOverrides, type LayoutLabelOverrides } from "../shared/config/layout_customization";
|
|
2
3
|
import { type LayoutDataClient } from "../shared/data/layout_data_client";
|
|
3
4
|
export type LoginLayoutProps<TClient = unknown> = {
|
|
4
|
-
image_src: string;
|
|
5
|
+
image_src: string | StaticImageData;
|
|
5
6
|
image_alt: string;
|
|
6
7
|
image_background_color?: string;
|
|
7
8
|
field_overrides?: LayoutFieldMapOverrides;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/login/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/login/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AASlD,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,MAAM,MAAM,gBAAgB,CAAC,OAAO,GAAG,OAAO,IAAI;IAChD,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QACjE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAUF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,OAAO,EAAE,EAC5C,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,WAAW,EACX,MAAM,EACN,aAAa,EACb,cAAyC,EACzC,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,oBAAmD,EACnD,qBAA0C,EAC1C,mBAA2C,EAC3C,oBAAuC,EACvC,UAAU,GACX,EAAE,gBAAgB,CAAC,OAAO,CAAC,2CAiK3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile_picture_dialog.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/my_settings/components/profile_picture_dialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"profile_picture_dialog.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/my_settings/components/profile_picture_dialog.tsx"],"names":[],"mappings":"AAuBA,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,CAAC,iBAAiB,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvG,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE;QACR,6BAA6B,EAAE,MAAM,CAAC;QACtC,sBAAsB,EAAE,MAAM,CAAC;QAC/B,2BAA2B,EAAE,MAAM,CAAC;QACpC,uBAAuB,EAAE,MAAM,CAAC;KACjC,CAAC;IACF,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;QAClC,uBAAuB,EAAE,MAAM,CAAC;QAChC,0BAA0B,EAAE,MAAM,CAAC;QACnC,0BAA0B,EAAE,MAAM,CAAC;QACnC,+BAA+B,EAAE,MAAM,CAAC;QACxC,4BAA4B,EAAE,MAAM,CAAC;KACtC,CAAC;IACF,SAAS,EAAE;QACT,wBAAwB,EAAE,MAAM,EAAE,CAAC;QACnC,wBAAwB,EAAE,MAAM,EAAE,CAAC;KACpC,CAAC;CACH,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,eAAwB,EACxB,iBAA4B,EAC5B,QAAgB,EAChB,QAAQ,EACR,OAAO,EACP,SAAS,GACV,EAAE,yBAAyB,2CAgT3B"}
|