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.
Files changed (108) hide show
  1. package/README.md +72 -1
  2. package/hazo_auth_config.example.ini +41 -0
  3. package/instrumentation.ts +2 -2
  4. package/package.json +4 -3
  5. package/scripts/init_users.ts +378 -0
  6. package/src/app/api/hazo_auth/auth/upload_profile_picture/route.ts +8 -8
  7. package/src/app/api/hazo_auth/change_password/route.ts +7 -7
  8. package/src/app/api/hazo_auth/forgot_password/route.ts +4 -4
  9. package/src/app/api/hazo_auth/get_auth/route.ts +4 -4
  10. package/src/app/api/hazo_auth/invalidate_cache/route.ts +5 -5
  11. package/src/app/api/hazo_auth/library_photos/route.ts +3 -3
  12. package/src/app/api/hazo_auth/login/route.ts +31 -5
  13. package/src/app/api/hazo_auth/logout/route.ts +4 -4
  14. package/src/app/api/hazo_auth/me/route.ts +1 -1
  15. package/src/app/api/hazo_auth/profile_picture/[filename]/route.ts +1 -1
  16. package/src/app/api/hazo_auth/register/route.ts +17 -14
  17. package/src/app/api/hazo_auth/remove_profile_picture/route.ts +5 -5
  18. package/src/app/api/hazo_auth/resend_verification/route.ts +4 -4
  19. package/src/app/api/hazo_auth/reset_password/route.ts +5 -5
  20. package/src/app/api/hazo_auth/update_user/route.ts +5 -5
  21. package/src/app/api/hazo_auth/upload_profile_picture/route.ts +8 -8
  22. package/src/app/api/hazo_auth/user_management/permissions/route.ts +4 -4
  23. package/src/app/api/hazo_auth/user_management/roles/route.ts +5 -5
  24. package/src/app/api/hazo_auth/user_management/users/roles/route.ts +5 -5
  25. package/src/app/api/hazo_auth/user_management/users/route.ts +6 -6
  26. package/src/app/api/hazo_auth/validate_reset_token/route.ts +4 -4
  27. package/src/app/api/hazo_auth/verify_email/route.ts +4 -4
  28. package/src/app/api/migrations/apply/route.ts +3 -3
  29. package/src/app/hazo_auth/forgot_password/forgot_password_page_client.tsx +4 -4
  30. package/src/app/hazo_auth/forgot_password/page.tsx +4 -4
  31. package/src/app/hazo_auth/login/login_page_client.tsx +20 -5
  32. package/src/app/hazo_auth/login/page.tsx +17 -5
  33. package/src/app/hazo_auth/my_settings/my_settings_page_client.tsx +3 -3
  34. package/src/app/hazo_auth/my_settings/page.tsx +4 -4
  35. package/src/app/hazo_auth/register/page.tsx +15 -5
  36. package/src/app/hazo_auth/register/register_page_client.tsx +13 -4
  37. package/src/app/hazo_auth/reset_password/page.tsx +4 -4
  38. package/src/app/hazo_auth/reset_password/reset_password_page_client.tsx +4 -4
  39. package/src/app/hazo_auth/user_management/page.tsx +3 -3
  40. package/src/app/hazo_auth/user_management/user_management_page_client.tsx +1 -1
  41. package/src/app/hazo_auth/verify_email/page.tsx +4 -4
  42. package/src/app/hazo_auth/verify_email/verify_email_page_client.tsx +4 -4
  43. package/src/app/hazo_connect/api/sqlite/data/route.ts +1 -1
  44. package/src/app/hazo_connect/api/sqlite/schema/route.ts +1 -1
  45. package/src/app/hazo_connect/api/sqlite/tables/route.ts +1 -1
  46. package/src/app/layout.tsx +1 -1
  47. package/src/app/page.tsx +1 -1
  48. package/src/components/layouts/email_verification/config/email_verification_field_config.ts +2 -2
  49. package/src/components/layouts/email_verification/hooks/use_email_verification.ts +3 -3
  50. package/src/components/layouts/email_verification/index.tsx +11 -11
  51. package/src/components/layouts/forgot_password/config/forgot_password_field_config.ts +2 -2
  52. package/src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts +3 -3
  53. package/src/components/layouts/forgot_password/index.tsx +10 -10
  54. package/src/components/layouts/login/config/login_field_config.ts +2 -2
  55. package/src/components/layouts/login/hooks/use_login_form.ts +18 -13
  56. package/src/components/layouts/login/index.tsx +39 -11
  57. package/src/components/layouts/my_settings/components/editable_field.tsx +3 -3
  58. package/src/components/layouts/my_settings/components/password_change_dialog.tsx +5 -5
  59. package/src/components/layouts/my_settings/components/profile_picture_dialog.tsx +4 -4
  60. package/src/components/layouts/my_settings/components/profile_picture_display.tsx +2 -2
  61. package/src/components/layouts/my_settings/components/profile_picture_gravatar_tab.tsx +3 -3
  62. package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +5 -5
  63. package/src/components/layouts/my_settings/components/profile_picture_upload_tab.tsx +4 -4
  64. package/src/components/layouts/my_settings/config/my_settings_field_config.ts +2 -2
  65. package/src/components/layouts/my_settings/hooks/use_my_settings.ts +2 -2
  66. package/src/components/layouts/my_settings/index.tsx +5 -5
  67. package/src/components/layouts/register/config/register_field_config.ts +2 -2
  68. package/src/components/layouts/register/hooks/use_register_form.ts +8 -5
  69. package/src/components/layouts/register/index.tsx +29 -11
  70. package/src/components/layouts/reset_password/config/reset_password_field_config.ts +2 -2
  71. package/src/components/layouts/reset_password/hooks/use_reset_password_form.ts +4 -4
  72. package/src/components/layouts/reset_password/index.tsx +10 -10
  73. package/src/components/layouts/shared/components/auth_page_shell.tsx +36 -0
  74. package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +53 -0
  75. package/src/components/layouts/user_management/components/roles_matrix.tsx +7 -7
  76. package/src/components/layouts/user_management/index.tsx +10 -10
  77. package/src/components/ui/alert-dialog.tsx +2 -2
  78. package/src/components/ui/avatar.tsx +1 -1
  79. package/src/components/ui/button.tsx +1 -1
  80. package/src/components/ui/checkbox.tsx +1 -1
  81. package/src/components/ui/dialog.tsx +1 -1
  82. package/src/components/ui/dropdown-menu.tsx +1 -1
  83. package/src/components/ui/hazo_ui_tooltip.tsx +1 -1
  84. package/src/components/ui/input.tsx +1 -1
  85. package/src/components/ui/label.tsx +1 -1
  86. package/src/components/ui/separator.tsx +1 -1
  87. package/src/components/ui/sheet.tsx +1 -1
  88. package/src/components/ui/sidebar.tsx +8 -8
  89. package/src/components/ui/skeleton.tsx +1 -1
  90. package/src/components/ui/switch.tsx +1 -1
  91. package/src/components/ui/table.tsx +1 -1
  92. package/src/components/ui/tabs.tsx +1 -1
  93. package/src/components/ui/tooltip.tsx +1 -1
  94. package/src/components/ui/vertical-tabs.tsx +1 -1
  95. package/src/lib/app_logger.ts +1 -1
  96. package/src/lib/config/config_loader.server.ts +20 -5
  97. package/src/lib/login_config.server.ts +25 -0
  98. package/src/lib/register_config.server.ts +17 -1
  99. package/src/lib/services/login_service.ts +19 -3
  100. package/src/lib/services/registration_service.ts +25 -4
  101. package/src/lib/services/user_update_service.ts +16 -3
  102. package/src/lib/ui_shell_config.server.ts +73 -0
  103. package/src/lib/utils/error_sanitizer.ts +75 -0
  104. package/src/stories/email_verification_layout.stories.tsx +2 -2
  105. package/src/stories/forgot_password_layout.stories.tsx +2 -2
  106. package/src/stories/login_layout.stories.tsx +2 -2
  107. package/src/stories/register_layout.stories.tsx +2 -2
  108. package/tsconfig.json +1 -4
@@ -1,9 +1,9 @@
1
1
  // file_description: API route for listing library photo categories and photos in categories
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_library_categories, get_library_photos } from "@/lib/services/profile_picture_service";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
4
+ import { get_library_categories, get_library_photos } from "../../../../lib/services/profile_picture_service";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
7
7
 
8
8
  // section: route_config
9
9
  export const dynamic = 'force-dynamic';
@@ -1,11 +1,12 @@
1
1
  // file_description: API route for user login authentication using hazo_connect
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { authenticate_user } from "@/lib/services/login_service";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { authenticate_user } from "../../../../lib/services/login_service";
7
7
  import { createCrudService } from "hazo_connect/server";
8
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
8
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
9
+ import { get_login_config } from "../../../../lib/login_config.server";
9
10
 
10
11
  // section: api_handler
11
12
  export async function POST(request: NextRequest) {
@@ -13,7 +14,7 @@ export async function POST(request: NextRequest) {
13
14
 
14
15
  try {
15
16
  const body = await request.json();
16
- const { email, password } = body;
17
+ const { email, password, url_on_logon } = body;
17
18
 
18
19
  // Validate input
19
20
  if (!email || !password) {
@@ -106,6 +107,30 @@ export async function POST(request: NextRequest) {
106
107
  const user = users && users.length > 0 ? users[0] : null;
107
108
  const user_name = user?.name as string | undefined;
108
109
 
110
+ // Determine redirect URL priority:
111
+ // 1. url_on_logon from request body (if valid)
112
+ // 2. stored_url_on_logon from database (if available)
113
+ // 3. redirect_route_on_successful_login from config
114
+ // 4. Default to "/"
115
+
116
+ let redirectUrl = "/";
117
+
118
+ // Check priority 1: Request body
119
+ if (url_on_logon && typeof url_on_logon === "string" && url_on_logon.startsWith("/") && !url_on_logon.startsWith("//")) {
120
+ redirectUrl = url_on_logon;
121
+ }
122
+ // Check priority 2: Stored URL from DB
123
+ else if (result.stored_url_on_logon && typeof result.stored_url_on_logon === "string") {
124
+ redirectUrl = result.stored_url_on_logon;
125
+ }
126
+ // Check priority 3: Config
127
+ else {
128
+ const loginConfig = get_login_config();
129
+ if (loginConfig.redirectRoute) {
130
+ redirectUrl = loginConfig.redirectRoute;
131
+ }
132
+ }
133
+
109
134
  // Create response with cookies
110
135
  const response = NextResponse.json(
111
136
  {
@@ -114,6 +139,7 @@ export async function POST(request: NextRequest) {
114
139
  user_id: user_id,
115
140
  email,
116
141
  name: user_name,
142
+ redirectUrl,
117
143
  },
118
144
  { status: 200 }
119
145
  );
@@ -1,10 +1,10 @@
1
1
  // file_description: API route for user logout
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { create_app_logger } from "@/lib/app_logger";
5
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
6
- import { get_auth_cache } from "@/lib/auth/auth_cache";
7
- import { get_auth_utility_config } from "@/lib/auth_utility_config.server";
4
+ import { create_app_logger } from "../../../../lib/app_logger";
5
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
6
+ import { get_auth_cache } from "../../../../lib/auth/auth_cache";
7
+ import { get_auth_utility_config } from "../../../../lib/auth_utility_config.server";
8
8
 
9
9
  // section: api_handler
10
10
  export async function POST(request: NextRequest) {
@@ -1,7 +1,7 @@
1
1
  // file_description: API route to get current authenticated user information
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_authenticated_user_with_response } from "@/lib/auth/auth_utils.server";
4
+ import { get_authenticated_user_with_response } from "../../../../lib/auth/auth_utils.server";
5
5
 
6
6
  // section: api_handler
7
7
  export async function GET(request: NextRequest) {
@@ -1,7 +1,7 @@
1
1
  // file_description: API route to serve uploaded profile pictures
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_profile_picture_config } from "@/lib/profile_picture_config.server";
4
+ import { get_profile_picture_config } from "../../../../../lib/profile_picture_config.server";
5
5
  import fs from "fs";
6
6
  import path from "path";
7
7
 
@@ -1,10 +1,11 @@
1
1
  // file_description: API route for user registration using hazo_connect to insert into hazo_users table
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { register_user } from "@/lib/services/registration_service";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { register_user } from "../../../../lib/services/registration_service";
7
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
8
+ import { sanitize_error_for_user } from "../../../../lib/utils/error_sanitizer";
8
9
 
9
10
  // section: api_handler
10
11
  export async function POST(request: NextRequest) {
@@ -12,7 +13,7 @@ export async function POST(request: NextRequest) {
12
13
 
13
14
  try {
14
15
  const body = await request.json();
15
- const { name, email, password } = body;
16
+ const { name, email, password, url_on_logon } = body;
16
17
 
17
18
  // Validate input
18
19
  if (!email || !password) {
@@ -52,6 +53,7 @@ export async function POST(request: NextRequest) {
52
53
  email,
53
54
  password,
54
55
  name,
56
+ url_on_logon,
55
57
  });
56
58
 
57
59
  if (!result.success) {
@@ -87,18 +89,19 @@ export async function POST(request: NextRequest) {
87
89
  { status: 201 }
88
90
  );
89
91
  } catch (error) {
90
- const error_message = error instanceof Error ? error.message : "Unknown error";
91
- const error_stack = error instanceof Error ? error.stack : undefined;
92
-
93
- logger.error("registration_error", {
94
- filename: get_filename(),
95
- line_number: get_line_number(),
96
- error_message,
97
- error_stack,
92
+ const user_friendly_error = sanitize_error_for_user(error, {
93
+ logToConsole: true,
94
+ logToLogger: true,
95
+ logger,
96
+ context: {
97
+ filename: get_filename(),
98
+ line_number: get_line_number(),
99
+ operation: "register_api_route",
100
+ },
98
101
  });
99
102
 
100
103
  return NextResponse.json(
101
- { error: "Registration failed. Please try again." },
104
+ { error: user_friendly_error },
102
105
  { status: 500 }
103
106
  );
104
107
  }
@@ -1,10 +1,10 @@
1
1
  // file_description: API route for removing profile pictures
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { remove_user_profile_picture } from "@/lib/services/profile_picture_remove_service";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { remove_user_profile_picture } from "../../../../lib/services/profile_picture_remove_service";
7
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
8
8
 
9
9
  // section: api_handler
10
10
  export async function DELETE(request: NextRequest) {
@@ -14,7 +14,7 @@ export async function DELETE(request: NextRequest) {
14
14
  // Use centralized auth check
15
15
  let user_id: string;
16
16
  try {
17
- const { require_auth } = await import("@/lib/auth/auth_utils.server");
17
+ const { require_auth } = await import("../../../../lib/auth/auth_utils.server");
18
18
  const user = await require_auth(request);
19
19
  user_id = user.user_id;
20
20
  } catch (error) {
@@ -1,10 +1,10 @@
1
1
  // file_description: API route for resending email verification using hazo_connect
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { resend_verification_email } from "@/lib/services/email_verification_service";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { resend_verification_email } from "../../../../lib/services/email_verification_service";
7
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
8
8
 
9
9
  // section: api_handler
10
10
  export async function POST(request: NextRequest) {
@@ -1,11 +1,11 @@
1
1
  // file_description: API route for resetting user password using a reset token
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { reset_password } from "@/lib/services/password_reset_service";
6
- import { create_app_logger } from "@/lib/app_logger";
7
- import { get_password_requirements_config } from "@/lib/password_requirements_config.server";
8
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { reset_password } from "../../../../lib/services/password_reset_service";
6
+ import { create_app_logger } from "../../../../lib/app_logger";
7
+ import { get_password_requirements_config } from "../../../../lib/password_requirements_config.server";
8
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
9
9
 
10
10
  // section: api_handler
11
11
  export async function POST(request: NextRequest) {
@@ -1,11 +1,11 @@
1
1
  // file_description: API route for updating user profile information
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { update_user_profile } from "@/lib/services/user_update_service";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
8
- import { require_auth } from "@/lib/auth/auth_utils.server";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { update_user_profile } from "../../../../lib/services/user_update_service";
7
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
8
+ import { require_auth } from "../../../../lib/auth/auth_utils.server";
9
9
 
10
10
  // section: api_handler
11
11
  export async function PATCH(request: NextRequest) {
@@ -1,14 +1,14 @@
1
1
  // file_description: API route for uploading profile pictures
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { get_profile_picture_config } from "@/lib/profile_picture_config.server";
7
- import { get_file_types_config } from "@/lib/file_types_config.server";
8
- import { update_user_profile_picture } from "@/lib/services/profile_picture_service";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { get_profile_picture_config } from "../../../../lib/profile_picture_config.server";
7
+ import { get_file_types_config } from "../../../../lib/file_types_config.server";
8
+ import { update_user_profile_picture } from "../../../../lib/services/profile_picture_service";
9
9
  import { createCrudService } from "hazo_connect/server";
10
- import { map_db_source_to_ui } from "@/lib/services/profile_picture_source_mapper";
11
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
10
+ import { map_db_source_to_ui } from "../../../../lib/services/profile_picture_source_mapper";
11
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
12
12
  import fs from "fs";
13
13
  import path from "path";
14
14
 
@@ -20,7 +20,7 @@ export async function POST(request: NextRequest) {
20
20
  // Use centralized auth check
21
21
  let user_id: string;
22
22
  try {
23
- const { require_auth } = await import("@/lib/auth/auth_utils.server");
23
+ const { require_auth } = await import("../../../../lib/auth/auth_utils.server");
24
24
  const user = await require_auth(request);
25
25
  user_id = user.user_id;
26
26
  } catch (error) {
@@ -1,11 +1,11 @@
1
1
  // file_description: API route for permissions management operations (list, migrate from config, update, delete)
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
4
+ import { get_hazo_connect_instance } from "../../../../../lib/hazo_connect_instance.server";
5
5
  import { createCrudService } from "hazo_connect/server";
6
- import { create_app_logger } from "@/lib/app_logger";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
8
- import { get_user_management_config } from "@/lib/user_management_config.server";
6
+ import { create_app_logger } from "../../../../../lib/app_logger";
7
+ import { get_filename, get_line_number } from "../../../../../lib/utils/api_route_helpers";
8
+ import { get_user_management_config } from "../../../../../lib/user_management_config.server";
9
9
 
10
10
  // section: route_config
11
11
  export const dynamic = 'force-dynamic';
@@ -1,12 +1,12 @@
1
1
  // file_description: API route for roles management operations (list roles with permissions, create role, update role permissions)
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
4
+ import { get_hazo_connect_instance } from "../../../../../lib/hazo_connect_instance.server";
5
5
  import { createCrudService, getSqliteAdminService } from "hazo_connect/server";
6
- import { create_app_logger } from "@/lib/app_logger";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
8
- import { get_auth_cache } from "@/lib/auth/auth_cache";
9
- import { get_auth_utility_config } from "@/lib/auth_utility_config.server";
6
+ import { create_app_logger } from "../../../../../lib/app_logger";
7
+ import { get_filename, get_line_number } from "../../../../../lib/utils/api_route_helpers";
8
+ import { get_auth_cache } from "../../../../../lib/auth/auth_cache";
9
+ import { get_auth_utility_config } from "../../../../../lib/auth_utility_config.server";
10
10
 
11
11
  // section: route_config
12
12
  export const dynamic = 'force-dynamic';
@@ -1,12 +1,12 @@
1
1
  // file_description: API route for managing user roles (assigning roles to users)
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
4
+ import { get_hazo_connect_instance } from "../../../../../../lib/hazo_connect_instance.server";
5
5
  import { createCrudService, getSqliteAdminService } from "hazo_connect/server";
6
- import { create_app_logger } from "@/lib/app_logger";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
8
- import { get_auth_cache } from "@/lib/auth/auth_cache";
9
- import { get_auth_utility_config } from "@/lib/auth_utility_config.server";
6
+ import { create_app_logger } from "../../../../../../lib/app_logger";
7
+ import { get_filename, get_line_number } from "../../../../../../lib/utils/api_route_helpers";
8
+ import { get_auth_cache } from "../../../../../../lib/auth/auth_cache";
9
+ import { get_auth_utility_config } from "../../../../../../lib/auth_utility_config.server";
10
10
 
11
11
  // section: route_config
12
12
  export const dynamic = 'force-dynamic';
@@ -1,13 +1,13 @@
1
1
  // file_description: API route for user management operations (list users, deactivate, reset password)
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
4
+ import { get_hazo_connect_instance } from "../../../../../lib/hazo_connect_instance.server";
5
5
  import { createCrudService } from "hazo_connect/server";
6
- import { create_app_logger } from "@/lib/app_logger";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
8
- import { request_password_reset } from "@/lib/services/password_reset_service";
9
- import { get_auth_cache } from "@/lib/auth/auth_cache";
10
- import { get_auth_utility_config } from "@/lib/auth_utility_config.server";
6
+ import { create_app_logger } from "../../../../../lib/app_logger";
7
+ import { get_filename, get_line_number } from "../../../../../lib/utils/api_route_helpers";
8
+ import { request_password_reset } from "../../../../../lib/services/password_reset_service";
9
+ import { get_auth_cache } from "../../../../../lib/auth/auth_cache";
10
+ import { get_auth_utility_config } from "../../../../../lib/auth_utility_config.server";
11
11
 
12
12
  // section: route_config
13
13
  export const dynamic = 'force-dynamic';
@@ -1,10 +1,10 @@
1
1
  // file_description: API route for validating password reset token without resetting password
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { validate_password_reset_token } from "@/lib/services/password_reset_service";
6
- import { create_app_logger } from "@/lib/app_logger";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { validate_password_reset_token } from "../../../../lib/services/password_reset_service";
6
+ import { create_app_logger } from "../../../../lib/app_logger";
7
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
8
8
 
9
9
  // section: route_config
10
10
  export const dynamic = 'force-dynamic';
@@ -1,10 +1,10 @@
1
1
  // file_description: API route for email verification using hazo_connect
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
6
- import { verify_email_token } from "@/lib/services/email_verification_service";
7
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
+ import { verify_email_token } from "../../../../lib/services/email_verification_service";
7
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
8
8
 
9
9
  // section: route_config
10
10
  export const dynamic = 'force-dynamic';
@@ -1,11 +1,11 @@
1
1
  // file_description: API route to manually apply database migrations
2
2
  // section: imports
3
3
  import { NextRequest, NextResponse } from "next/server";
4
- import { get_hazo_connect_instance } from "@/lib/hazo_connect_instance.server";
5
- import { create_app_logger } from "@/lib/app_logger";
4
+ import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
5
+ import { create_app_logger } from "../../../../lib/app_logger";
6
6
  import fs from "fs";
7
7
  import path from "path";
8
- import { get_filename, get_line_number } from "@/lib/utils/api_route_helpers";
8
+ import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
9
9
 
10
10
  // section: api_handler
11
11
  export async function POST(request: NextRequest) {
@@ -4,10 +4,10 @@
4
4
 
5
5
  // section: imports
6
6
  import { useEffect, useState } from "react";
7
- import forgot_password_layout from "@/components/layouts/forgot_password";
8
- import { createLayoutDataClient } from "@/components/layouts/shared/data/layout_data_client";
9
- import { create_sqlite_hazo_connect } from "@/lib/hazo_connect_setup";
10
- import type { LayoutDataClient } from "@/components/layouts/shared/data/layout_data_client";
7
+ import forgot_password_layout from "../../../components/layouts/forgot_password";
8
+ import { createLayoutDataClient } from "../../../components/layouts/shared/data/layout_data_client";
9
+ import { create_sqlite_hazo_connect } from "../../../lib/hazo_connect_setup";
10
+ import type { LayoutDataClient } from "../../../components/layouts/shared/data/layout_data_client";
11
11
 
12
12
  // section: types
13
13
  type ForgotPasswordPageClientProps = {
@@ -1,8 +1,8 @@
1
1
  // file_description: render the forgot password page shell and mount the forgot password layout component within sidebar
2
2
  // section: imports
3
- import { SidebarLayoutWrapper } from "@/components/layouts/shared/components/sidebar_layout_wrapper";
3
+ import { AuthPageShell } from "../../../components/layouts/shared/components/auth_page_shell";
4
4
  import { ForgotPasswordPageClient } from "./forgot_password_page_client";
5
- import { get_forgot_password_config } from "@/lib/forgot_password_config.server";
5
+ import { get_forgot_password_config } from "../../../lib/forgot_password_config.server";
6
6
 
7
7
  // section: component
8
8
  export default function forgot_password_page() {
@@ -10,7 +10,7 @@ export default function forgot_password_page() {
10
10
  const forgotPasswordConfig = get_forgot_password_config();
11
11
 
12
12
  return (
13
- <SidebarLayoutWrapper>
13
+ <AuthPageShell>
14
14
  <ForgotPasswordPageClient
15
15
  alreadyLoggedInMessage={forgotPasswordConfig.alreadyLoggedInMessage}
16
16
  showLogoutButton={forgotPasswordConfig.showLogoutButton}
@@ -18,7 +18,7 @@ export default function forgot_password_page() {
18
18
  returnHomeButtonLabel={forgotPasswordConfig.returnHomeButtonLabel}
19
19
  returnHomePath={forgotPasswordConfig.returnHomePath}
20
20
  />
21
- </SidebarLayoutWrapper>
21
+ </AuthPageShell>
22
22
  );
23
23
  }
24
24
 
@@ -4,11 +4,11 @@
4
4
 
5
5
  // section: imports
6
6
  import { useEffect, useState } from "react";
7
- import login_layout from "@/components/layouts/login";
8
- import { createLayoutDataClient } from "@/components/layouts/shared/data/layout_data_client";
9
- import { create_sqlite_hazo_connect } from "@/lib/hazo_connect_setup";
10
- import { create_app_logger } from "@/lib/app_logger";
11
- import type { LayoutDataClient } from "@/components/layouts/shared/data/layout_data_client";
7
+ import login_layout from "../../../components/layouts/login";
8
+ import { createLayoutDataClient } from "../../../components/layouts/shared/data/layout_data_client";
9
+ import { create_sqlite_hazo_connect } from "../../../lib/hazo_connect_setup";
10
+ import { create_app_logger } from "../../../lib/app_logger";
11
+ import type { LayoutDataClient } from "../../../components/layouts/shared/data/layout_data_client";
12
12
 
13
13
  // section: types
14
14
  type LoginPageClientProps = {
@@ -19,6 +19,11 @@ type LoginPageClientProps = {
19
19
  showReturnHomeButton?: boolean;
20
20
  returnHomeButtonLabel?: string;
21
21
  returnHomePath?: string;
22
+ forgotPasswordPath?: string;
23
+ forgotPasswordLabel?: string;
24
+ createAccountPath?: string;
25
+ createAccountLabel?: string;
26
+ urlOnLogon?: string;
22
27
  };
23
28
 
24
29
  // section: component
@@ -30,6 +35,11 @@ export function LoginPageClient({
30
35
  showReturnHomeButton,
31
36
  returnHomeButtonLabel,
32
37
  returnHomePath,
38
+ forgotPasswordPath,
39
+ forgotPasswordLabel,
40
+ createAccountPath,
41
+ createAccountLabel,
42
+ urlOnLogon,
33
43
  }: LoginPageClientProps) {
34
44
  const [dataClient, setDataClient] = useState<LayoutDataClient<unknown> | null>(null);
35
45
  const [logger, setLogger] = useState<ReturnType<typeof create_app_logger> | null>(null);
@@ -65,6 +75,11 @@ export function LoginPageClient({
65
75
  showReturnHomeButton={showReturnHomeButton}
66
76
  returnHomeButtonLabel={returnHomeButtonLabel}
67
77
  returnHomePath={returnHomePath}
78
+ forgot_password_path={forgotPasswordPath}
79
+ forgot_password_label={forgotPasswordLabel}
80
+ create_account_path={createAccountPath}
81
+ create_account_label={createAccountLabel}
82
+ urlOnLogon={urlOnLogon}
68
83
  />
69
84
  );
70
85
  }
@@ -1,16 +1,23 @@
1
1
  // file_description: render the login page shell and mount the login layout component within sidebar
2
2
  // section: imports
3
- import { SidebarLayoutWrapper } from "@/components/layouts/shared/components/sidebar_layout_wrapper";
3
+ import { AuthPageShell } from "../../../components/layouts/shared/components/auth_page_shell";
4
4
  import { LoginPageClient } from "./login_page_client";
5
- import { get_login_config } from "@/lib/login_config.server";
5
+ import { get_login_config } from "../../../lib/login_config.server";
6
6
 
7
7
  // section: component
8
- export default function login_page() {
8
+ export default function login_page({
9
+ searchParams,
10
+ }: {
11
+ searchParams: { [key: string]: string | string[] | undefined };
12
+ }) {
9
13
  // Read login configuration from hazo_auth_config.ini (server-side)
10
14
  const loginConfig = get_login_config();
11
15
 
16
+ // Get url_on_logon from query params (if any)
17
+ const urlOnLogon = typeof searchParams.url_on_logon === "string" ? searchParams.url_on_logon : undefined;
18
+
12
19
  return (
13
- <SidebarLayoutWrapper>
20
+ <AuthPageShell>
14
21
  <LoginPageClient
15
22
  redirectRoute={loginConfig.redirectRoute}
16
23
  successMessage={loginConfig.successMessage}
@@ -19,8 +26,13 @@ export default function login_page() {
19
26
  showReturnHomeButton={loginConfig.showReturnHomeButton}
20
27
  returnHomeButtonLabel={loginConfig.returnHomeButtonLabel}
21
28
  returnHomePath={loginConfig.returnHomePath}
29
+ forgotPasswordPath={loginConfig.forgotPasswordPath}
30
+ forgotPasswordLabel={loginConfig.forgotPasswordLabel}
31
+ createAccountPath={loginConfig.createAccountPath}
32
+ createAccountLabel={loginConfig.createAccountLabel}
33
+ urlOnLogon={urlOnLogon}
22
34
  />
23
- </SidebarLayoutWrapper>
35
+ </AuthPageShell>
24
36
  );
25
37
  }
26
38
 
@@ -4,9 +4,9 @@
4
4
 
5
5
  // section: imports
6
6
  import { useEffect, useState } from "react";
7
- import my_settings_layout from "@/components/layouts/my_settings";
8
- import type { LayoutDataClient } from "@/components/layouts/shared/data/layout_data_client";
9
- import type { PasswordRequirementOptions } from "@/components/layouts/shared/config/layout_customization";
7
+ import my_settings_layout from "../../../components/layouts/my_settings";
8
+ import type { LayoutDataClient } from "../../../components/layouts/shared/data/layout_data_client";
9
+ import type { PasswordRequirementOptions } from "../../../components/layouts/shared/config/layout_customization";
10
10
 
11
11
  // section: types
12
12
  type MySettingsPageClientProps = {
@@ -1,8 +1,8 @@
1
1
  // file_description: render the my settings page shell and mount the my settings layout component within sidebar
2
2
  // section: imports
3
- import { SidebarLayoutWrapper } from "@/components/layouts/shared/components/sidebar_layout_wrapper";
3
+ import { AuthPageShell } from "../../../components/layouts/shared/components/auth_page_shell";
4
4
  import { MySettingsPageClient } from "./my_settings_page_client";
5
- import { get_my_settings_config } from "@/lib/my_settings_config.server";
5
+ import { get_my_settings_config } from "../../../lib/my_settings_config.server";
6
6
 
7
7
  // section: component
8
8
  export default function my_settings_page() {
@@ -10,7 +10,7 @@ export default function my_settings_page() {
10
10
  const mySettingsConfig = get_my_settings_config();
11
11
 
12
12
  return (
13
- <SidebarLayoutWrapper>
13
+ <AuthPageShell>
14
14
  <MySettingsPageClient
15
15
  userFields={mySettingsConfig.userFields}
16
16
  passwordRequirements={mySettingsConfig.passwordRequirements}
@@ -34,7 +34,7 @@ export default function my_settings_page() {
34
34
  uiSizes={mySettingsConfig.uiSizes}
35
35
  fileTypes={mySettingsConfig.fileTypes}
36
36
  />
37
- </SidebarLayoutWrapper>
37
+ </AuthPageShell>
38
38
  );
39
39
  }
40
40