hazo_auth 1.0.2 → 1.0.3

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.
@@ -19,6 +19,11 @@ enable_admin_ui = true
19
19
 
20
20
  # PostgREST configuration (uncomment if using postgrest type)
21
21
  # postgrest_url =
22
+
23
+ # PostgREST API Key (REQUIRED if PostgREST uses authentication)
24
+ # IMPORTANT: API keys should ONLY be set in environment variables for security
25
+ # Set HAZO_CONNECT_POSTGREST_API_KEY or POSTGREST_API_KEY in your .env file
26
+ # DO NOT put API keys in this config file
22
27
  # postgrest_api_key =
23
28
 
24
29
  [hazo_auth__register_layout]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "files": [
5
5
  "src/**/*",
6
6
  "public/file.svg",
@@ -101,8 +101,8 @@
101
101
  "@types/react-dom": "^18",
102
102
  "better-sqlite3": "^12.4.1",
103
103
  "cross-env": "^10.1.0",
104
- "eslint": "^8",
105
- "eslint-config-next": "^14.2.7",
104
+ "eslint": "^9.0.0",
105
+ "eslint-config-next": "^16.0.3",
106
106
  "eslint-plugin-storybook": "^10.0.6",
107
107
  "jest": "^30.2.0",
108
108
  "jest-environment-jsdom": "^29.7.0",
@@ -52,20 +52,21 @@ export async function POST(request: NextRequest) {
52
52
  });
53
53
 
54
54
  if (!result.success) {
55
- logger.warn("resend_verification_failed", {
55
+ logger.error("resend_verification_failed", {
56
56
  filename: get_filename(),
57
57
  line_number: get_line_number(),
58
58
  email,
59
59
  error: result.error,
60
60
  });
61
61
 
62
- // Still return 200 OK to prevent email enumeration attacks
62
+ // Return error response (500) when email sending fails
63
+ // This is a technical error, not a security issue, so we can reveal it
63
64
  return NextResponse.json(
64
65
  {
65
- success: true,
66
- message: "If an account with that email exists and is not verified, a verification link has been sent.",
66
+ success: false,
67
+ error: result.error || "Failed to resend verification email",
67
68
  },
68
- { status: 200 }
69
+ { status: 500 }
69
70
  );
70
71
  }
71
72
 
@@ -155,10 +155,10 @@ export const use_email_verification = <TClient,>({
155
155
  return true;
156
156
  }
157
157
 
158
- const hasEmptyField = Object.values(values).some((fieldValue) => fieldValue.trim() === "");
159
- const hasErrors = Object.keys(errors).length > 0;
160
- return hasEmptyField || hasErrors;
161
- }, [errors, values, isSubmitting]);
158
+ // Only disable if there are active errors
159
+ const hasErrors = !!errors[EMAIL_VERIFICATION_FIELD_IDS.EMAIL];
160
+ return hasErrors;
161
+ }, [errors, isSubmitting]);
162
162
 
163
163
  const handleFieldChange = useCallback((fieldId: EmailVerificationFieldId, value: string) => {
164
164
  setValues((previousValues) => {
@@ -231,7 +231,13 @@ export const use_email_verification = <TClient,>({
231
231
  }),
232
232
  });
233
233
 
234
- const data = await response.json();
234
+ let data;
235
+ try {
236
+ data = await response.json();
237
+ } catch (jsonError) {
238
+ // If JSON parsing fails, the response is likely HTML (e.g., error page)
239
+ throw new Error("Server returned an invalid response. Please try again later.");
240
+ }
235
241
 
236
242
  if (!response.ok) {
237
243
  throw new Error(data.error || "Failed to resend verification email");
@@ -38,36 +38,60 @@ export function get_hazo_connect_instance(): HazoConnectAdapter {
38
38
  try {
39
39
  // Get configuration from hazo_auth_config.ini (falls back to environment variables)
40
40
  const config_options = get_hazo_connect_config_options();
41
+ const logger = create_app_logger();
42
+ logger.debug("hazo_connect_singleton_attempt", {
43
+ filename: "hazo_connect_instance.server.ts",
44
+ line_number: 38,
45
+ config_options,
46
+ note: "Attempting to get singleton with these options",
47
+ });
41
48
  return getHazoConnectSingleton(config_options);
42
49
  } catch (error) {
50
+ const logger = create_app_logger();
51
+ const error_message = error instanceof Error ? error.message : "Unknown error";
52
+ logger.error("hazo_connect_singleton_failed", {
53
+ filename: "hazo_connect_instance.server.ts",
54
+ line_number: 45,
55
+ error: error_message,
56
+ error_stack: error instanceof Error ? error.stack : undefined,
57
+ note: "Falling back to manual singleton implementation",
58
+ });
59
+
43
60
  // Fallback: Manual singleton implementation if new API fails
44
61
  // This should not happen with the updated package, but kept for safety
45
62
  if (!hazoConnectInstance) {
46
- // Initialize admin service first (if not already done)
47
- if (!isInitialized) {
63
+ // Get config options to determine database type
64
+ const config_options = get_hazo_connect_config_options();
65
+ const db_type = config_options.type;
66
+
67
+ // Only initialize SQLite admin service for SQLite databases
68
+ if (db_type === "sqlite" && !isInitialized) {
48
69
  initializeAdminService({ enable_admin_ui: true });
49
70
  isInitialized = true;
50
71
  }
51
72
 
52
73
  // Create the adapter instance (reads from hazo_auth_config.ini)
74
+ // Note: Despite the name, this function supports both SQLite and PostgREST
53
75
  hazoConnectInstance = create_sqlite_hazo_connect_server();
54
76
 
55
77
  // Note: Database migrations should be applied manually via SQLite Admin UI
56
78
  // or through a separate migration script. The token_service has fallback
57
79
  // logic to work without the token_type column if migration hasn't been applied.
58
80
 
59
- // Finalize initialization by getting the admin service.
60
- try {
61
- getSqliteAdminService();
62
- } catch (adminError) {
63
- const logger = create_app_logger();
64
- const error_message = adminError instanceof Error ? adminError.message : "Unknown error";
65
- logger.warn("hazo_connect_instance_admin_service_init_failed", {
66
- filename: "hazo_connect_instance.server.ts",
67
- line_number: 0,
68
- error: error_message,
69
- note: "Could not get SqliteAdminService during initialization, continuing...",
70
- });
81
+ // Finalize initialization by getting the admin service (only for SQLite)
82
+ if (db_type === "sqlite") {
83
+ try {
84
+ getSqliteAdminService();
85
+ } catch (adminError) {
86
+ const logger = create_app_logger();
87
+ const error_message = adminError instanceof Error ? adminError.message : "Unknown error";
88
+ logger.warn("hazo_connect_instance_admin_service_init_failed", {
89
+ filename: "hazo_connect_instance.server.ts",
90
+ line_number: 0,
91
+ error: error_message,
92
+ note: "Could not get SqliteAdminService during initialization, continuing...",
93
+ });
94
+ }
71
95
  }
72
96
  }
73
97
 
@@ -100,8 +100,10 @@ function get_hazo_connect_config(): {
100
100
  hazo_connect_section?.postgrest_url ||
101
101
  process.env.HAZO_CONNECT_POSTGREST_URL ||
102
102
  process.env.POSTGREST_URL;
103
+ // API key must only come from environment variables for security
104
+ // Check multiple possible env var names for compatibility
103
105
  const postgrest_api_key =
104
- hazo_connect_section?.postgrest_api_key ||
106
+ process.env.postgrest_api_key || // hazo_connect package expects this
105
107
  process.env.HAZO_CONNECT_POSTGREST_API_KEY ||
106
108
  process.env.POSTGREST_API_KEY;
107
109
 
@@ -141,10 +143,13 @@ export function create_sqlite_hazo_connect_server() {
141
143
  }
142
144
 
143
145
  if (config.type === "postgrest") {
146
+ // Ensure we have a value (empty string if not set, for PostgREST instances without auth)
147
+ const apiKey = config.postgrestApiKey || "";
148
+
144
149
  return createHazoConnect({
145
150
  type: "postgrest",
146
151
  baseUrl: config.postgrestUrl!,
147
- apiKey: config.postgrestApiKey,
152
+ apiKey: apiKey, // Pass empty string if not set
148
153
  });
149
154
  }
150
155
 
@@ -161,6 +166,8 @@ export function get_hazo_connect_config_options(): {
161
166
  sqlitePath?: string;
162
167
  enableAdminUi?: boolean;
163
168
  readOnly?: boolean;
169
+ postgrestUrl?: string;
170
+ postgrestApiKey?: string;
164
171
  } {
165
172
  const config = get_hazo_connect_config();
166
173
 
@@ -173,8 +180,15 @@ export function get_hazo_connect_config_options(): {
173
180
  };
174
181
  }
175
182
 
176
- // PostgREST is not supported by the singleton API options yet
177
- // Return empty object to let it use environment variables
183
+ if (config.type === "postgrest") {
184
+ return {
185
+ type: "postgrest",
186
+ baseUrl: config.postgrestUrl, // Corrected from postgrestUrl
187
+ apiKey: config.postgrestApiKey || "", // Corrected from postgrestApiKey and ensured string value
188
+ };
189
+ }
190
+
191
+ // Fallback: return empty object to let it use environment variables
178
192
  return {};
179
193
  }
180
194
 
@@ -245,6 +245,12 @@ export async function resend_verification_email(
245
245
  error: email_result.error,
246
246
  note: "Verification token created but email failed to send",
247
247
  });
248
+
249
+ // Return error if email sending failed (this is a technical error, not a security issue)
250
+ return {
251
+ success: false,
252
+ error: email_result.error || "Failed to send verification email",
253
+ };
248
254
  }
249
255
  }
250
256
 
package/src/middleware.ts CHANGED
@@ -46,6 +46,7 @@ export async function middleware(request: NextRequest) {
46
46
  "/api/hazo_auth/reset_password",
47
47
  "/api/hazo_auth/verify_email",
48
48
  "/api/hazo_auth/validate_reset_token",
49
+ "/api/hazo_auth/resend_verification", // Allow resend verification email without auth
49
50
  "/api/hazo_auth/me", // Allow /api/hazo_auth/me to be public (returns authenticated: false if not logged in)
50
51
  "/hazo_connect/api/sqlite", // SQLite Admin API routes (admin tool, should be accessible)
51
52
  "/hazo_connect/sqlite_admin", // SQLite Admin UI page