sitepaige-mcp-server 1.0.3 → 1.2.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 (51) hide show
  1. package/components/IntegrationComponent.tsx +1 -0
  2. package/components/admin.tsx +30 -27
  3. package/components/auth.tsx +9 -9
  4. package/components/cta.tsx +3 -10
  5. package/components/headerlogin.tsx +19 -37
  6. package/components/login.tsx +7 -4
  7. package/components/logincallback.tsx +1 -0
  8. package/components/menu.tsx +0 -6
  9. package/components/profile.tsx +304 -47
  10. package/defaultapp/api/Auth/resend-verification/route.ts +1 -1
  11. package/defaultapp/api/Auth/route.ts +39 -39
  12. package/defaultapp/api/Auth/signup/route.ts +1 -1
  13. package/defaultapp/api/Auth/verify-email/route.ts +6 -6
  14. package/defaultapp/api/admin/users/route.ts +5 -3
  15. package/defaultapp/api/profile/route.ts +154 -0
  16. package/defaultapp/auth/auth.ts +9 -9
  17. package/defaultapp/db-mysql.ts +1 -1
  18. package/defaultapp/db-postgres.ts +1 -1
  19. package/defaultapp/db-sqlite.ts +1 -1
  20. package/defaultapp/db-users.ts +64 -64
  21. package/defaultapp/profile/page.tsx +6 -0
  22. package/dist/blueprintWriter.js.map +1 -1
  23. package/dist/components/IntegrationComponent.tsx +1 -0
  24. package/dist/components/admin.tsx +30 -27
  25. package/dist/components/auth.tsx +9 -9
  26. package/dist/components/cta.tsx +3 -10
  27. package/dist/components/headerlogin.tsx +19 -37
  28. package/dist/components/login.tsx +7 -4
  29. package/dist/components/logincallback.tsx +1 -0
  30. package/dist/components/menu.tsx +0 -6
  31. package/dist/components/profile.tsx +304 -47
  32. package/dist/defaultapp/api/Auth/resend-verification/route.ts +1 -1
  33. package/dist/defaultapp/api/Auth/route.ts +39 -39
  34. package/dist/defaultapp/api/Auth/signup/route.ts +1 -1
  35. package/dist/defaultapp/api/Auth/verify-email/route.ts +6 -6
  36. package/dist/defaultapp/api/admin/users/route.ts +5 -3
  37. package/dist/defaultapp/api/profile/route.ts +154 -0
  38. package/dist/defaultapp/auth/auth.ts +9 -9
  39. package/dist/defaultapp/db-mysql.ts +1 -1
  40. package/dist/defaultapp/db-postgres.ts +1 -1
  41. package/dist/defaultapp/db-sqlite.ts +1 -1
  42. package/dist/defaultapp/db-users.ts +64 -64
  43. package/dist/defaultapp/profile/page.tsx +6 -0
  44. package/dist/generators/env-example-template.txt +4 -3
  45. package/dist/generators/sql.js +11 -3
  46. package/dist/generators/sql.js.map +1 -1
  47. package/dist/generators/views.js +2 -2
  48. package/dist/sitepaige.js +2 -1
  49. package/dist/sitepaige.js.map +1 -1
  50. package/package.json +1 -1
  51. package/defaultapp/admin/page.tsx +0 -6
@@ -1,85 +1,342 @@
1
- /*
2
- Sitepaige Components v1.0.0
3
- Sitepaige components are automatically added to your project the first time it is built, and are only added again if the "Build Components" button is
4
- checked in the system build settings. It is safe to modify this file without it being overwritten unless that setting is selected.
5
- */
6
-
7
1
  'use client';
8
2
 
9
3
  import { useState, useEffect } from 'react';
4
+ import { useRouter } from 'next/navigation';
5
+ // import { useCsrfToken } from './csrf-provider'; // Disabled for now
10
6
 
11
- interface UserProfile {
12
- ID: string;
13
- UserName: string;
14
- AvatarURL: string | null;
7
+ interface UserData {
8
+ userid: string;
9
+ username: string;
10
+ avatarurl?: string;
11
+ email?: string;
12
+ userlevel: number;
13
+ source: string;
15
14
  }
16
15
 
17
16
  export default function Profile() {
18
- const [profile, setProfile] = useState<UserProfile | null>(null);
17
+ const router = useRouter();
18
+ // const csrfToken = useCsrfToken(); // Disabled for now
19
+ const [userData, setUserData] = useState<UserData | null>(null);
19
20
  const [loading, setLoading] = useState(true);
20
21
  const [error, setError] = useState<string | null>(null);
22
+ const [success, setSuccess] = useState<string | null>(null);
23
+
24
+ // Password change state
25
+ const [currentPassword, setCurrentPassword] = useState('');
26
+ const [newPassword, setNewPassword] = useState('');
27
+ const [confirmPassword, setConfirmPassword] = useState('');
28
+ const [isChangingPassword, setIsChangingPassword] = useState(false);
29
+
30
+ // Account deletion state
31
+ const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
32
+ const [deleteConfirmText, setDeleteConfirmText] = useState('');
33
+ const [isDeleting, setIsDeleting] = useState(false);
21
34
 
22
35
  useEffect(() => {
23
- const fetchProfile = async () => {
36
+ fetchUserData();
37
+ }, []);
38
+
39
+ const fetchUserData = async () => {
24
40
  try {
41
+ setLoading(true);
25
42
  const response = await fetch('/api/Auth', {
26
- method: 'GET'
43
+ credentials: 'include'
27
44
  });
28
45
 
29
46
  if (!response.ok) {
30
- throw new Error('Failed to fetch profile');
47
+ throw new Error('Failed to fetch user data');
31
48
  }
32
49
 
33
50
  const data = await response.json();
34
-
35
- if (!data.user) {
36
- throw new Error('User not authenticated');
37
- }
38
-
39
- // Use the user object from the response
40
- const userData = data.user;
41
- setProfile({
42
- ID: userData.userid,
43
- UserName: userData.UserName,
44
- AvatarURL: userData.AvatarURL
45
- });
51
+ if (data.user) {
52
+ setUserData(data.user);
53
+ } else {
54
+ // Not authenticated, redirect to login
55
+ router.push('/login');
56
+ }
46
57
  } catch (err) {
47
- setError(err instanceof Error ? err.message : 'An error occurred');
58
+ setError(err instanceof Error ? err.message : 'Failed to load profile');
48
59
  } finally {
49
60
  setLoading(false);
50
61
  }
51
62
  };
52
63
 
53
- fetchProfile();
54
- }, []);
64
+ const handlePasswordChange = async (e: React.FormEvent) => {
65
+ e.preventDefault();
66
+ setError(null);
67
+ setSuccess(null);
68
+
69
+ // Validate passwords
70
+ if (newPassword !== confirmPassword) {
71
+ setError('Passwords do not match');
72
+ return;
73
+ }
74
+
75
+ if (newPassword.length < 8) {
76
+ setError('Password must be at least 8 characters long');
77
+ return;
78
+ }
79
+
80
+ setIsChangingPassword(true);
81
+
82
+ try {
83
+ const response = await fetch('/api/profile', {
84
+ method: 'PUT',
85
+ headers: {
86
+ 'Content-Type': 'application/json'
87
+ // 'X-CSRF-Token': csrfToken || '' // Disabled for now
88
+ },
89
+ credentials: 'include',
90
+ body: JSON.stringify({
91
+ currentPassword,
92
+ newPassword
93
+ })
94
+ });
95
+
96
+ const data = await response.json();
97
+
98
+ if (!response.ok) {
99
+ throw new Error(data.error || 'Failed to update password');
100
+ }
101
+
102
+ setSuccess('Password updated successfully');
103
+ setCurrentPassword('');
104
+ setNewPassword('');
105
+ setConfirmPassword('');
106
+ } catch (err) {
107
+ setError(err instanceof Error ? err.message : 'Failed to update password');
108
+ } finally {
109
+ setIsChangingPassword(false);
110
+ }
111
+ };
55
112
 
56
- if (loading) {
57
- return <div className="flex justify-center items-center min-h-[200px]">Loading...</div>;
58
- }
113
+ const handleDeleteAccount = async () => {
114
+ if (deleteConfirmText !== 'DELETE') {
115
+ setError('Please type DELETE to confirm account deletion');
116
+ return;
117
+ }
118
+
119
+ setIsDeleting(true);
120
+ setError(null);
121
+
122
+ try {
123
+ const response = await fetch('/api/profile', {
124
+ method: 'DELETE',
125
+ headers: {
126
+ 'Content-Type': 'application/json'
127
+ // 'X-CSRF-Token': csrfToken || '' // Disabled for now
128
+ },
129
+ credentials: 'include',
130
+ body: JSON.stringify({
131
+ confirmDelete: true
132
+ })
133
+ });
134
+
135
+ const data = await response.json();
136
+
137
+ if (!response.ok) {
138
+ throw new Error(data.error || 'Failed to delete account');
139
+ }
140
+
141
+ // Redirect to home page after successful deletion
142
+ window.location.href = '/';
143
+ } catch (err) {
144
+ setError(err instanceof Error ? err.message : 'Failed to delete account');
145
+ setIsDeleting(false);
146
+ }
147
+ };
148
+
149
+ const getUserLevelName = (level: number) => {
150
+ switch (level) {
151
+ case 0: return 'Guest';
152
+ case 1: return 'Registered User';
153
+ case 2: return 'Admin';
154
+ default: return 'Unknown';
155
+ }
156
+ };
157
+
158
+ const getAuthMethodName = (source: string) => {
159
+ switch (source) {
160
+ case 'userpass': return 'Email/Password';
161
+ case 'google': return 'Google';
162
+ case 'facebook': return 'Facebook';
163
+ case 'apple': return 'Apple';
164
+ case 'github': return 'GitHub';
165
+ default: return source;
166
+ }
167
+ };
59
168
 
60
- if (error) {
61
- return <div className="text-red-500 text-center">{error}</div>;
169
+ if (loading) {
170
+ return (
171
+ <div className="flex items-center justify-center min-h-screen">
172
+ <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-600"></div>
173
+ </div>
174
+ );
62
175
  }
63
176
 
64
- if (!profile) {
65
- return <div className="text-center">No profile found</div>;
177
+ if (!userData) {
178
+ return null; // Will redirect to login
66
179
  }
67
180
 
68
181
  return (
69
- <div className="max-w-md mx-auto mt-8 p-6 bg-white rounded-lg shadow-md">
70
- <div className="flex flex-col items-center">
71
- {profile.AvatarURL && (
72
- <img
73
- src={profile.AvatarURL}
74
- alt="Profile avatar"
75
- className="w-32 h-32 rounded-full mb-4"
182
+ <div className="container mx-auto px-4 py-8 max-w-4xl">
183
+ <h1 className="text-3xl font-bold mb-8">Profile Settings</h1>
184
+
185
+ {/* User Information */}
186
+ <div className="bg-white rounded-lg shadow p-6 mb-8">
187
+ <h2 className="text-xl font-semibold mb-4">User Information</h2>
188
+ <div className="grid md:grid-cols-2 gap-4">
189
+ <div className="flex items-center space-x-4">
190
+ {userData.avatarurl ? (
191
+ <img
192
+ src={userData.avatarurl}
193
+ alt={userData.username}
194
+ className="w-16 h-16 rounded-full"
76
195
  referrerPolicy="no-referrer"
77
196
  crossOrigin="anonymous"
78
197
  />
79
- )}
80
- <h2 className="text-2xl font-semibold text-gray-800">{profile.UserName}</h2>
81
- <p className="text-gray-500 mt-2">User ID: {profile.ID}</p>
198
+ ) : (
199
+ <div className="w-16 h-16 rounded-full bg-gray-300 flex items-center justify-center">
200
+ <span className="text-2xl text-gray-600">
201
+ {userData.username.charAt(0).toUpperCase()}
202
+ </span>
203
+ </div>
204
+ )}
205
+ <div>
206
+ <p className="font-semibold">{userData.username}</p>
207
+ {userData.email && (
208
+ <p className="text-sm text-gray-600">{userData.email}</p>
209
+ )}
210
+ </div>
211
+ </div>
212
+ <div className="space-y-2">
213
+ <p><span className="font-semibold">User Level:</span> {getUserLevelName(userData.userlevel)}</p>
214
+ <p><span className="font-semibold">Auth Method:</span> {getAuthMethodName(userData.source)}</p>
215
+ </div>
216
+ </div>
217
+ </div>
218
+
219
+ {/* Error and Success Messages */}
220
+ {error && (
221
+ <div className="mb-4 p-4 bg-red-50 border border-red-200 text-red-700 rounded">
222
+ {error}
223
+ </div>
224
+ )}
225
+ {success && (
226
+ <div className="mb-4 p-4 bg-green-50 border border-green-200 text-green-700 rounded">
227
+ {success}
228
+ </div>
229
+ )}
230
+
231
+ {/* Password Change Section - Only for email/password users */}
232
+ {userData.source === 'userpass' && (
233
+ <div className="bg-white rounded-lg shadow p-6 mb-8">
234
+ <h2 className="text-xl font-semibold mb-4">Change Password</h2>
235
+ <form onSubmit={handlePasswordChange} className="space-y-4">
236
+ <div>
237
+ <label htmlFor="currentPassword" className="block text-sm font-medium text-gray-700 mb-1">
238
+ Current Password
239
+ </label>
240
+ <input
241
+ type="password"
242
+ id="currentPassword"
243
+ value={currentPassword}
244
+ onChange={(e) => setCurrentPassword(e.target.value)}
245
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
246
+ required
247
+ />
248
+ </div>
249
+ <div>
250
+ <label htmlFor="newPassword" className="block text-sm font-medium text-gray-700 mb-1">
251
+ New Password
252
+ </label>
253
+ <input
254
+ type="password"
255
+ id="newPassword"
256
+ value={newPassword}
257
+ onChange={(e) => setNewPassword(e.target.value)}
258
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
259
+ required
260
+ minLength={8}
261
+ />
262
+ <p className="text-xs text-gray-500 mt-1">Must be at least 8 characters long</p>
263
+ </div>
264
+ <div>
265
+ <label htmlFor="confirmPassword" className="block text-sm font-medium text-gray-700 mb-1">
266
+ Confirm New Password
267
+ </label>
268
+ <input
269
+ type="password"
270
+ id="confirmPassword"
271
+ value={confirmPassword}
272
+ onChange={(e) => setConfirmPassword(e.target.value)}
273
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
274
+ required
275
+ />
276
+ </div>
277
+ <button
278
+ type="submit"
279
+ disabled={isChangingPassword}
280
+ className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
281
+ >
282
+ {isChangingPassword ? 'Updating...' : 'Update Password'}
283
+ </button>
284
+ </form>
285
+ </div>
286
+ )}
287
+
288
+ {/* Delete Account Section */}
289
+ <div className="bg-white rounded-lg shadow p-6">
290
+ <h2 className="text-xl font-semibold mb-4 text-red-600">Danger Zone</h2>
291
+ <div className="border border-red-200 rounded-md p-4">
292
+ <h3 className="font-semibold mb-2">Delete Account</h3>
293
+ <p className="text-sm text-gray-600 mb-4">
294
+ Once you delete your account, there is no going back. Please be certain.
295
+ </p>
296
+
297
+ {!showDeleteConfirm ? (
298
+ <button
299
+ onClick={() => setShowDeleteConfirm(true)}
300
+ className="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700"
301
+ >
302
+ Delete Account
303
+ </button>
304
+ ) : (
305
+ <div className="space-y-4">
306
+ <p className="text-sm font-semibold">
307
+ To confirm deletion, please type <span className="font-mono bg-gray-100 px-1">DELETE</span> below:
308
+ </p>
309
+ <input
310
+ type="text"
311
+ value={deleteConfirmText}
312
+ onChange={(e) => setDeleteConfirmText(e.target.value)}
313
+ placeholder="Type DELETE to confirm"
314
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-red-500"
315
+ />
316
+ <div className="flex space-x-4">
317
+ <button
318
+ onClick={handleDeleteAccount}
319
+ disabled={isDeleting || deleteConfirmText !== 'DELETE'}
320
+ className="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed"
321
+ >
322
+ {isDeleting ? 'Deleting...' : 'Confirm Delete'}
323
+ </button>
324
+ <button
325
+ onClick={() => {
326
+ setShowDeleteConfirm(false);
327
+ setDeleteConfirmText('');
328
+ setError(null);
329
+ }}
330
+ disabled={isDeleting}
331
+ className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md hover:bg-gray-400"
332
+ >
333
+ Cancel
334
+ </button>
335
+ </div>
336
+ </div>
337
+ )}
338
+ </div>
82
339
  </div>
83
340
  </div>
84
341
  );
85
- }
342
+ }
@@ -36,7 +36,7 @@ export async function POST(request: Request) {
36
36
  const { verificationToken } = result;
37
37
 
38
38
  // Get site domain from environment or default
39
- const siteDomain = process.env.SITE_DOMAIN || 'https://sitepaige.com';
39
+ const siteDomain = process.env.NODE_ENV === 'production' ? process.env.DOMAIN : process.env.LOCAL_DOMAIN;
40
40
  const verificationUrl = `${siteDomain}/api/Auth/verify-email?token=${verificationToken}`;
41
41
 
42
42
  // Send verification email
@@ -41,7 +41,7 @@ export async function POST(request: Request) {
41
41
  }
42
42
 
43
43
  // Handle username/password authentication
44
- if (provider === 'username') {
44
+ if (provider === 'userpass') {
45
45
  if (!email || !password) {
46
46
  return NextResponse.json(
47
47
  { error: 'Email and password are required' },
@@ -69,7 +69,7 @@ export async function POST(request: Request) {
69
69
  // Create or update user in the main Users table
70
70
  const user = await upsertUser(
71
71
  `password_${authRecord.id}`, // Unique OAuth ID for password users
72
- 'username' as any, // Source type
72
+ 'userpass' as any, // Source type
73
73
  email.split('@')[0], // Username from email
74
74
  email,
75
75
  undefined // No avatar for password auth
@@ -77,14 +77,14 @@ export async function POST(request: Request) {
77
77
 
78
78
  // Delete existing sessions for this user
79
79
  const existingSessions = await db_query(db,
80
- "SELECT ID FROM usersession WHERE userid = ?",
80
+ "SELECT id FROM usersession WHERE userid = ?",
81
81
  [user.userid]
82
82
  );
83
83
 
84
84
  if (existingSessions && existingSessions.length > 0) {
85
- const sessionIds = existingSessions.map(session => session.ID);
85
+ const sessionIds = existingSessions.map(session => session.id);
86
86
  const placeholders = sessionIds.map(() => '?').join(',');
87
- await db_query(db, `DELETE FROM usersession WHERE ID IN (${placeholders})`, sessionIds);
87
+ await db_query(db, `DELETE FROM usersession WHERE id IN (${placeholders})`, sessionIds);
88
88
  }
89
89
 
90
90
  // Generate secure session token and ID
@@ -93,7 +93,7 @@ export async function POST(request: Request) {
93
93
 
94
94
  // Create new session with secure token
95
95
  await db_query(db,
96
- "INSERT INTO usersession (ID, SessionToken, userid, ExpirationDate) VALUES (?, ?, ?, ?)",
96
+ "INSERT INTO usersession (id, sessiontoken, userid, expirationdate) VALUES (?, ?, ?, ?)",
97
97
  [sessionId, sessionToken, user.userid, new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString()]
98
98
  );
99
99
 
@@ -112,10 +112,10 @@ export async function POST(request: Request) {
112
112
  // Create a completely clean object to avoid any database result object issues
113
113
  const cleanUserData = {
114
114
  userid: String(user.userid),
115
- userName: String(user.UserName),
116
- avatarURL: String(user.AvatarURL || ''),
117
- userLevel: Number(user.UserLevel),
118
- isAdmin: Number(user.UserLevel) === 2
115
+ userName: String(user.username),
116
+ avatarURL: String(user.avatarurl || ''),
117
+ userLevel: Number(user.userlevel),
118
+ isAdmin: Number(user.userlevel) === 2
119
119
  };
120
120
 
121
121
  return NextResponse.json({
@@ -152,7 +152,7 @@ export async function POST(request: Request) {
152
152
  }
153
153
 
154
154
  let userData = {
155
- ID: '',
155
+ id: '',
156
156
  name: '',
157
157
  email: '',
158
158
  avatar_url: '',
@@ -203,28 +203,28 @@ export async function POST(request: Request) {
203
203
  switch (validProvider) {
204
204
 
205
205
  case 'google':
206
- userData.ID = fetchedUserData.id;
206
+ userData.id = fetchedUserData.id;
207
207
  userData.name = fetchedUserData.name;
208
208
  userData.email = fetchedUserData.email;
209
209
  userData.avatar_url = fetchedUserData.picture;
210
210
  break;
211
211
 
212
212
  case 'facebook':
213
- userData.ID = fetchedUserData.id;
213
+ userData.id = fetchedUserData.id;
214
214
  userData.name = fetchedUserData.name;
215
215
  userData.email = fetchedUserData.email;
216
216
  userData.avatar_url = fetchedUserData.picture?.data?.url;
217
217
  break;
218
218
 
219
219
  case 'apple':
220
- userData.ID = fetchedUserData.sub;
220
+ userData.id = fetchedUserData.sub;
221
221
  userData.name = `${fetchedUserData.given_name || ''} ${fetchedUserData.family_name || ''}`.trim();
222
222
  userData.email = fetchedUserData.email;
223
223
  // Apple doesn't provide avatar URL
224
224
  break;
225
225
 
226
226
  case 'github':
227
- userData.ID = fetchedUserData.id?.toString();
227
+ userData.id = fetchedUserData.id?.toString();
228
228
  userData.name = fetchedUserData.name || fetchedUserData.login;
229
229
  userData.email = fetchedUserData.email;
230
230
  userData.avatar_url = fetchedUserData.avatar_url;
@@ -239,7 +239,7 @@ export async function POST(request: Request) {
239
239
 
240
240
  // Create or update user using the new user management system
241
241
  const user = await upsertUser(
242
- userData.ID,
242
+ userData.id,
243
243
  validProvider,
244
244
  userData.name,
245
245
  userData.email,
@@ -257,14 +257,14 @@ export async function POST(request: Request) {
257
257
 
258
258
  // Delete existing sessions for this user
259
259
  const existingSessions = await db_query(db,
260
- "SELECT ID FROM usersession WHERE userid = ?",
260
+ "SELECT id FROM usersession WHERE userid = ?",
261
261
  [user.userid]
262
262
  );
263
263
 
264
264
  if (existingSessions && existingSessions.length > 0) {
265
- const sessionIds = existingSessions.map(session => session.ID);
265
+ const sessionIds = existingSessions.map(session => session.id);
266
266
  const placeholders = sessionIds.map(() => '?').join(',');
267
- await db_query(db, `DELETE FROM usersession WHERE ID IN (${placeholders})`, sessionIds);
267
+ await db_query(db, `DELETE FROM usersession WHERE id IN (${placeholders})`, sessionIds);
268
268
  }
269
269
 
270
270
  // Generate secure session token and ID
@@ -273,7 +273,7 @@ export async function POST(request: Request) {
273
273
 
274
274
  // Create new session with secure token
275
275
  await db_query(db,
276
- "INSERT INTO usersession (ID, SessionToken, userid, ExpirationDate) VALUES (?, ?, ?, ?)",
276
+ "INSERT INTO usersession (id, sessiontoken, userid, expirationdate) VALUES (?, ?, ?, ?)",
277
277
  [sessionId, sessionToken, user.userid, new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString()]
278
278
  );
279
279
 
@@ -292,10 +292,10 @@ export async function POST(request: Request) {
292
292
  // Create a completely clean object to avoid any database result object issues
293
293
  const cleanUserData = {
294
294
  userid: String(user.userid),
295
- userName: String(user.UserName),
296
- avatarURL: String(user.AvatarURL || ''),
297
- userLevel: Number(user.UserLevel),
298
- isAdmin: Number(user.UserLevel) === 2
295
+ userName: String(user.username),
296
+ avatarURL: String(user.avatarurl || ''),
297
+ userLevel: Number(user.userlevel),
298
+ isAdmin: Number(user.userlevel) === 2
299
299
  };
300
300
 
301
301
  return NextResponse.json({
@@ -346,13 +346,13 @@ export async function GET() {
346
346
  const response = NextResponse.json({
347
347
  user: {
348
348
  userid: sessionData.user.userid,
349
- UserName: sessionData.user.UserName,
350
- AvatarURL: sessionData.user.AvatarURL,
351
- Email: sessionData.user.Email,
352
- UserLevel: sessionData.user.UserLevel,
353
- IsAdmin: sessionData.user.UserLevel === 2,
354
- Source: sessionData.user.Source,
355
- LastLoginDate: sessionData.user.LastLoginDate
349
+ username: sessionData.user.username,
350
+ avatarurl: sessionData.user.avatarurl,
351
+ email: sessionData.user.email,
352
+ userlevel: sessionData.user.userlevel,
353
+ isadmin: sessionData.user.userlevel === 2,
354
+ source: sessionData.user.source,
355
+ lastlogindate: sessionData.user.lastlogindate
356
356
  }
357
357
  });
358
358
 
@@ -375,13 +375,13 @@ export async function GET() {
375
375
  return NextResponse.json({
376
376
  user: {
377
377
  userid: sessionData.user.userid,
378
- UserName: sessionData.user.UserName,
379
- AvatarURL: sessionData.user.AvatarURL,
380
- Email: sessionData.user.Email,
381
- UserLevel: sessionData.user.UserLevel,
382
- IsAdmin: sessionData.user.UserLevel === 2,
383
- Source: sessionData.user.Source,
384
- LastLoginDate: sessionData.user.LastLoginDate
378
+ username: sessionData.user.username,
379
+ avatarurl: sessionData.user.avatarurl,
380
+ email: sessionData.user.email,
381
+ userlevel: sessionData.user.userlevel,
382
+ isadmin: sessionData.user.userlevel === 2,
383
+ source: sessionData.user.source,
384
+ lastlogindate: sessionData.user.lastlogindate
385
385
  }
386
386
  });
387
387
 
@@ -410,7 +410,7 @@ export async function DELETE(request: Request) {
410
410
 
411
411
  // Delete session from database using the actual session token
412
412
  await db_query(db,
413
- "DELETE FROM usersession WHERE SessionToken = ?",
413
+ "DELETE FROM usersession WHERE sessiontoken = ?",
414
414
  [sessionToken]
415
415
  );
416
416
 
@@ -37,7 +37,7 @@ export async function POST(request: Request) {
37
37
  const { passwordAuth, verificationToken } = await createPasswordAuth(email, password);
38
38
 
39
39
  // Get site domain from environment or default
40
- const siteDomain = process.env.SITE_DOMAIN || 'https://sitepaige.com';
40
+ const siteDomain = process.env.NODE_ENV === 'production' ? process.env.DOMAIN : process.env.LOCAL_DOMAIN;
41
41
  const verificationUrl = `${siteDomain}/api/Auth/verify-email?token=${verificationToken}`;
42
42
 
43
43
  // Send verification email
@@ -53,14 +53,14 @@ export async function GET(request: Request) {
53
53
 
54
54
  // Delete existing sessions for this user
55
55
  const existingSessions = await db_query(db,
56
- "SELECT ID FROM usersession WHERE userid = ?",
56
+ "SELECT id FROM usersession WHERE userid = ?",
57
57
  [user.userid]
58
58
  );
59
59
 
60
60
  if (existingSessions && existingSessions.length > 0) {
61
- const sessionIds = existingSessions.map(session => session.ID);
61
+ const sessionIds = existingSessions.map(session => session.id);
62
62
  const placeholders = sessionIds.map(() => '?').join(',');
63
- await db_query(db, `DELETE FROM usersession WHERE ID IN (${placeholders})`, sessionIds);
63
+ await db_query(db, `DELETE FROM usersession WHERE id IN (${placeholders})`, sessionIds);
64
64
  }
65
65
 
66
66
  // Generate secure session token and ID
@@ -69,7 +69,7 @@ export async function GET(request: Request) {
69
69
 
70
70
  // Create new session with secure token
71
71
  await db_query(db,
72
- "INSERT INTO usersession (ID, SessionToken, userid, ExpirationDate) VALUES (?, ?, ?, ?)",
72
+ "INSERT INTO usersession (id, sessiontoken, userid, expirationdate) VALUES (?, ?, ?, ?)",
73
73
  [sessionId, sessionToken, user.userid, new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString()]
74
74
  );
75
75
 
@@ -86,7 +86,7 @@ export async function GET(request: Request) {
86
86
  });
87
87
 
88
88
  // Redirect to home page or dashboard with success message
89
- const siteDomain = process.env.SITE_DOMAIN || 'https://sitepaige.com';
89
+ const siteDomain = process.env.NODE_ENV === 'production' ? process.env.DOMAIN : process.env.LOCAL_DOMAIN;
90
90
  const redirectUrl = new URL('/', siteDomain);
91
91
  redirectUrl.searchParams.set('verified', 'true');
92
92
 
@@ -96,7 +96,7 @@ export async function GET(request: Request) {
96
96
  console.error('Email verification error:', error);
97
97
 
98
98
  // Redirect to home with error
99
- const siteDomain = process.env.SITE_DOMAIN || 'https://sitepaige.com';
99
+ const siteDomain = process.env.NODE_ENV === 'production' ? process.env.DOMAIN : process.env.LOCAL_DOMAIN;
100
100
  const redirectUrl = new URL('/', siteDomain);
101
101
  redirectUrl.searchParams.set('error', 'verification_failed');
102
102