hazo_auth 6.1.1 → 7.0.2
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 +65 -167
- package/SETUP_CHECKLIST.md +28 -100
- package/cli-src/cli/generate.ts +1 -10
- package/cli-src/cli/validate.ts +0 -4
- package/cli-src/lib/auth/auth_types.ts +12 -21
- package/cli-src/lib/auth/hazo_get_tenant_auth.server.ts +24 -25
- package/cli-src/lib/auth/index.ts +2 -2
- package/cli-src/lib/auth/nextauth_config.ts +61 -1
- package/cli-src/lib/auth/with_auth.server.ts +15 -15
- package/cli-src/lib/config/default_config.ts +8 -0
- package/cli-src/lib/cookies_config.server.ts +1 -1
- package/cli-src/lib/login_config.server.ts +2 -18
- package/cli-src/lib/oauth_config.server.ts +32 -0
- package/cli-src/lib/register_config.server.ts +4 -0
- package/cli-src/lib/services/email_template_manifest.ts +0 -17
- package/cli-src/lib/services/index.ts +2 -8
- package/cli-src/lib/services/oauth_service.ts +143 -0
- package/cli-src/lib/services/otp_service.ts +7 -2
- package/cli-src/lib/services/session_token_service.ts +0 -2
- package/config/hazo_auth_config.example.ini +0 -38
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +1 -10
- package/dist/cli/validate.d.ts.map +1 -1
- package/dist/cli/validate.js +0 -4
- package/dist/client.d.ts +0 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +0 -1
- package/dist/components/layouts/login/index.d.ts +5 -7
- package/dist/components/layouts/login/index.d.ts.map +1 -1
- package/dist/components/layouts/login/index.js +5 -2
- package/dist/components/layouts/otp/index.d.ts +12 -1
- package/dist/components/layouts/otp/index.d.ts.map +1 -1
- package/dist/components/layouts/otp/index.js +4 -2
- package/dist/components/layouts/register/index.d.ts +4 -0
- package/dist/components/layouts/register/index.d.ts.map +1 -1
- package/dist/components/layouts/register/index.js +4 -1
- package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts +21 -0
- package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/facebook_sign_in_button.js +47 -0
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +3 -8
- package/dist/components/layouts/shared/index.d.ts +2 -0
- package/dist/components/layouts/shared/index.d.ts.map +1 -1
- package/dist/components/layouts/shared/index.js +1 -0
- package/dist/components/layouts/user_management/index.d.ts.map +1 -1
- package/dist/components/layouts/user_management/index.js +39 -2
- package/dist/consent/consent_state.d.ts +18 -0
- package/dist/consent/consent_state.d.ts.map +1 -0
- package/dist/consent/consent_state.js +29 -0
- package/dist/consent/cookie_consent_banner.d.ts +11 -0
- package/dist/consent/cookie_consent_banner.d.ts.map +1 -0
- package/dist/consent/cookie_consent_banner.js +40 -0
- package/dist/consent/gtm_mapping.d.ts +13 -0
- package/dist/consent/gtm_mapping.d.ts.map +1 -0
- package/dist/consent/gtm_mapping.js +30 -0
- package/dist/consent/index.d.ts +7 -0
- package/dist/consent/index.d.ts.map +1 -0
- package/dist/consent/index.js +7 -0
- package/dist/consent/manage_modal.d.ts +2 -0
- package/dist/consent/manage_modal.d.ts.map +1 -0
- package/dist/consent/manage_modal.js +33 -0
- package/dist/consent/read_consent.d.ts +15 -0
- package/dist/consent/read_consent.d.ts.map +1 -0
- package/dist/consent/read_consent.js +23 -0
- package/dist/consent/use_consent.d.ts +7 -0
- package/dist/consent/use_consent.d.ts.map +1 -0
- package/dist/consent/use_consent.js +55 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.d.ts +12 -13
- package/dist/lib/auth/auth_types.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.js +0 -8
- package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts +7 -8
- package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_tenant_auth.server.js +22 -23
- package/dist/lib/auth/index.d.ts +2 -2
- package/dist/lib/auth/index.d.ts.map +1 -1
- package/dist/lib/auth/nextauth_config.d.ts.map +1 -1
- package/dist/lib/auth/nextauth_config.js +50 -1
- package/dist/lib/auth/with_auth.server.d.ts +13 -13
- package/dist/lib/auth/with_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/with_auth.server.js +2 -2
- package/dist/lib/config/default_config.d.ts +16 -0
- package/dist/lib/config/default_config.d.ts.map +1 -1
- package/dist/lib/config/default_config.js +8 -0
- package/dist/lib/cookies_config.server.d.ts +1 -1
- package/dist/lib/cookies_config.server.js +1 -1
- package/dist/lib/login_config.server.d.ts +0 -6
- package/dist/lib/login_config.server.d.ts.map +1 -1
- package/dist/lib/login_config.server.js +2 -11
- package/dist/lib/oauth_config.server.d.ts +8 -0
- package/dist/lib/oauth_config.server.d.ts.map +1 -1
- package/dist/lib/oauth_config.server.js +10 -0
- package/dist/lib/register_config.server.d.ts +2 -0
- package/dist/lib/register_config.server.d.ts.map +1 -1
- package/dist/lib/register_config.server.js +2 -0
- package/dist/lib/services/email_template_manifest.d.ts.map +1 -1
- package/dist/lib/services/email_template_manifest.js +0 -17
- package/dist/lib/services/index.d.ts +0 -2
- package/dist/lib/services/index.d.ts.map +1 -1
- package/dist/lib/services/index.js +0 -1
- package/dist/lib/services/oauth_service.d.ts +13 -0
- package/dist/lib/services/oauth_service.d.ts.map +1 -1
- package/dist/lib/services/oauth_service.js +122 -0
- package/dist/lib/services/otp_service.d.ts +1 -1
- package/dist/lib/services/otp_service.d.ts.map +1 -1
- package/dist/lib/services/otp_service.js +6 -1
- package/dist/lib/services/session_token_service.d.ts +0 -2
- package/dist/lib/services/session_token_service.d.ts.map +1 -1
- package/dist/lib/services/session_token_service.js +0 -2
- package/dist/server/routes/assets.d.ts +8 -0
- package/dist/server/routes/assets.d.ts.map +1 -0
- package/dist/server/routes/assets.js +38 -0
- package/dist/server/routes/consent_me.d.ts +4 -0
- package/dist/server/routes/consent_me.d.ts.map +1 -0
- package/dist/server/routes/consent_me.js +15 -0
- package/dist/server/routes/index.d.ts +6 -3
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +9 -4
- package/dist/server/routes/me.d.ts.map +1 -1
- package/dist/server/routes/me.js +1 -43
- package/dist/server/routes/oauth_facebook_callback.d.ts +8 -0
- package/dist/server/routes/oauth_facebook_callback.d.ts.map +1 -0
- package/dist/server/routes/oauth_facebook_callback.js +164 -0
- package/dist/server/routes/otp/verify.js +2 -2
- package/dist/server/routes/strings_defaults.d.ts +4 -0
- package/dist/server/routes/strings_defaults.d.ts.map +1 -0
- package/dist/server/routes/strings_defaults.js +7 -0
- package/dist/server/routes/user_management_users.d.ts +11 -0
- package/dist/server/routes/user_management_users.d.ts.map +1 -1
- package/dist/server/routes/user_management_users.js +50 -0
- package/dist/server-lib.d.ts +0 -3
- package/dist/server-lib.d.ts.map +1 -1
- package/dist/server-lib.js +0 -2
- package/dist/server_pages/forgot_password.d.ts +1 -1
- package/dist/server_pages/forgot_password.d.ts.map +1 -1
- package/dist/server_pages/forgot_password.js +9 -3
- package/dist/server_pages/forgot_password_client_wrapper.d.ts +3 -1
- package/dist/server_pages/forgot_password_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/forgot_password_client_wrapper.js +2 -2
- package/dist/server_pages/index.d.ts +2 -0
- package/dist/server_pages/index.d.ts.map +1 -1
- package/dist/server_pages/index.js +1 -0
- package/dist/server_pages/login.d.ts +1 -1
- package/dist/server_pages/login.d.ts.map +1 -1
- package/dist/server_pages/login.js +12 -3
- package/dist/server_pages/login_client_wrapper.d.ts +4 -1
- package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/login_client_wrapper.js +2 -2
- package/dist/server_pages/my_settings.d.ts +1 -1
- package/dist/server_pages/my_settings.d.ts.map +1 -1
- package/dist/server_pages/my_settings.js +1 -2
- package/dist/server_pages/otp.d.ts +16 -2
- package/dist/server_pages/otp.d.ts.map +1 -1
- package/dist/server_pages/otp.js +10 -3
- package/dist/server_pages/register.d.ts +1 -1
- package/dist/server_pages/register.d.ts.map +1 -1
- package/dist/server_pages/register.js +11 -3
- package/dist/server_pages/register_client_wrapper.d.ts +3 -1
- package/dist/server_pages/register_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/register_client_wrapper.js +2 -2
- package/dist/server_pages/reset_password.d.ts +1 -1
- package/dist/server_pages/reset_password.d.ts.map +1 -1
- package/dist/server_pages/reset_password.js +9 -3
- package/dist/server_pages/reset_password_client_wrapper.d.ts +3 -1
- package/dist/server_pages/reset_password_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/reset_password_client_wrapper.js +2 -2
- package/dist/server_pages/verify_email.d.ts +1 -1
- package/dist/server_pages/verify_email.d.ts.map +1 -1
- package/dist/server_pages/verify_email.js +8 -3
- package/dist/server_pages/verify_email_client_wrapper.d.ts +3 -1
- package/dist/server_pages/verify_email_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/verify_email_client_wrapper.js +2 -2
- package/dist/strings/default_strings.d.ts +47 -0
- package/dist/strings/default_strings.d.ts.map +1 -0
- package/dist/strings/default_strings.js +18 -0
- package/dist/strings/index.d.ts +4 -0
- package/dist/strings/index.d.ts.map +1 -0
- package/dist/strings/index.js +3 -0
- package/dist/strings/strings_context.d.ts +12 -0
- package/dist/strings/strings_context.d.ts.map +1 -0
- package/dist/strings/strings_context.js +23 -0
- package/dist/strings/strings_provider.d.ts +26 -0
- package/dist/strings/strings_provider.d.ts.map +1 -0
- package/dist/strings/strings_provider.js +45 -0
- package/dist/theme/create_theme.d.ts +7 -0
- package/dist/theme/create_theme.d.ts.map +1 -0
- package/dist/theme/create_theme.js +97 -0
- package/dist/theme/hex_to_hsl.d.ts +16 -0
- package/dist/theme/hex_to_hsl.d.ts.map +1 -0
- package/dist/theme/hex_to_hsl.js +110 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +3 -0
- package/dist/theme/luminance.d.ts +11 -0
- package/dist/theme/luminance.d.ts.map +1 -0
- package/dist/theme/luminance.js +45 -0
- package/dist/theme/theme_provider.d.ts +14 -0
- package/dist/theme/theme_provider.d.ts.map +1 -0
- package/dist/theme/theme_provider.js +23 -0
- package/dist/theme/theme_types.d.ts +36 -0
- package/dist/theme/theme_types.d.ts.map +1 -0
- package/dist/theme/theme_types.js +1 -0
- package/dist/themes/index.d.ts +2 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +2 -0
- package/dist/themes/preset_neutral.d.ts +3 -0
- package/dist/themes/preset_neutral.d.ts.map +1 -0
- package/dist/themes/preset_neutral.js +14 -0
- package/package.json +25 -22
|
@@ -94,6 +94,7 @@ export function UserManagementLayout({ className, hrbacEnabled = false, userType
|
|
|
94
94
|
const [users, setUsers] = useState([]);
|
|
95
95
|
const [usersLoading, setUsersLoading] = useState(true);
|
|
96
96
|
const [deactivateDialogOpen, setDeactivateDialogOpen] = useState(false);
|
|
97
|
+
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
97
98
|
const [resetPasswordDialogOpen, setResetPasswordDialogOpen] = useState(false);
|
|
98
99
|
const [userDetailDialogOpen, setUserDetailDialogOpen] = useState(false);
|
|
99
100
|
const [assignRolesDialogOpen, setAssignRolesDialogOpen] = useState(false);
|
|
@@ -217,6 +218,36 @@ export function UserManagementLayout({ className, hrbacEnabled = false, userType
|
|
|
217
218
|
setUsersActionLoading(false);
|
|
218
219
|
}
|
|
219
220
|
};
|
|
221
|
+
// Handle delete user (hard-delete)
|
|
222
|
+
const handleDeleteUser = async () => {
|
|
223
|
+
if (!selectedUser)
|
|
224
|
+
return;
|
|
225
|
+
setUsersActionLoading(true);
|
|
226
|
+
try {
|
|
227
|
+
const response = await fetch(`${apiBasePath}/user_management/users`, {
|
|
228
|
+
method: "DELETE",
|
|
229
|
+
headers: { "Content-Type": "application/json" },
|
|
230
|
+
credentials: "include",
|
|
231
|
+
body: JSON.stringify({ user_id: selectedUser.id }),
|
|
232
|
+
});
|
|
233
|
+
const data = await response.json();
|
|
234
|
+
if (response.ok && data.success) {
|
|
235
|
+
setUsers((prev) => prev.filter((u) => u.id !== selectedUser.id));
|
|
236
|
+
setDeleteDialogOpen(false);
|
|
237
|
+
setSelectedUser(null);
|
|
238
|
+
toast.success("User deleted successfully");
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
toast.error(data.error || "Failed to delete user");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (_a) {
|
|
245
|
+
toast.error("Failed to delete user");
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
setUsersActionLoading(false);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
220
251
|
// Handle reset password
|
|
221
252
|
const handleResetPassword = async () => {
|
|
222
253
|
if (!selectedUser)
|
|
@@ -535,7 +566,10 @@ export function UserManagementLayout({ className, hrbacEnabled = false, userType
|
|
|
535
566
|
}, variant: "outline", size: "sm", className: "cls_user_management_users_table_action_deactivate", children: _jsx(UserX, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Deactivate" }) })] })), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { onClick: () => {
|
|
536
567
|
setSelectedUser(user);
|
|
537
568
|
setResetPasswordDialogOpen(true);
|
|
538
|
-
}, variant: "outline", size: "sm", className: "cls_user_management_users_table_action_reset_password", children: _jsx(KeyRound, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Reset Password" }) })] })
|
|
569
|
+
}, variant: "outline", size: "sm", className: "cls_user_management_users_table_action_reset_password", children: _jsx(KeyRound, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Reset Password" }) })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { onClick: () => {
|
|
570
|
+
setSelectedUser(user);
|
|
571
|
+
setDeleteDialogOpen(true);
|
|
572
|
+
}, variant: "outline", size: "sm", className: "cls_user_management_users_table_action_delete text-destructive", children: _jsx(Trash2, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: _jsx("p", { children: "Delete User" }) })] })] }) }) })] }, user.id)))) })] }) })) })), showRolesTab && (_jsx(TabsContent, { value: "roles", className: "cls_user_management_tab_roles w-full", children: _jsx(RolesMatrix, { add_button_enabled: true, role_name_selection_enabled: false, onSave: (data) => {
|
|
539
573
|
// Data is already saved by RolesMatrix component
|
|
540
574
|
console.log("Roles saved:", data);
|
|
541
575
|
} }) })), showPermissionsTab && (_jsx(TabsContent, { value: "permissions", className: "cls_user_management_tab_permissions w-full", children: _jsxs("div", { className: "cls_user_management_permissions_container flex flex-col gap-4 w-full", children: [_jsxs("div", { className: "cls_user_management_permissions_header flex items-center justify-between", children: [_jsx("div", { className: "cls_user_management_permissions_header_left flex items-center gap-2", children: _jsxs(Button, { onClick: () => setAddPermissionDialogOpen(true), variant: "default", size: "sm", className: "cls_user_management_permissions_add_button", children: [_jsx(Plus, { className: "h-4 w-4 mr-2" }), "Add Permission"] }) }), _jsx("div", { className: "cls_user_management_permissions_header_right", children: _jsx(Button, { onClick: handleMigratePermissions, disabled: migrateLoading, variant: "default", size: "sm", className: "cls_user_management_permissions_migrate_button", children: migrateLoading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Migrating..."] })) : ("Migrate config to database") }) })] }), permissionsLoading ? (_jsx("div", { className: "cls_user_management_permissions_loading flex items-center justify-center p-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-slate-400" }) })) : (_jsx("div", { className: "cls_user_management_permissions_table_container border rounded-lg overflow-auto w-full", children: _jsxs(Table, { className: "cls_user_management_permissions_table w-full", children: [_jsx(TableHeader, { className: "cls_user_management_permissions_table_header", children: _jsxs(TableRow, { className: "cls_user_management_permissions_table_header_row", children: [_jsx(TableHead, { className: "cls_user_management_permissions_table_header_name", children: "Permission Name" }), _jsx(TableHead, { className: "cls_user_management_permissions_table_header_description", children: "Description" }), _jsx(TableHead, { className: "cls_user_management_permissions_table_header_source", children: "Source" }), _jsx(TableHead, { className: "cls_user_management_permissions_table_header_actions text-right", children: "Actions" })] }) }), _jsx(TableBody, { className: "cls_user_management_permissions_table_body", children: permissions.length === 0 ? (_jsx(TableRow, { className: "cls_user_management_permissions_table_row_empty", children: _jsx(TableCell, { colSpan: 4, className: "text-center text-muted-foreground py-8", children: "No permissions found." }) })) : (permissions.map((permission) => (_jsxs(TableRow, { className: "cls_user_management_permissions_table_row", children: [_jsx(TableCell, { className: `cls_user_management_permissions_table_cell_name font-medium ${permission.source === "db" ? "text-blue-600" : "text-purple-600"}`, children: permission.permission_name }), _jsx(TableCell, { className: "cls_user_management_permissions_table_cell_description", children: permission.description || "-" }), _jsx(TableCell, { className: "cls_user_management_permissions_table_cell_source", children: _jsx("span", { className: `px-2 py-1 rounded text-xs font-medium ${permission.source === "db"
|
|
@@ -547,7 +581,10 @@ export function UserManagementLayout({ className, hrbacEnabled = false, userType
|
|
|
547
581
|
}, variant: "outline", size: "sm", className: "cls_user_management_permissions_table_action_edit", children: [_jsx(Edit, { className: "h-4 w-4 mr-1" }), "Edit"] }), _jsxs(Button, { onClick: () => handleDeletePermission(permission), disabled: permissionsActionLoading, variant: "outline", size: "sm", className: "cls_user_management_permissions_table_action_delete text-destructive", children: [_jsx(Trash2, { className: "h-4 w-4 mr-1" }), "Delete"] })] })) }) })] }, `${permission.source}-${permission.id}-${permission.permission_name}`)))) })] }) }))] }) })), showScopeHierarchyTab && (_jsx(TabsContent, { value: "scope_hierarchy", className: "cls_user_management_tab_scope_hierarchy w-full", children: _jsx(ScopeHierarchyTab, {}) })), showUserScopesTab && (_jsx(TabsContent, { value: "user_scopes", className: "cls_user_management_tab_user_scopes w-full", children: _jsx(UserScopesTab, {}) }))] })), _jsx(AlertDialog, { open: deactivateDialogOpen, onOpenChange: setDeactivateDialogOpen, children: _jsxs(AlertDialogContent, { className: "cls_user_management_deactivate_dialog", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Deactivate User" }), _jsxs(AlertDialogDescription, { children: ["Are you sure you want to deactivate ", (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name) || (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.email_address), "? They will not be able to log in until reactivated."] })] }), _jsxs(AlertDialogFooter, { className: "cls_user_management_deactivate_dialog_footer", children: [_jsx(AlertDialogAction, { onClick: handleDeactivateUser, disabled: usersActionLoading, className: "cls_user_management_deactivate_dialog_confirm", children: usersActionLoading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Deactivating..."] })) : ("Deactivate") }), _jsx(AlertDialogCancel, { onClick: () => {
|
|
548
582
|
setDeactivateDialogOpen(false);
|
|
549
583
|
setSelectedUser(null);
|
|
550
|
-
}, className: "cls_user_management_deactivate_dialog_cancel", children: "Cancel" })] })] }) }), _jsx(AlertDialog, { open:
|
|
584
|
+
}, className: "cls_user_management_deactivate_dialog_cancel", children: "Cancel" })] })] }) }), _jsx(AlertDialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: _jsxs(AlertDialogContent, { className: "cls_user_management_delete_dialog", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete User" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name) || (selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.email_address), "'s account and all associated data. This cannot be undone."] })] }), _jsxs(AlertDialogFooter, { className: "cls_user_management_delete_dialog_footer", children: [_jsx(AlertDialogAction, { onClick: handleDeleteUser, disabled: usersActionLoading, className: "cls_user_management_delete_dialog_confirm bg-destructive text-destructive-foreground hover:bg-destructive/90", children: usersActionLoading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Deleting..."] })) : (_jsxs(_Fragment, { children: [_jsx(Trash2, { className: "h-4 w-4 mr-2" }), "Delete"] })) }), _jsx(AlertDialogCancel, { onClick: () => {
|
|
585
|
+
setDeleteDialogOpen(false);
|
|
586
|
+
setSelectedUser(null);
|
|
587
|
+
}, className: "cls_user_management_delete_dialog_cancel", children: "Cancel" })] })] }) }), _jsx(AlertDialog, { open: resetPasswordDialogOpen, onOpenChange: setResetPasswordDialogOpen, children: _jsxs(AlertDialogContent, { className: "cls_user_management_reset_password_dialog", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Reset Password" }), _jsxs(AlertDialogDescription, { children: ["Send a password reset email to ", selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.email_address, "? They will receive a link to reset their password."] })] }), _jsxs(AlertDialogFooter, { className: "cls_user_management_reset_password_dialog_footer", children: [_jsx(AlertDialogAction, { onClick: handleResetPassword, disabled: usersActionLoading, className: "cls_user_management_reset_password_dialog_confirm", children: usersActionLoading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Sending..."] })) : ("Send Reset Email") }), _jsx(AlertDialogCancel, { onClick: () => {
|
|
551
588
|
setResetPasswordDialogOpen(false);
|
|
552
589
|
setSelectedUser(null);
|
|
553
590
|
}, className: "cls_user_management_reset_password_dialog_cancel", children: "Cancel" })] })] }) }), _jsx(Dialog, { open: editPermissionDialogOpen, onOpenChange: setEditPermissionDialogOpen, children: _jsxs(DialogContent, { className: "cls_user_management_edit_permission_dialog", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Edit Permission" }), _jsxs(DialogDescription, { children: ["Update the description for permission: ", editingPermission === null || editingPermission === void 0 ? void 0 : editingPermission.permission_name] })] }), _jsx("div", { className: "cls_user_management_edit_permission_dialog_content flex flex-col gap-4 py-4", children: _jsxs("div", { className: "cls_user_management_edit_permission_dialog_field flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "permission_description", className: "cls_user_management_edit_permission_dialog_label", children: "Description" }), _jsx(Input, { id: "permission_description", value: editDescription, onChange: (e) => setEditDescription(e.target.value), placeholder: "Enter permission description", className: "cls_user_management_edit_permission_dialog_input" })] }) }), _jsxs(DialogFooter, { className: "cls_user_management_edit_permission_dialog_footer", children: [_jsx(Button, { onClick: handleEditPermission, disabled: permissionsActionLoading, variant: "default", className: "cls_user_management_edit_permission_dialog_save", children: permissionsActionLoading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Saving..."] })) : (_jsxs(_Fragment, { children: [_jsx(CircleCheck, { className: "h-4 w-4 mr-2" }), "Save"] })) }), _jsxs(Button, { onClick: () => {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ConsentState {
|
|
2
|
+
necessary: true;
|
|
3
|
+
functional: boolean;
|
|
4
|
+
analytics: boolean;
|
|
5
|
+
marketing: boolean;
|
|
6
|
+
version: 1;
|
|
7
|
+
}
|
|
8
|
+
export declare const HAZO_CONSENT_COOKIE_NAME = "hazo_consent_v1";
|
|
9
|
+
/**
|
|
10
|
+
* Parse a URL-encoded JSON cookie value into a ConsentState.
|
|
11
|
+
* Returns null if the value is invalid or has an unexpected shape.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parse_consent(value: string): ConsentState | null;
|
|
14
|
+
/**
|
|
15
|
+
* Serialize a ConsentState to a URL-encoded JSON string suitable for cookie storage.
|
|
16
|
+
*/
|
|
17
|
+
export declare function serialize_consent(state: ConsentState): string;
|
|
18
|
+
//# sourceMappingURL=consent_state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent_state.d.ts","sourceRoot":"","sources":["../../src/consent/consent_state.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,eAAO,MAAM,wBAAwB,oBAAoB,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAgBhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAE7D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// file_description: isomorphic consent state types, parser, and serializer — no Node.js or browser-specific imports
|
|
2
|
+
export const HAZO_CONSENT_COOKIE_NAME = "hazo_consent_v1";
|
|
3
|
+
/**
|
|
4
|
+
* Parse a URL-encoded JSON cookie value into a ConsentState.
|
|
5
|
+
* Returns null if the value is invalid or has an unexpected shape.
|
|
6
|
+
*/
|
|
7
|
+
export function parse_consent(value) {
|
|
8
|
+
try {
|
|
9
|
+
const decoded = decodeURIComponent(value);
|
|
10
|
+
const parsed = JSON.parse(decoded);
|
|
11
|
+
// Validate shape
|
|
12
|
+
if (parsed.version !== 1 ||
|
|
13
|
+
parsed.necessary !== true ||
|
|
14
|
+
typeof parsed.functional !== "boolean" ||
|
|
15
|
+
typeof parsed.analytics !== "boolean" ||
|
|
16
|
+
typeof parsed.marketing !== "boolean")
|
|
17
|
+
return null;
|
|
18
|
+
return parsed;
|
|
19
|
+
}
|
|
20
|
+
catch (_a) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Serialize a ConsentState to a URL-encoded JSON string suitable for cookie storage.
|
|
26
|
+
*/
|
|
27
|
+
export function serialize_consent(state) {
|
|
28
|
+
return encodeURIComponent(JSON.stringify(state));
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ConsentState } from "./consent_state.js";
|
|
2
|
+
interface CookieConsentBannerProps {
|
|
3
|
+
enableGTM?: boolean;
|
|
4
|
+
gtmContainerId?: string;
|
|
5
|
+
onChange?: (state: ConsentState) => void;
|
|
6
|
+
/** Default: "bottom" */
|
|
7
|
+
position?: "bottom" | "top";
|
|
8
|
+
}
|
|
9
|
+
export declare function CookieConsentBanner({ enableGTM, gtmContainerId, onChange, position, }: CookieConsentBannerProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=cookie_consent_banner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookie_consent_banner.d.ts","sourceRoot":"","sources":["../../src/consent/cookie_consent_banner.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAKpD,UAAU,wBAAwB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,cAAc,EACd,QAAQ,EACR,QAAmB,GACpB,EAAE,wBAAwB,2CA4E1B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
// file_description: cookie consent banner — shown until the user makes a consent choice; renders manage modal afterward
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
import { useConsent } from "./use_consent.js";
|
|
6
|
+
import { ConsentManageModal } from "./manage_modal.js";
|
|
7
|
+
import { to_gtm_signals, gtm_default_payload } from "./gtm_mapping.js";
|
|
8
|
+
export function CookieConsentBanner({ enableGTM, gtmContainerId, onChange, position = "bottom", }) {
|
|
9
|
+
const { consent, set_consent, open_manager } = useConsent();
|
|
10
|
+
const gtm_default_pushed = useRef(false);
|
|
11
|
+
// Push consent_default to GTM on first mount (before user has consented)
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!enableGTM || !gtmContainerId)
|
|
14
|
+
return;
|
|
15
|
+
if (gtm_default_pushed.current)
|
|
16
|
+
return;
|
|
17
|
+
gtm_default_pushed.current = true;
|
|
18
|
+
window.dataLayer = window.dataLayer || [];
|
|
19
|
+
window.dataLayer.push(Object.assign({ event: "consent_default" }, gtm_default_payload()));
|
|
20
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
21
|
+
}, []); // only on mount
|
|
22
|
+
// Push consent_update to GTM whenever the user's consent changes
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!consent)
|
|
25
|
+
return; // no state yet — don't push
|
|
26
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(consent);
|
|
27
|
+
if (enableGTM && gtmContainerId) {
|
|
28
|
+
window.dataLayer = window.dataLayer || [];
|
|
29
|
+
window.dataLayer.push(Object.assign({ event: "consent_update" }, to_gtm_signals(consent)));
|
|
30
|
+
}
|
|
31
|
+
// onChange is intentionally excluded to avoid infinite loops with unstable prop refs
|
|
32
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
33
|
+
}, [consent, enableGTM, gtmContainerId]);
|
|
34
|
+
// Consent already captured — only render the modal so open_manager() still works
|
|
35
|
+
if (consent !== null) {
|
|
36
|
+
return _jsx(ConsentManageModal, {});
|
|
37
|
+
}
|
|
38
|
+
const positionClass = position === "top" ? "top-0" : "bottom-0";
|
|
39
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: `fixed ${positionClass} left-0 right-0 z-40 bg-primary text-primary-foreground p-4 flex flex-wrap items-center gap-3 justify-between`, children: [_jsx("p", { className: "text-sm flex-1 min-w-[200px]", children: "We use cookies to improve your experience. By continuing, you agree to our use of cookies." }), _jsxs("div", { className: "flex gap-2 flex-wrap", children: [_jsx("button", { onClick: () => set_consent({ functional: false, analytics: false, marketing: false }), className: "px-3 py-1.5 text-xs bg-primary-foreground/20 hover:bg-primary-foreground/30 rounded text-primary-foreground", children: "Decline all" }), _jsx("button", { onClick: () => open_manager(), className: "px-3 py-1.5 text-xs bg-primary-foreground/20 hover:bg-primary-foreground/30 rounded text-primary-foreground", children: "Manage" }), _jsx("button", { onClick: () => set_consent({ functional: true, analytics: true, marketing: true }), className: "px-3 py-1.5 text-xs bg-primary-foreground rounded text-primary font-medium", children: "Accept all" })] })] }), _jsx(ConsentManageModal, {})] }));
|
|
40
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ConsentState } from "./consent_state";
|
|
2
|
+
export type GtmSignal = "security_storage" | "functionality_storage" | "personalization_storage" | "analytics_storage" | "ad_storage" | "ad_user_data" | "ad_personalization";
|
|
3
|
+
/**
|
|
4
|
+
* Maps a ConsentState to GTM consent signals.
|
|
5
|
+
* security_storage is always granted; other signals follow the user's category choices.
|
|
6
|
+
*/
|
|
7
|
+
export declare function to_gtm_signals(state: ConsentState): Record<GtmSignal, "granted" | "denied">;
|
|
8
|
+
/**
|
|
9
|
+
* Default GTM consent payload before the user has made a choice.
|
|
10
|
+
* security_storage is granted; all others are denied.
|
|
11
|
+
*/
|
|
12
|
+
export declare function gtm_default_payload(): Record<GtmSignal, "granted" | "denied">;
|
|
13
|
+
//# sourceMappingURL=gtm_mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gtm_mapping.d.ts","sourceRoot":"","sources":["../../src/consent/gtm_mapping.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,MAAM,SAAS,GACjB,kBAAkB,GAClB,uBAAuB,GACvB,yBAAyB,GACzB,mBAAmB,GACnB,YAAY,GACZ,cAAc,GACd,oBAAoB,CAAC;AAEzB;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAAC,CAU3F;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAAC,CAU7E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps a ConsentState to GTM consent signals.
|
|
3
|
+
* security_storage is always granted; other signals follow the user's category choices.
|
|
4
|
+
*/
|
|
5
|
+
export function to_gtm_signals(state) {
|
|
6
|
+
return {
|
|
7
|
+
security_storage: "granted", // always granted
|
|
8
|
+
functionality_storage: state.functional ? "granted" : "denied",
|
|
9
|
+
personalization_storage: state.functional ? "granted" : "denied",
|
|
10
|
+
analytics_storage: state.analytics ? "granted" : "denied",
|
|
11
|
+
ad_storage: state.marketing ? "granted" : "denied",
|
|
12
|
+
ad_user_data: state.marketing ? "granted" : "denied",
|
|
13
|
+
ad_personalization: state.marketing ? "granted" : "denied",
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Default GTM consent payload before the user has made a choice.
|
|
18
|
+
* security_storage is granted; all others are denied.
|
|
19
|
+
*/
|
|
20
|
+
export function gtm_default_payload() {
|
|
21
|
+
return {
|
|
22
|
+
security_storage: "granted",
|
|
23
|
+
functionality_storage: "denied",
|
|
24
|
+
personalization_storage: "denied",
|
|
25
|
+
analytics_storage: "denied",
|
|
26
|
+
ad_storage: "denied",
|
|
27
|
+
ad_user_data: "denied",
|
|
28
|
+
ad_personalization: "denied",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/consent/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// file_description: barrel export for the hazo_auth consent module
|
|
2
|
+
export * from "./consent_state.js";
|
|
3
|
+
export * from "./cookie_consent_banner.js";
|
|
4
|
+
export * from "./use_consent.js";
|
|
5
|
+
export * from "./read_consent.js";
|
|
6
|
+
export * from "./gtm_mapping.js";
|
|
7
|
+
export * from "./manage_modal.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage_modal.d.ts","sourceRoot":"","sources":["../../src/consent/manage_modal.tsx"],"names":[],"mappings":"AAOA,wBAAgB,kBAAkB,4CA0GjC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// file_description: modal dialog for managing individual cookie consent categories
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import * as Dialog from "@radix-ui/react-dialog";
|
|
6
|
+
import { useConsent } from "./use_consent.js";
|
|
7
|
+
export function ConsentManageModal() {
|
|
8
|
+
const { consent, set_consent } = useConsent();
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const [local, setLocal] = useState({
|
|
11
|
+
functional: false,
|
|
12
|
+
analytics: false,
|
|
13
|
+
marketing: false,
|
|
14
|
+
});
|
|
15
|
+
// Listen for the open event dispatched by open_manager()
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const handle = () => {
|
|
18
|
+
setLocal({
|
|
19
|
+
functional: !!(consent === null || consent === void 0 ? void 0 : consent.functional),
|
|
20
|
+
analytics: !!(consent === null || consent === void 0 ? void 0 : consent.analytics),
|
|
21
|
+
marketing: !!(consent === null || consent === void 0 ? void 0 : consent.marketing),
|
|
22
|
+
});
|
|
23
|
+
setOpen(true);
|
|
24
|
+
};
|
|
25
|
+
window.addEventListener("hazo_auth:open_consent_manager", handle);
|
|
26
|
+
return () => window.removeEventListener("hazo_auth:open_consent_manager", handle);
|
|
27
|
+
}, [consent]);
|
|
28
|
+
const save = () => {
|
|
29
|
+
set_consent(Object.assign(Object.assign({}, local), { necessary: true, version: 1 }));
|
|
30
|
+
setOpen(false);
|
|
31
|
+
};
|
|
32
|
+
return (_jsx(Dialog.Root, { open: open, onOpenChange: setOpen, children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Overlay, { className: "fixed inset-0 bg-black/50 z-50" }), _jsxs(Dialog.Content, { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-background rounded-lg p-6 z-50 w-full max-w-md shadow-lg", children: [_jsx(Dialog.Title, { className: "text-lg font-semibold mb-4", children: "Cookie preferences" }), _jsxs("div", { className: "flex items-center justify-between py-3 border-b", children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "Necessary" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Required for the site to function" })] }), _jsx("input", { type: "checkbox", checked: true, disabled: true, className: "h-4 w-4" })] }), _jsxs("div", { className: "flex items-center justify-between py-3 border-b", children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "Functional" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Remembers your preferences" })] }), _jsx("input", { type: "checkbox", checked: local.functional, onChange: (e) => setLocal((p) => (Object.assign(Object.assign({}, p), { functional: e.target.checked }))), className: "h-4 w-4" })] }), _jsxs("div", { className: "flex items-center justify-between py-3 border-b", children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "Analytics" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Helps us understand how you use the site" })] }), _jsx("input", { type: "checkbox", checked: local.analytics, onChange: (e) => setLocal((p) => (Object.assign(Object.assign({}, p), { analytics: e.target.checked }))), className: "h-4 w-4" })] }), _jsxs("div", { className: "flex items-center justify-between py-3", children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "Marketing" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Used for targeted advertising" })] }), _jsx("input", { type: "checkbox", checked: local.marketing, onChange: (e) => setLocal((p) => (Object.assign(Object.assign({}, p), { marketing: e.target.checked }))), className: "h-4 w-4" })] }), _jsxs("div", { className: "mt-6 flex gap-3 justify-end", children: [_jsx("button", { className: "px-4 py-2 text-sm border rounded-md hover:bg-muted", onClick: () => setOpen(false), children: "Cancel" }), _jsx("button", { className: "px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:opacity-90", onClick: save, children: "Save preferences" })] })] })] }) }));
|
|
33
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ConsentState } from "./consent_state.js";
|
|
2
|
+
/** Structural type covering both `Headers` and Next.js `ReadonlyHeaders`. */
|
|
3
|
+
type AnyHeaders = {
|
|
4
|
+
get(name: string): string | null;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Reads the consent state from request headers (server-side).
|
|
8
|
+
* Returns null if the consent cookie is absent or contains invalid data.
|
|
9
|
+
*
|
|
10
|
+
* Prefix support (Phase 7): when cookie_prefix config is set, the cookie name
|
|
11
|
+
* is `${prefix}hazo_consent_v1`. Currently uses the base name only.
|
|
12
|
+
*/
|
|
13
|
+
export declare function read_consent(headers: AnyHeaders): ConsentState | null;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=read_consent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read_consent.d.ts","sourceRoot":"","sources":["../../src/consent/read_consent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAA2C,MAAM,iBAAiB,CAAC;AAE7F,6EAA6E;AAC7E,KAAK,UAAU,GAAG;IAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI,CAcrE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// file_description: server-side helper that reads consent state from request headers
|
|
2
|
+
import { HAZO_CONSENT_COOKIE_NAME, parse_consent } from "./consent_state.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reads the consent state from request headers (server-side).
|
|
5
|
+
* Returns null if the consent cookie is absent or contains invalid data.
|
|
6
|
+
*
|
|
7
|
+
* Prefix support (Phase 7): when cookie_prefix config is set, the cookie name
|
|
8
|
+
* is `${prefix}hazo_consent_v1`. Currently uses the base name only.
|
|
9
|
+
*/
|
|
10
|
+
export function read_consent(headers) {
|
|
11
|
+
const cookie_header = headers.get("cookie");
|
|
12
|
+
if (!cookie_header)
|
|
13
|
+
return null;
|
|
14
|
+
const cookie_name = HAZO_CONSENT_COOKIE_NAME;
|
|
15
|
+
const match = cookie_header
|
|
16
|
+
.split(";")
|
|
17
|
+
.map((c) => c.trim())
|
|
18
|
+
.find((c) => c.startsWith(`${cookie_name}=`));
|
|
19
|
+
if (!match)
|
|
20
|
+
return null;
|
|
21
|
+
const value = match.slice(cookie_name.length + 1);
|
|
22
|
+
return parse_consent(value);
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_consent.d.ts","sourceRoot":"","sources":["../../src/consent/use_consent.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,iBAAiB,CAAC;AAmBzB,wBAAgB,UAAU,IAAI;IAC5B,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACpD,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAyCA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// file_description: client hook to read and update the user's cookie consent state
|
|
3
|
+
import { useState, useEffect, useCallback } from "react";
|
|
4
|
+
import { HAZO_CONSENT_COOKIE_NAME, parse_consent, serialize_consent, } from "./consent_state.js";
|
|
5
|
+
function read_from_cookie() {
|
|
6
|
+
if (typeof document === "undefined")
|
|
7
|
+
return null;
|
|
8
|
+
const match = document.cookie
|
|
9
|
+
.split(";")
|
|
10
|
+
.map((c) => c.trim())
|
|
11
|
+
.find((c) => c.startsWith(`${HAZO_CONSENT_COOKIE_NAME}=`));
|
|
12
|
+
if (!match)
|
|
13
|
+
return null;
|
|
14
|
+
return parse_consent(match.slice(HAZO_CONSENT_COOKIE_NAME.length + 1));
|
|
15
|
+
}
|
|
16
|
+
function write_cookie(state) {
|
|
17
|
+
const value = serialize_consent(state);
|
|
18
|
+
const maxAge = 13 * 30 * 24 * 60 * 60; // ~13 months in seconds
|
|
19
|
+
const secure = location.protocol === "https:" ? "; Secure" : "";
|
|
20
|
+
document.cookie = `${HAZO_CONSENT_COOKIE_NAME}=${value}; Max-Age=${maxAge}; SameSite=Lax; Path=/${secure}`;
|
|
21
|
+
}
|
|
22
|
+
export function useConsent() {
|
|
23
|
+
const [consent, setConsent] = useState(null);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
// Hydrate from cookie on mount
|
|
26
|
+
setConsent(read_from_cookie());
|
|
27
|
+
// Subscribe to cross-component updates dispatched by other useConsent instances.
|
|
28
|
+
// Read state from event.detail to avoid a redundant cookie parse and prevent
|
|
29
|
+
// a double re-render when the same hook instance dispatches the event itself.
|
|
30
|
+
const handle_update = (e) => {
|
|
31
|
+
const detail = e.detail;
|
|
32
|
+
setConsent(detail);
|
|
33
|
+
};
|
|
34
|
+
window.addEventListener("hazo_auth:consent_update", handle_update);
|
|
35
|
+
return () => window.removeEventListener("hazo_auth:consent_update", handle_update);
|
|
36
|
+
}, []);
|
|
37
|
+
const set_consent = useCallback((patch) => {
|
|
38
|
+
const base = consent !== null && consent !== void 0 ? consent : {
|
|
39
|
+
necessary: true,
|
|
40
|
+
functional: false,
|
|
41
|
+
analytics: false,
|
|
42
|
+
marketing: false,
|
|
43
|
+
version: 1,
|
|
44
|
+
};
|
|
45
|
+
// necessary and version are always forced to their fixed values
|
|
46
|
+
const next = Object.assign(Object.assign(Object.assign({}, base), patch), { necessary: true, version: 1 });
|
|
47
|
+
write_cookie(next);
|
|
48
|
+
setConsent(next);
|
|
49
|
+
window.dispatchEvent(new CustomEvent("hazo_auth:consent_update", { detail: next }));
|
|
50
|
+
}, [consent]);
|
|
51
|
+
const open_manager = useCallback(() => {
|
|
52
|
+
window.dispatchEvent(new CustomEvent("hazo_auth:open_consent_manager"));
|
|
53
|
+
}, []);
|
|
54
|
+
return { consent, set_consent, open_manager };
|
|
55
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./contexts/hazo_auth_provider.js";
|
|
2
2
|
export * from "./contexts/hazo_auth_config.js";
|
|
3
3
|
export * from "./components/index.js";
|
|
4
|
-
export type { HazoAuthUser, HazoAuthResult, HazoAuthError, HazoAuthOptions, ScopeDetails,
|
|
4
|
+
export type { HazoAuthUser, HazoAuthResult, HazoAuthError, HazoAuthOptions, ScopeDetails, TenantOrganization, TenantAuthOptions, TenantAuthResult, RequiredTenantAuthResult, } from "./lib/auth/auth_types";
|
|
5
5
|
export { AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError, } from "./lib/auth/auth_types.js";
|
|
6
6
|
export { cn, merge_class_names } from "./lib/utils.js";
|
|
7
7
|
export { HAZO_AUTH_PERMISSIONS, ALL_ADMIN_PERMISSIONS } from "./lib/constants.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAG5C,cAAc,oBAAoB,CAAC;AAGnC,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,eAAe,EACf,YAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAG5C,cAAc,oBAAoB,CAAC;AAGnC,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -103,11 +103,10 @@ export type ScopeDetails = {
|
|
|
103
103
|
tagline: string | null;
|
|
104
104
|
};
|
|
105
105
|
/**
|
|
106
|
-
*
|
|
107
|
-
* Simplified view of
|
|
108
|
-
* `X-Hazo-Scope-Id` header.
|
|
106
|
+
* Tenant/organization information returned in tenant auth results
|
|
107
|
+
* Simplified view of scope for API responses
|
|
109
108
|
*/
|
|
110
|
-
export type
|
|
109
|
+
export type TenantOrganization = {
|
|
111
110
|
id: string;
|
|
112
111
|
name: string;
|
|
113
112
|
slug: string | null;
|
|
@@ -145,9 +144,9 @@ export type TenantAuthResult = {
|
|
|
145
144
|
permissions: string[];
|
|
146
145
|
permission_ok: boolean;
|
|
147
146
|
missing_permissions?: string[];
|
|
148
|
-
|
|
149
|
-
/** Shorthand for
|
|
150
|
-
|
|
147
|
+
organization: TenantOrganization | null;
|
|
148
|
+
/** Shorthand for organization?.id - commonly used for DB query filters */
|
|
149
|
+
organization_id: string | null;
|
|
151
150
|
user_scopes: ScopeDetails[];
|
|
152
151
|
scope_ok?: boolean;
|
|
153
152
|
scope_access_via?: ScopeAccessInfo;
|
|
@@ -156,19 +155,19 @@ export type TenantAuthResult = {
|
|
|
156
155
|
user: null;
|
|
157
156
|
permissions: [];
|
|
158
157
|
permission_ok: false;
|
|
159
|
-
|
|
160
|
-
/** Shorthand for
|
|
161
|
-
|
|
158
|
+
organization: null;
|
|
159
|
+
/** Shorthand for organization?.id - commonly used for DB query filters */
|
|
160
|
+
organization_id: null;
|
|
162
161
|
user_scopes: [];
|
|
163
162
|
scope_ok?: false;
|
|
164
163
|
};
|
|
165
164
|
/**
|
|
166
|
-
* Guaranteed authenticated result with non-null
|
|
167
|
-
* Returned by require_tenant_auth when validation passes
|
|
165
|
+
* Guaranteed authenticated result with non-null organization
|
|
166
|
+
* Returned by require_tenant_auth when validation passes
|
|
168
167
|
*/
|
|
169
168
|
export type RequiredTenantAuthResult = TenantAuthResult & {
|
|
170
169
|
authenticated: true;
|
|
171
|
-
|
|
170
|
+
organization: TenantOrganization;
|
|
172
171
|
};
|
|
173
172
|
/**
|
|
174
173
|
* Base error class for all hazo_auth errors
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth_types.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/auth_types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth_types.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/auth_types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
// file_description: Type definitions and error classes for hazo_get_auth utility
|
|
2
|
-
//
|
|
3
|
-
// Naming note (v6.0.0): the field previously called `organization` (and
|
|
4
|
-
// `organization_id`) on `TenantAuthResult` was renamed to `selected_scope`
|
|
5
|
-
// (and `selected_scope_id`), and the type `TenantOrganization` was renamed
|
|
6
|
-
// to `SelectedScope`. The multi-tenancy model is scopes throughout; the
|
|
7
|
-
// old name was a legacy synonym for "the currently selected scope" derived
|
|
8
|
-
// from the scope-selection cookie/header. No deprecation shim is provided.
|
|
9
|
-
//
|
|
10
2
|
// section: types
|
|
11
3
|
/**
|
|
12
4
|
* Custom error class for permission denials
|
|
@@ -13,21 +13,20 @@ export declare function extract_scope_id_from_request(request: NextRequest, opti
|
|
|
13
13
|
* Tenant-aware authentication function
|
|
14
14
|
*
|
|
15
15
|
* Extracts tenant/scope context from request headers or cookies,
|
|
16
|
-
* validates access, and returns enriched result
|
|
17
|
-
* selected scope.
|
|
16
|
+
* validates access, and returns enriched result with organization info.
|
|
18
17
|
*
|
|
19
18
|
* Header priority: X-Hazo-Scope-Id > Cookie
|
|
20
19
|
*
|
|
21
20
|
* @param request - NextRequest object
|
|
22
21
|
* @param options - TenantAuthOptions for customization
|
|
23
|
-
* @returns TenantAuthResult with user, permissions,
|
|
22
|
+
* @returns TenantAuthResult with user, permissions, organization, and user_scopes
|
|
24
23
|
*
|
|
25
24
|
* @example
|
|
26
25
|
* ```typescript
|
|
27
26
|
* const auth = await hazo_get_tenant_auth(request);
|
|
28
|
-
* if (auth.authenticated && auth.
|
|
27
|
+
* if (auth.authenticated && auth.organization) {
|
|
29
28
|
* // Access tenant-specific data
|
|
30
|
-
* const data = await getData(auth.
|
|
29
|
+
* const data = await getData(auth.organization.id);
|
|
31
30
|
* }
|
|
32
31
|
* ```
|
|
33
32
|
*/
|
|
@@ -42,15 +41,15 @@ export declare function hazo_get_tenant_auth(request: NextRequest, options?: Ten
|
|
|
42
41
|
*
|
|
43
42
|
* @param request - NextRequest object
|
|
44
43
|
* @param options - TenantAuthOptions for customization
|
|
45
|
-
* @returns RequiredTenantAuthResult with guaranteed non-null
|
|
44
|
+
* @returns RequiredTenantAuthResult with guaranteed non-null organization
|
|
46
45
|
* @throws AuthenticationRequiredError, TenantRequiredError, TenantAccessDeniedError
|
|
47
46
|
*
|
|
48
47
|
* @example
|
|
49
48
|
* ```typescript
|
|
50
49
|
* try {
|
|
51
50
|
* const auth = await require_tenant_auth(request);
|
|
52
|
-
* // auth.
|
|
53
|
-
* const data = await getData(auth.
|
|
51
|
+
* // auth.organization is guaranteed non-null here
|
|
52
|
+
* const data = await getData(auth.organization.id);
|
|
54
53
|
* } catch (error) {
|
|
55
54
|
* if (error instanceof HazoAuthError) {
|
|
56
55
|
* return NextResponse.json(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hazo_get_tenant_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/hazo_get_tenant_auth.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EAGzB,MAAM,cAAc,CAAC;AAqBtB;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,iBAAiB,GACzB,MAAM,GAAG,SAAS,CAYpB;AAiCD
|
|
1
|
+
{"version":3,"file":"hazo_get_tenant_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/hazo_get_tenant_auth.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EAGzB,MAAM,cAAc,CAAC;AAqBtB;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,iBAAiB,GACzB,MAAM,GAAG,SAAS,CAYpB;AAiCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CA0F3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,wBAAwB,CAAC,CA0BnC"}
|