hazo_auth 1.0.4 → 1.1.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 +72 -1
- package/hazo_auth_config.example.ini +41 -0
- package/instrumentation.ts +2 -2
- package/package.json +4 -3
- package/scripts/init_users.ts +378 -0
- package/src/app/api/hazo_auth/auth/upload_profile_picture/route.ts +8 -8
- package/src/app/api/hazo_auth/change_password/route.ts +7 -7
- package/src/app/api/hazo_auth/forgot_password/route.ts +4 -4
- package/src/app/api/hazo_auth/get_auth/route.ts +4 -4
- package/src/app/api/hazo_auth/invalidate_cache/route.ts +5 -5
- package/src/app/api/hazo_auth/library_photos/route.ts +3 -3
- package/src/app/api/hazo_auth/login/route.ts +31 -5
- package/src/app/api/hazo_auth/logout/route.ts +4 -4
- package/src/app/api/hazo_auth/me/route.ts +1 -1
- package/src/app/api/hazo_auth/profile_picture/[filename]/route.ts +1 -1
- package/src/app/api/hazo_auth/register/route.ts +17 -14
- package/src/app/api/hazo_auth/remove_profile_picture/route.ts +5 -5
- package/src/app/api/hazo_auth/resend_verification/route.ts +4 -4
- package/src/app/api/hazo_auth/reset_password/route.ts +5 -5
- package/src/app/api/hazo_auth/update_user/route.ts +5 -5
- package/src/app/api/hazo_auth/upload_profile_picture/route.ts +8 -8
- package/src/app/api/hazo_auth/user_management/permissions/route.ts +4 -4
- package/src/app/api/hazo_auth/user_management/roles/route.ts +5 -5
- package/src/app/api/hazo_auth/user_management/users/roles/route.ts +5 -5
- package/src/app/api/hazo_auth/user_management/users/route.ts +6 -6
- package/src/app/api/hazo_auth/validate_reset_token/route.ts +4 -4
- package/src/app/api/hazo_auth/verify_email/route.ts +4 -4
- package/src/app/api/migrations/apply/route.ts +3 -3
- package/src/app/hazo_auth/forgot_password/forgot_password_page_client.tsx +4 -4
- package/src/app/hazo_auth/forgot_password/page.tsx +4 -4
- package/src/app/hazo_auth/login/login_page_client.tsx +20 -5
- package/src/app/hazo_auth/login/page.tsx +17 -5
- package/src/app/hazo_auth/my_settings/my_settings_page_client.tsx +3 -3
- package/src/app/hazo_auth/my_settings/page.tsx +4 -4
- package/src/app/hazo_auth/register/page.tsx +15 -5
- package/src/app/hazo_auth/register/register_page_client.tsx +13 -4
- package/src/app/hazo_auth/reset_password/page.tsx +4 -4
- package/src/app/hazo_auth/reset_password/reset_password_page_client.tsx +4 -4
- package/src/app/hazo_auth/user_management/page.tsx +3 -3
- package/src/app/hazo_auth/user_management/user_management_page_client.tsx +1 -1
- package/src/app/hazo_auth/verify_email/page.tsx +4 -4
- package/src/app/hazo_auth/verify_email/verify_email_page_client.tsx +4 -4
- package/src/app/hazo_connect/api/sqlite/data/route.ts +1 -1
- package/src/app/hazo_connect/api/sqlite/schema/route.ts +1 -1
- package/src/app/hazo_connect/api/sqlite/tables/route.ts +1 -1
- package/src/app/layout.tsx +1 -1
- package/src/app/page.tsx +1 -1
- package/src/components/layouts/email_verification/config/email_verification_field_config.ts +2 -2
- package/src/components/layouts/email_verification/hooks/use_email_verification.ts +3 -3
- package/src/components/layouts/email_verification/index.tsx +11 -11
- package/src/components/layouts/forgot_password/config/forgot_password_field_config.ts +2 -2
- package/src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts +3 -3
- package/src/components/layouts/forgot_password/index.tsx +10 -10
- package/src/components/layouts/login/config/login_field_config.ts +2 -2
- package/src/components/layouts/login/hooks/use_login_form.ts +18 -13
- package/src/components/layouts/login/index.tsx +39 -11
- package/src/components/layouts/my_settings/components/editable_field.tsx +3 -3
- package/src/components/layouts/my_settings/components/password_change_dialog.tsx +5 -5
- package/src/components/layouts/my_settings/components/profile_picture_dialog.tsx +4 -4
- package/src/components/layouts/my_settings/components/profile_picture_display.tsx +2 -2
- package/src/components/layouts/my_settings/components/profile_picture_gravatar_tab.tsx +3 -3
- package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +5 -5
- package/src/components/layouts/my_settings/components/profile_picture_upload_tab.tsx +4 -4
- package/src/components/layouts/my_settings/config/my_settings_field_config.ts +2 -2
- package/src/components/layouts/my_settings/hooks/use_my_settings.ts +2 -2
- package/src/components/layouts/my_settings/index.tsx +5 -5
- package/src/components/layouts/register/config/register_field_config.ts +2 -2
- package/src/components/layouts/register/hooks/use_register_form.ts +8 -5
- package/src/components/layouts/register/index.tsx +29 -11
- package/src/components/layouts/reset_password/config/reset_password_field_config.ts +2 -2
- package/src/components/layouts/reset_password/hooks/use_reset_password_form.ts +4 -4
- package/src/components/layouts/reset_password/index.tsx +10 -10
- package/src/components/layouts/shared/components/auth_page_shell.tsx +36 -0
- package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +53 -0
- package/src/components/layouts/user_management/components/roles_matrix.tsx +7 -7
- package/src/components/layouts/user_management/index.tsx +10 -10
- package/src/components/ui/alert-dialog.tsx +2 -2
- package/src/components/ui/avatar.tsx +1 -1
- package/src/components/ui/button.tsx +1 -1
- package/src/components/ui/checkbox.tsx +1 -1
- package/src/components/ui/dialog.tsx +1 -1
- package/src/components/ui/dropdown-menu.tsx +1 -1
- package/src/components/ui/hazo_ui_tooltip.tsx +1 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/label.tsx +1 -1
- package/src/components/ui/separator.tsx +1 -1
- package/src/components/ui/sheet.tsx +1 -1
- package/src/components/ui/sidebar.tsx +8 -8
- package/src/components/ui/skeleton.tsx +1 -1
- package/src/components/ui/switch.tsx +1 -1
- package/src/components/ui/table.tsx +1 -1
- package/src/components/ui/tabs.tsx +1 -1
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/components/ui/vertical-tabs.tsx +1 -1
- package/src/lib/app_logger.ts +1 -1
- package/src/lib/config/config_loader.server.ts +20 -5
- package/src/lib/login_config.server.ts +25 -0
- package/src/lib/register_config.server.ts +17 -1
- package/src/lib/services/login_service.ts +19 -3
- package/src/lib/services/registration_service.ts +25 -4
- package/src/lib/services/user_update_service.ts +16 -3
- package/src/lib/ui_shell_config.server.ts +73 -0
- package/src/lib/utils/error_sanitizer.ts +75 -0
- package/src/stories/email_verification_layout.stories.tsx +2 -2
- package/src/stories/forgot_password_layout.stories.tsx +2 -2
- package/src/stories/login_layout.stories.tsx +2 -2
- package/src/stories/register_layout.stories.tsx +2 -2
- package/tsconfig.json +1 -4
|
@@ -10,14 +10,14 @@ import {
|
|
|
10
10
|
DialogHeader,
|
|
11
11
|
DialogTitle,
|
|
12
12
|
DialogDescription,
|
|
13
|
-
} from "
|
|
14
|
-
import { Button } from "
|
|
15
|
-
import { Tabs, TabsContent, TabsList, TabsTrigger } from "
|
|
13
|
+
} from "../../../ui/dialog";
|
|
14
|
+
import { Button } from "../../../ui/button";
|
|
15
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/tabs";
|
|
16
16
|
import { ProfilePictureUploadTab } from "./profile_picture_upload_tab";
|
|
17
17
|
import { ProfilePictureLibraryTab } from "./profile_picture_library_tab";
|
|
18
18
|
import { ProfilePictureGravatarTab } from "./profile_picture_gravatar_tab";
|
|
19
19
|
import { toast } from "sonner";
|
|
20
|
-
import { cn } from "
|
|
20
|
+
import { cn } from "../../../../lib/utils";
|
|
21
21
|
|
|
22
22
|
// section: types
|
|
23
23
|
export type ProfilePictureDialogProps = {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
|
-
import { Avatar, AvatarImage, AvatarFallback } from "
|
|
7
|
-
import { Button } from "
|
|
6
|
+
import { Avatar, AvatarImage, AvatarFallback } from "../../../ui/avatar";
|
|
7
|
+
import { Button } from "../../../ui/button";
|
|
8
8
|
import { Pencil } from "lucide-react";
|
|
9
9
|
|
|
10
10
|
// section: types
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { useState, useEffect } from "react";
|
|
7
|
-
import { Switch } from "
|
|
8
|
-
import { Label } from "
|
|
9
|
-
import { Avatar, AvatarImage, AvatarFallback } from "
|
|
7
|
+
import { Switch } from "../../../ui/switch";
|
|
8
|
+
import { Label } from "../../../ui/label";
|
|
9
|
+
import { Avatar, AvatarImage, AvatarFallback } from "../../../ui/avatar";
|
|
10
10
|
import { Info } from "lucide-react";
|
|
11
11
|
import gravatarUrl from "gravatar-url";
|
|
12
12
|
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { useState, useEffect } from "react";
|
|
7
|
-
import { Switch } from "
|
|
8
|
-
import { Label } from "
|
|
9
|
-
import { Avatar, AvatarFallback } from "
|
|
10
|
-
import { VerticalTabs, VerticalTabsList, VerticalTabsTrigger, VerticalTabsContent } from "
|
|
7
|
+
import { Switch } from "../../../ui/switch";
|
|
8
|
+
import { Label } from "../../../ui/label";
|
|
9
|
+
import { Avatar, AvatarFallback } from "../../../ui/avatar";
|
|
10
|
+
import { VerticalTabs, VerticalTabsList, VerticalTabsTrigger, VerticalTabsContent } from "../../../ui/vertical-tabs";
|
|
11
11
|
import { Loader2 } from "lucide-react";
|
|
12
|
-
import { HazoUITooltip } from "
|
|
12
|
+
import { HazoUITooltip } from "../../../ui/hazo_ui_tooltip";
|
|
13
13
|
|
|
14
14
|
// section: types
|
|
15
15
|
export type ProfilePictureLibraryTabProps = {
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { useState, useCallback, useEffect } from "react";
|
|
7
|
-
import { Switch } from "
|
|
8
|
-
import { Label } from "
|
|
9
|
-
import { Avatar, AvatarImage, AvatarFallback } from "
|
|
7
|
+
import { Switch } from "../../../ui/switch";
|
|
8
|
+
import { Label } from "../../../ui/label";
|
|
9
|
+
import { Avatar, AvatarImage, AvatarFallback } from "../../../ui/avatar";
|
|
10
10
|
import { Upload, X, Loader2, Info } from "lucide-react";
|
|
11
|
-
import { Button } from "
|
|
11
|
+
import { Button } from "../../../ui/button";
|
|
12
12
|
import imageCompression from "browser-image-compression";
|
|
13
13
|
|
|
14
14
|
// section: types
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// file_description: my settings layout specific configuration helpers
|
|
2
2
|
// section: imports
|
|
3
|
-
import type { LayoutFieldMap } from "
|
|
3
|
+
import type { LayoutFieldMap } from "../../shared/config/layout_customization";
|
|
4
4
|
import {
|
|
5
5
|
resolveButtonPalette,
|
|
6
6
|
type ButtonPaletteDefaults,
|
|
7
7
|
type ButtonPaletteOverrides,
|
|
8
8
|
type PasswordRequirementOptions,
|
|
9
|
-
} from "
|
|
9
|
+
} from "../../shared/config/layout_customization";
|
|
10
10
|
|
|
11
11
|
// section: field_identifiers
|
|
12
12
|
export const MY_SETTINGS_FIELD_IDS = {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { useState, useEffect, useCallback } from "react";
|
|
7
|
-
import { use_auth_status, trigger_auth_status_refresh } from "
|
|
7
|
+
import { use_auth_status, trigger_auth_status_refresh } from "../../shared/hooks/use_auth_status";
|
|
8
8
|
import { toast } from "sonner";
|
|
9
|
-
import type { PasswordRequirementOptions } from "
|
|
9
|
+
import type { PasswordRequirementOptions } from "../../shared/config/layout_customization";
|
|
10
10
|
|
|
11
11
|
// section: types
|
|
12
12
|
export type PasswordFields = {
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
|
-
import { Button } from "
|
|
6
|
+
import { Button } from "../../ui/button";
|
|
7
7
|
import { EditableField } from "./components/editable_field";
|
|
8
8
|
import { ProfilePictureDisplay } from "./components/profile_picture_display";
|
|
9
9
|
import { ProfilePictureDialog } from "./components/profile_picture_dialog";
|
|
10
|
-
import { UnauthorizedGuard } from "
|
|
10
|
+
import { UnauthorizedGuard } from "../shared/components/unauthorized_guard";
|
|
11
11
|
import { use_my_settings } from "./hooks/use_my_settings";
|
|
12
12
|
import {
|
|
13
13
|
resolveMySettingsLabels,
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
import type {
|
|
18
18
|
PasswordRequirementOptions,
|
|
19
19
|
ButtonPaletteOverrides,
|
|
20
|
-
} from "
|
|
20
|
+
} from "../shared/config/layout_customization";
|
|
21
21
|
import { formatDistanceToNow } from "date-fns";
|
|
22
|
-
import { PasswordField } from "
|
|
23
|
-
import { FormFieldWrapper } from "
|
|
22
|
+
import { PasswordField } from "../shared/components/password_field";
|
|
23
|
+
import { FormFieldWrapper } from "../shared/components/form_field_wrapper";
|
|
24
24
|
import { Pencil, Trash2 } from "lucide-react";
|
|
25
25
|
|
|
26
26
|
// section: types
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// file_description: register layout specific configuration helpers
|
|
2
2
|
// section: imports
|
|
3
|
-
import type { LayoutFieldMap, LayoutFieldMapOverrides } from "
|
|
3
|
+
import type { LayoutFieldMap, LayoutFieldMapOverrides } from "../../shared/config/layout_customization";
|
|
4
4
|
import {
|
|
5
5
|
resolveButtonPalette,
|
|
6
6
|
resolveFieldDefinitions,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
type LayoutLabelOverrides,
|
|
13
13
|
type PasswordRequirementOptions,
|
|
14
14
|
type PasswordRequirementOverrides,
|
|
15
|
-
} from "
|
|
15
|
+
} from "../../shared/config/layout_customization";
|
|
16
16
|
|
|
17
17
|
// section: field_identifiers
|
|
18
18
|
export const REGISTER_FIELD_IDS = {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// section: imports
|
|
3
3
|
import { useCallback, useMemo, useState } from "react";
|
|
4
4
|
import { toast } from "sonner";
|
|
5
|
-
import type { LayoutDataClient } from "
|
|
6
|
-
import type { PasswordRequirementOptions, PasswordRequirementOverrides } from "
|
|
7
|
-
import { REGISTER_FIELD_IDS, type RegisterFieldId } from "
|
|
8
|
-
import { validateEmail, validatePassword } from "
|
|
5
|
+
import type { LayoutDataClient } from "../../shared/data/layout_data_client";
|
|
6
|
+
import type { PasswordRequirementOptions, PasswordRequirementOverrides } from "../../shared/config/layout_customization";
|
|
7
|
+
import { REGISTER_FIELD_IDS, type RegisterFieldId } from "../config/register_field_config";
|
|
8
|
+
import { validateEmail, validatePassword } from "../../shared/utils/validation";
|
|
9
9
|
|
|
10
10
|
// section: constants
|
|
11
11
|
const PASSWORD_FIELDS: Array<RegisterFieldId> = [
|
|
@@ -28,6 +28,7 @@ export type UseRegisterFormParams<TClient = unknown> = {
|
|
|
28
28
|
passwordRequirements: PasswordRequirementOptions;
|
|
29
29
|
passwordRequirementOverrides?: PasswordRequirementOverrides;
|
|
30
30
|
dataClient: LayoutDataClient<TClient>;
|
|
31
|
+
urlOnLogon?: string;
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
export type UseRegisterFormResult = {
|
|
@@ -58,6 +59,7 @@ export const use_register_form = <TClient,>({
|
|
|
58
59
|
showNameField,
|
|
59
60
|
passwordRequirements,
|
|
60
61
|
dataClient,
|
|
62
|
+
urlOnLogon,
|
|
61
63
|
}: UseRegisterFormParams<TClient>): UseRegisterFormResult => {
|
|
62
64
|
const [values, setValues] = useState<RegisterFormValues>(buildInitialValues);
|
|
63
65
|
const [errors, setErrors] = useState<RegisterFormErrors>({});
|
|
@@ -203,6 +205,7 @@ export const use_register_form = <TClient,>({
|
|
|
203
205
|
name: values[REGISTER_FIELD_IDS.NAME] || undefined,
|
|
204
206
|
email: values[REGISTER_FIELD_IDS.EMAIL],
|
|
205
207
|
password: values[REGISTER_FIELD_IDS.PASSWORD],
|
|
208
|
+
url_on_logon: urlOnLogon,
|
|
206
209
|
}),
|
|
207
210
|
});
|
|
208
211
|
|
|
@@ -242,7 +245,7 @@ export const use_register_form = <TClient,>({
|
|
|
242
245
|
setIsSubmitting(false);
|
|
243
246
|
}
|
|
244
247
|
},
|
|
245
|
-
[values, passwordRequirements, dataClient],
|
|
248
|
+
[values, passwordRequirements, dataClient, urlOnLogon],
|
|
246
249
|
);
|
|
247
250
|
|
|
248
251
|
const handleCancel = useCallback(() => {
|
|
@@ -3,31 +3,32 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
6
|
+
import Link from "next/link";
|
|
7
|
+
import { Input } from "../../ui/input";
|
|
8
|
+
import { PasswordField } from "../shared/components/password_field";
|
|
9
|
+
import { FormFieldWrapper } from "../shared/components/form_field_wrapper";
|
|
10
|
+
import { FormHeader } from "../shared/components/form_header";
|
|
11
|
+
import { FormActionButtons } from "../shared/components/form_action_buttons";
|
|
12
|
+
import { TwoColumnAuthLayout } from "../shared/components/two_column_auth_layout";
|
|
13
|
+
import { AlreadyLoggedInGuard } from "../shared/components/already_logged_in_guard";
|
|
13
14
|
import {
|
|
14
15
|
type ButtonPaletteOverrides,
|
|
15
16
|
type LayoutFieldMapOverrides,
|
|
16
17
|
type LayoutLabelOverrides,
|
|
17
18
|
type PasswordRequirementOverrides,
|
|
18
|
-
} from "
|
|
19
|
+
} from "../shared/config/layout_customization";
|
|
19
20
|
import {
|
|
20
21
|
REGISTER_FIELD_IDS,
|
|
21
22
|
createRegisterFieldDefinitions,
|
|
22
23
|
resolveRegisterButtonPalette,
|
|
23
24
|
resolveRegisterLabels,
|
|
24
25
|
resolveRegisterPasswordRequirements,
|
|
25
|
-
} from "
|
|
26
|
+
} from "./config/register_field_config";
|
|
26
27
|
import {
|
|
27
28
|
use_register_form,
|
|
28
29
|
type UseRegisterFormResult,
|
|
29
|
-
} from "
|
|
30
|
-
import { type LayoutDataClient } from "
|
|
30
|
+
} from "./hooks/use_register_form";
|
|
31
|
+
import { type LayoutDataClient } from "../shared/data/layout_data_client";
|
|
31
32
|
|
|
32
33
|
// section: types
|
|
33
34
|
export type RegisterLayoutProps<TClient = unknown> = {
|
|
@@ -45,6 +46,9 @@ export type RegisterLayoutProps<TClient = unknown> = {
|
|
|
45
46
|
showReturnHomeButton?: boolean;
|
|
46
47
|
returnHomeButtonLabel?: string;
|
|
47
48
|
returnHomePath?: string;
|
|
49
|
+
signInPath?: string;
|
|
50
|
+
signInLabel?: string;
|
|
51
|
+
urlOnLogon?: string;
|
|
48
52
|
};
|
|
49
53
|
|
|
50
54
|
const ORDERED_FIELDS: RegisterFieldId[] = [
|
|
@@ -72,6 +76,9 @@ export default function register_layout<TClient>({
|
|
|
72
76
|
showReturnHomeButton = false,
|
|
73
77
|
returnHomeButtonLabel = "Return home",
|
|
74
78
|
returnHomePath = "/",
|
|
79
|
+
signInPath = "/hazo_auth/login",
|
|
80
|
+
signInLabel = "Sign in",
|
|
81
|
+
urlOnLogon,
|
|
75
82
|
}: RegisterLayoutProps<TClient>) {
|
|
76
83
|
const fieldDefinitions = createRegisterFieldDefinitions(field_overrides);
|
|
77
84
|
const resolvedLabels = resolveRegisterLabels(labels);
|
|
@@ -84,6 +91,7 @@ export default function register_layout<TClient>({
|
|
|
84
91
|
showNameField: show_name_field,
|
|
85
92
|
passwordRequirements: resolvedPasswordRequirements,
|
|
86
93
|
dataClient: data_client,
|
|
94
|
+
urlOnLogon: urlOnLogon,
|
|
87
95
|
});
|
|
88
96
|
|
|
89
97
|
const renderFields = (formState: UseRegisterFormResult) => {
|
|
@@ -193,6 +201,16 @@ export default function register_layout<TClient>({
|
|
|
193
201
|
submitAriaLabel="Submit registration form"
|
|
194
202
|
cancelAriaLabel="Cancel registration form"
|
|
195
203
|
/>
|
|
204
|
+
<div className="cls_register_layout_sign_in_link flex items-center justify-center gap-1 text-sm text-muted-foreground">
|
|
205
|
+
<span>Already have an account?</span>
|
|
206
|
+
<Link
|
|
207
|
+
href={signInPath}
|
|
208
|
+
className="cls_register_layout_sign_in_link_text text-primary underline-offset-4 hover:underline"
|
|
209
|
+
aria-label="Go to sign in page"
|
|
210
|
+
>
|
|
211
|
+
{signInLabel}
|
|
212
|
+
</Link>
|
|
213
|
+
</div>
|
|
196
214
|
{form.isSubmitting && (
|
|
197
215
|
<div className="cls_register_submitting_indicator text-sm text-slate-600 text-center">
|
|
198
216
|
Registering...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// file_description: reset password layout specific configuration helpers
|
|
2
2
|
// section: imports
|
|
3
|
-
import type { LayoutFieldMap, LayoutFieldMapOverrides } from "
|
|
3
|
+
import type { LayoutFieldMap, LayoutFieldMapOverrides } from "../../shared/config/layout_customization";
|
|
4
4
|
import {
|
|
5
5
|
resolveButtonPalette,
|
|
6
6
|
resolveFieldDefinitions,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
type PasswordRequirementOptions,
|
|
13
13
|
type PasswordRequirementOverrides,
|
|
14
14
|
resolvePasswordRequirements,
|
|
15
|
-
} from "
|
|
15
|
+
} from "../../shared/config/layout_customization";
|
|
16
16
|
|
|
17
17
|
// section: field_identifiers
|
|
18
18
|
export const RESET_PASSWORD_FIELD_IDS = {
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
import { useCallback, useMemo, useState, useEffect } from "react";
|
|
4
4
|
import { useSearchParams, useRouter } from "next/navigation";
|
|
5
5
|
import { toast } from "sonner";
|
|
6
|
-
import type { LayoutDataClient } from "
|
|
7
|
-
import type { PasswordRequirementOptions } from "
|
|
8
|
-
import { RESET_PASSWORD_FIELD_IDS, type ResetPasswordFieldId } from "
|
|
9
|
-
import { validatePassword } from "
|
|
6
|
+
import type { LayoutDataClient } from "../../shared/data/layout_data_client";
|
|
7
|
+
import type { PasswordRequirementOptions } from "../../shared/config/layout_customization";
|
|
8
|
+
import { RESET_PASSWORD_FIELD_IDS, type ResetPasswordFieldId } from "../config/reset_password_field_config";
|
|
9
|
+
import { validatePassword } from "../../shared/utils/validation";
|
|
10
10
|
|
|
11
11
|
// section: constants
|
|
12
12
|
const PASSWORD_FIELDS: Array<ResetPasswordFieldId> = [
|
|
@@ -3,31 +3,31 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
|
-
import { PasswordField } from "
|
|
7
|
-
import { FormFieldWrapper } from "
|
|
8
|
-
import { FormHeader } from "
|
|
9
|
-
import { FormActionButtons } from "
|
|
10
|
-
import { TwoColumnAuthLayout } from "
|
|
6
|
+
import { PasswordField } from "../shared/components/password_field";
|
|
7
|
+
import { FormFieldWrapper } from "../shared/components/form_field_wrapper";
|
|
8
|
+
import { FormHeader } from "../shared/components/form_header";
|
|
9
|
+
import { FormActionButtons } from "../shared/components/form_action_buttons";
|
|
10
|
+
import { TwoColumnAuthLayout } from "../shared/components/two_column_auth_layout";
|
|
11
11
|
import { CheckCircle, XCircle, Loader2 } from "lucide-react";
|
|
12
|
-
import { AlreadyLoggedInGuard } from "
|
|
12
|
+
import { AlreadyLoggedInGuard } from "../shared/components/already_logged_in_guard";
|
|
13
13
|
import {
|
|
14
14
|
type ButtonPaletteOverrides,
|
|
15
15
|
type LayoutFieldMapOverrides,
|
|
16
16
|
type LayoutLabelOverrides,
|
|
17
17
|
type PasswordRequirementOverrides,
|
|
18
|
-
} from "
|
|
18
|
+
} from "../shared/config/layout_customization";
|
|
19
19
|
import {
|
|
20
20
|
RESET_PASSWORD_FIELD_IDS,
|
|
21
21
|
createResetPasswordFieldDefinitions,
|
|
22
22
|
resolveResetPasswordButtonPalette,
|
|
23
23
|
resolveResetPasswordLabels,
|
|
24
24
|
resolveResetPasswordPasswordRequirements,
|
|
25
|
-
} from "
|
|
25
|
+
} from "./config/reset_password_field_config";
|
|
26
26
|
import {
|
|
27
27
|
use_reset_password_form,
|
|
28
28
|
type UseResetPasswordFormResult,
|
|
29
|
-
} from "
|
|
30
|
-
import { type LayoutDataClient } from "
|
|
29
|
+
} from "./hooks/use_reset_password_form";
|
|
30
|
+
import { type LayoutDataClient } from "../shared/data/layout_data_client";
|
|
31
31
|
import Link from "next/link";
|
|
32
32
|
|
|
33
33
|
// section: types
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// file_description: server component that chooses between sidebar shell and standalone shell
|
|
2
|
+
// section: imports
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import { SidebarLayoutWrapper } from "./sidebar_layout_wrapper";
|
|
5
|
+
import { StandaloneLayoutWrapper } from "./standalone_layout_wrapper";
|
|
6
|
+
import { get_ui_shell_config } from "../../../../lib/ui_shell_config.server";
|
|
7
|
+
|
|
8
|
+
// section: types
|
|
9
|
+
type AuthPageShellProps = {
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// section: component
|
|
14
|
+
export function AuthPageShell({ children }: AuthPageShellProps) {
|
|
15
|
+
const uiShellConfig = get_ui_shell_config();
|
|
16
|
+
|
|
17
|
+
if (uiShellConfig.layout_mode === "standalone") {
|
|
18
|
+
return (
|
|
19
|
+
<StandaloneLayoutWrapper
|
|
20
|
+
heading={uiShellConfig.standalone_heading}
|
|
21
|
+
description={uiShellConfig.standalone_description}
|
|
22
|
+
wrapperClassName={uiShellConfig.standalone_wrapper_class}
|
|
23
|
+
contentClassName={uiShellConfig.standalone_content_class}
|
|
24
|
+
showHeading={uiShellConfig.standalone_show_heading}
|
|
25
|
+
showDescription={uiShellConfig.standalone_show_description}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</StandaloneLayoutWrapper>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return <SidebarLayoutWrapper>{children}</SidebarLayoutWrapper>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// file_description: renders a simple full-width shell without the developer sidebar
|
|
2
|
+
// section: client_directive
|
|
3
|
+
"use client";
|
|
4
|
+
|
|
5
|
+
// section: imports
|
|
6
|
+
import { cn } from "../../../../lib/utils";
|
|
7
|
+
|
|
8
|
+
// section: types
|
|
9
|
+
export type StandaloneLayoutWrapperProps = {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
heading?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
wrapperClassName?: string;
|
|
14
|
+
contentClassName?: string;
|
|
15
|
+
showHeading?: boolean;
|
|
16
|
+
showDescription?: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// section: component
|
|
20
|
+
export function StandaloneLayoutWrapper({
|
|
21
|
+
children,
|
|
22
|
+
heading = "hazo auth",
|
|
23
|
+
description = "Drop-in authentication flows that inherit your existing theme.",
|
|
24
|
+
wrapperClassName,
|
|
25
|
+
contentClassName,
|
|
26
|
+
showHeading = true,
|
|
27
|
+
showDescription = true,
|
|
28
|
+
}: StandaloneLayoutWrapperProps) {
|
|
29
|
+
return (
|
|
30
|
+
<div className={cn("cls_standalone_layout_wrapper min-h-screen w-full bg-background", wrapperClassName)}>
|
|
31
|
+
<div className={cn("cls_standalone_layout_content mx-auto flex w-full max-w-5xl flex-col gap-8 p-6", contentClassName)}>
|
|
32
|
+
{(showHeading || showDescription) && (
|
|
33
|
+
<div className="cls_standalone_layout_header text-center">
|
|
34
|
+
{showHeading && (
|
|
35
|
+
<h1 className="cls_standalone_layout_title text-2xl font-semibold tracking-tight text-foreground">
|
|
36
|
+
{heading}
|
|
37
|
+
</h1>
|
|
38
|
+
)}
|
|
39
|
+
{showDescription && (
|
|
40
|
+
<p className="cls_standalone_layout_description mt-2 text-sm text-muted-foreground">
|
|
41
|
+
{description}
|
|
42
|
+
</p>
|
|
43
|
+
)}
|
|
44
|
+
</div>
|
|
45
|
+
)}
|
|
46
|
+
<div className="cls_standalone_layout_body">{children}</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { useState, useEffect, useMemo } from "react";
|
|
7
|
-
import { Button } from "
|
|
8
|
-
import { Checkbox } from "
|
|
7
|
+
import { Button } from "../../../ui/button";
|
|
8
|
+
import { Checkbox } from "../../../ui/checkbox";
|
|
9
9
|
import {
|
|
10
10
|
Table,
|
|
11
11
|
TableBody,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
TableHead,
|
|
14
14
|
TableHeader,
|
|
15
15
|
TableRow,
|
|
16
|
-
} from "
|
|
16
|
+
} from "../../../ui/table";
|
|
17
17
|
import {
|
|
18
18
|
Dialog,
|
|
19
19
|
DialogContent,
|
|
@@ -21,12 +21,12 @@ import {
|
|
|
21
21
|
DialogFooter,
|
|
22
22
|
DialogHeader,
|
|
23
23
|
DialogTitle,
|
|
24
|
-
} from "
|
|
25
|
-
import { Input } from "
|
|
26
|
-
import { Label } from "
|
|
24
|
+
} from "../../../ui/dialog";
|
|
25
|
+
import { Input } from "../../../ui/input";
|
|
26
|
+
import { Label } from "../../../ui/label";
|
|
27
27
|
import { Plus, Save, Loader2, CircleCheck, CircleX } from "lucide-react";
|
|
28
28
|
import { toast } from "sonner";
|
|
29
|
-
import { Avatar, AvatarImage, AvatarFallback } from "
|
|
29
|
+
import { Avatar, AvatarImage, AvatarFallback } from "../../../ui/avatar";
|
|
30
30
|
|
|
31
31
|
// section: types
|
|
32
32
|
export type RolesMatrixData = {
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { useState, useEffect, useCallback } from "react";
|
|
7
|
-
import { Tabs, TabsContent, TabsList, TabsTrigger } from "
|
|
8
|
-
import { use_hazo_auth } from "
|
|
7
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../ui/tabs";
|
|
8
|
+
import { use_hazo_auth } from "../shared/hooks/use_hazo_auth";
|
|
9
9
|
import {
|
|
10
10
|
Table,
|
|
11
11
|
TableBody,
|
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
TableHead,
|
|
14
14
|
TableHeader,
|
|
15
15
|
TableRow,
|
|
16
|
-
} from "
|
|
17
|
-
import { Button } from "
|
|
18
|
-
import { Avatar, AvatarImage, AvatarFallback } from "
|
|
16
|
+
} from "../../ui/table";
|
|
17
|
+
import { Button } from "../../ui/button";
|
|
18
|
+
import { Avatar, AvatarImage, AvatarFallback } from "../../ui/avatar";
|
|
19
19
|
import {
|
|
20
20
|
AlertDialog,
|
|
21
21
|
AlertDialogAction,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
AlertDialogFooter,
|
|
26
26
|
AlertDialogHeader,
|
|
27
27
|
AlertDialogTitle,
|
|
28
|
-
} from "
|
|
28
|
+
} from "../../ui/alert-dialog";
|
|
29
29
|
import {
|
|
30
30
|
Dialog,
|
|
31
31
|
DialogContent,
|
|
@@ -33,13 +33,13 @@ import {
|
|
|
33
33
|
DialogFooter,
|
|
34
34
|
DialogHeader,
|
|
35
35
|
DialogTitle,
|
|
36
|
-
} from "
|
|
37
|
-
import { Input } from "
|
|
38
|
-
import { Label } from "
|
|
36
|
+
} from "../../ui/dialog";
|
|
37
|
+
import { Input } from "../../ui/input";
|
|
38
|
+
import { Label } from "../../ui/label";
|
|
39
39
|
import { RolesMatrix } from "./components/roles_matrix";
|
|
40
40
|
import { UserX, KeyRound, Edit, Trash2, Loader2, CircleCheck, CircleX, Plus, UserPlus } from "lucide-react";
|
|
41
41
|
import { toast } from "sonner";
|
|
42
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "
|
|
42
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../ui/tooltip";
|
|
43
43
|
|
|
44
44
|
// section: types
|
|
45
45
|
export type UserManagementLayoutProps = {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
|
5
5
|
|
|
6
|
-
import { cn } from "
|
|
7
|
-
import { buttonVariants } from "
|
|
6
|
+
import { cn } from "../../lib/utils"
|
|
7
|
+
import { buttonVariants } from "./button"
|
|
8
8
|
|
|
9
9
|
const AlertDialog = AlertDialogPrimitive.Root
|
|
10
10
|
|
|
@@ -2,7 +2,7 @@ import * as React from "react"
|
|
|
2
2
|
import { Slot } from "@radix-ui/react-slot"
|
|
3
3
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
4
|
|
|
5
|
-
import { cn } from "
|
|
5
|
+
import { cn } from "../../lib/utils"
|
|
6
6
|
|
|
7
7
|
const buttonVariants = cva(
|
|
8
8
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
@@ -4,7 +4,7 @@ import * as React from "react"
|
|
|
4
4
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
|
5
5
|
import { Check } from "lucide-react"
|
|
6
6
|
|
|
7
|
-
import { cn } from "
|
|
7
|
+
import { cn } from "../../lib/utils"
|
|
8
8
|
|
|
9
9
|
const Checkbox = React.forwardRef<
|
|
10
10
|
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
|
@@ -4,7 +4,7 @@ import * as React from "react"
|
|
|
4
4
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
|
5
5
|
import { Check, ChevronRight, Circle } from "lucide-react"
|
|
6
6
|
|
|
7
|
-
import { cn } from "
|
|
7
|
+
import { cn } from "../../lib/utils"
|
|
8
8
|
|
|
9
9
|
const DropdownMenu = DropdownMenuPrimitive.Root
|
|
10
10
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { HelpCircle } from "lucide-react";
|
|
7
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "
|
|
7
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./tooltip";
|
|
8
8
|
|
|
9
9
|
// section: types
|
|
10
10
|
export type HazoUITooltipProps = {
|