sitepaige-mcp-server 1.0.3 → 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 (38) 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 +9 -9
  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 +12 -11
  10. package/defaultapp/api/Auth/route.ts +39 -39
  11. package/defaultapp/api/Auth/verify-email/route.ts +4 -4
  12. package/defaultapp/api/admin/users/route.ts +5 -3
  13. package/defaultapp/auth/auth.ts +9 -9
  14. package/defaultapp/db-mysql.ts +1 -1
  15. package/defaultapp/db-postgres.ts +1 -1
  16. package/defaultapp/db-sqlite.ts +1 -1
  17. package/defaultapp/db-users.ts +63 -63
  18. package/dist/components/IntegrationComponent.tsx +1 -0
  19. package/dist/components/admin.tsx +30 -27
  20. package/dist/components/auth.tsx +9 -9
  21. package/dist/components/cta.tsx +3 -10
  22. package/dist/components/headerlogin.tsx +9 -9
  23. package/dist/components/login.tsx +7 -4
  24. package/dist/components/logincallback.tsx +1 -0
  25. package/dist/components/menu.tsx +0 -6
  26. package/dist/components/profile.tsx +12 -11
  27. package/dist/defaultapp/api/Auth/route.ts +39 -39
  28. package/dist/defaultapp/api/Auth/verify-email/route.ts +4 -4
  29. package/dist/defaultapp/api/admin/users/route.ts +5 -3
  30. package/dist/defaultapp/auth/auth.ts +9 -9
  31. package/dist/defaultapp/db-mysql.ts +1 -1
  32. package/dist/defaultapp/db-postgres.ts +1 -1
  33. package/dist/defaultapp/db-sqlite.ts +1 -1
  34. package/dist/defaultapp/db-users.ts +63 -63
  35. package/dist/generators/sql.js +11 -3
  36. package/dist/generators/sql.js.map +1 -1
  37. package/dist/generators/views.js +2 -2
  38. package/package.json +1 -1
@@ -9,7 +9,7 @@ checked in the system build settings. It is safe to modify this file without it
9
9
  import React, { useState } from 'react';
10
10
 
11
11
  interface LoginProps {
12
- providers: ('apple' | 'facebook' | 'github' | 'google' | 'username')[];
12
+ providers: ('apple' | 'facebook' | 'github' | 'google' | 'userpass')[];
13
13
  }
14
14
 
15
15
  export default function Login({ providers }: LoginProps) {
@@ -62,6 +62,7 @@ export default function Login({ providers }: LoginProps) {
62
62
  headers: {
63
63
  'Content-Type': 'application/json'
64
64
  },
65
+ credentials: 'include', // Include cookies in request
65
66
  body: JSON.stringify({ email: resendEmail || email })
66
67
  });
67
68
 
@@ -101,6 +102,7 @@ export default function Login({ providers }: LoginProps) {
101
102
  headers: {
102
103
  'Content-Type': 'application/json'
103
104
  },
105
+ credentials: 'include', // Include cookies in request
104
106
  body: JSON.stringify({ email, password })
105
107
  });
106
108
 
@@ -121,7 +123,8 @@ export default function Login({ providers }: LoginProps) {
121
123
  headers: {
122
124
  'Content-Type': 'application/json'
123
125
  },
124
- body: JSON.stringify({ email, password, provider: 'username' })
126
+ credentials: 'include', // Include cookies in request
127
+ body: JSON.stringify({ email, password, provider: 'userpass' })
125
128
  });
126
129
 
127
130
  const data = await response.json();
@@ -145,8 +148,8 @@ export default function Login({ providers }: LoginProps) {
145
148
  }
146
149
  };
147
150
 
148
- const showUsernamePasswordForm = providers?.includes('username');
149
- const oauthProviders = providers?.filter(p => p !== 'username') || [];
151
+ const showUsernamePasswordForm = providers?.includes('userpass');
152
+ const oauthProviders = providers?.filter(p => p !== 'userpass') || [];
150
153
 
151
154
  return (
152
155
  <div className="flex flex-col items-center justify-center min-h-[500px] p-4">
@@ -44,6 +44,7 @@ export default function LoginCallback({ code, state }: LoginCallbackProps) {
44
44
  headers: {
45
45
  'Content-Type': 'application/json',
46
46
  },
47
+ credentials: 'include',
47
48
  body: JSON.stringify({
48
49
  code,
49
50
  provider
@@ -60,7 +60,6 @@ export default function Menu({ menu, onClick, pages = [] }: MenuProps) {
60
60
  const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
61
61
  const [isMobile, setIsMobile] = useState(false);
62
62
  const [selectedPage, setSelectedPage] = useState<string | null>(null);
63
- const [isPaigeLoading, setIsPaigeLoading] = useState(false);
64
63
 
65
64
  // Handle case where menu is undefined/null
66
65
  if (!menu) {
@@ -230,7 +229,6 @@ export default function Menu({ menu, onClick, pages = [] }: MenuProps) {
230
229
  items-center
231
230
  justify-center
232
231
  ${isSelected ? 'border-blue-600 bg-blue-50' : ''}
233
- ${isPaigeLoading ? 'opacity-50 cursor-not-allowed' : ''}
234
232
  `}>
235
233
  <h3
236
234
  className={`${isSelected ? 'font-bold' : 'font-medium'} text-gray-800`}
@@ -284,10 +282,6 @@ export default function Menu({ menu, onClick, pages = [] }: MenuProps) {
284
282
  href={linkUrl}
285
283
  onClick={(e) => {
286
284
  e.preventDefault();
287
- if (isPaigeLoading) {
288
- console.log('Navigation blocked: Paige is currently processing a request');
289
- return;
290
- }
291
285
  setSelectedPage(item.page);
292
286
  onClick?.();
293
287
  }}
@@ -9,9 +9,9 @@ checked in the system build settings. It is safe to modify this file without it
9
9
  import { useState, useEffect } from 'react';
10
10
 
11
11
  interface UserProfile {
12
- ID: string;
13
- UserName: string;
14
- AvatarURL: string | null;
12
+ id: string;
13
+ username: string;
14
+ avatarurl: string | null;
15
15
  }
16
16
 
17
17
  export default function Profile() {
@@ -23,7 +23,8 @@ export default function Profile() {
23
23
  const fetchProfile = async () => {
24
24
  try {
25
25
  const response = await fetch('/api/Auth', {
26
- method: 'GET'
26
+ method: 'GET',
27
+ credentials: 'include'
27
28
  });
28
29
 
29
30
  if (!response.ok) {
@@ -39,9 +40,9 @@ export default function Profile() {
39
40
  // Use the user object from the response
40
41
  const userData = data.user;
41
42
  setProfile({
42
- ID: userData.userid,
43
- UserName: userData.UserName,
44
- AvatarURL: userData.AvatarURL
43
+ id: userData.userid,
44
+ username: userData.username,
45
+ avatarurl: userData.avatarurl
45
46
  });
46
47
  } catch (err) {
47
48
  setError(err instanceof Error ? err.message : 'An error occurred');
@@ -68,17 +69,17 @@ export default function Profile() {
68
69
  return (
69
70
  <div className="max-w-md mx-auto mt-8 p-6 bg-white rounded-lg shadow-md">
70
71
  <div className="flex flex-col items-center">
71
- {profile.AvatarURL && (
72
+ {profile.avatarurl && (
72
73
  <img
73
- src={profile.AvatarURL}
74
+ src={profile.avatarurl}
74
75
  alt="Profile avatar"
75
76
  className="w-32 h-32 rounded-full mb-4"
76
77
  referrerPolicy="no-referrer"
77
78
  crossOrigin="anonymous"
78
79
  />
79
80
  )}
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>
81
+ <h2 className="text-2xl font-semibold text-gray-800">{profile.username}</h2>
82
+ <p className="text-gray-500 mt-2">User ID: {profile.id}</p>
82
83
  </div>
83
84
  </div>
84
85
  );
@@ -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
 
@@ -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
 
@@ -28,9 +28,11 @@ async function checkAdminAuth(): Promise<{ isAdmin: boolean; userId?: string }>
28
28
 
29
29
  // Get session
30
30
  const sessions = await db_query(db,
31
- "SELECT userid FROM UserSession WHERE SessionToken = ?",
31
+ "SELECT userid FROM usersession WHERE sessiontoken = ?",
32
32
  [sessionId]
33
33
  );
34
+
35
+ console.log(sessions);
34
36
 
35
37
  if (sessions.length === 0) {
36
38
  return { isAdmin: false };
@@ -38,8 +40,8 @@ async function checkAdminAuth(): Promise<{ isAdmin: boolean; userId?: string }>
38
40
 
39
41
  // Check if user is admin
40
42
  const user = await getUserByID(sessions[0].userid);
41
-
42
- if (!user || user.UserLevel !== 2) {
43
+
44
+ if (!user || user.userlevel !== 2) {
43
45
  return { isAdmin: false };
44
46
  }
45
47
 
@@ -1,14 +1,14 @@
1
1
  import { cookies } from 'next/headers';
2
2
 
3
- export async function check_auth(db: any, db_query: any): Promise<{ userid: string, UserLevel: number, UserTier: number, IsAdmin: boolean }> {
3
+ export async function check_auth(db: any, db_query: any): Promise<{ userid: string, userlevel: number, usertier: number, isadmin: boolean }> {
4
4
  const cookieStore = await cookies();
5
5
  const sessionId = cookieStore.get('session_id')?.value;
6
6
 
7
7
  const sessionInfo = {
8
8
  userid: '',
9
- UserLevel: 0,
10
- UserTier: 0,
11
- IsAdmin: false
9
+ userlevel: 0,
10
+ usertier: 0,
11
+ isadmin: false
12
12
  };
13
13
 
14
14
  if (!sessionId) {
@@ -16,16 +16,16 @@ export async function check_auth(db: any, db_query: any): Promise<{ userid: stri
16
16
  }
17
17
 
18
18
  // SQLite is case-insensitive for identifiers, but use standard column names (no quotes, correct names)
19
- const session = await db_query(db, 'SELECT userid FROM UserSession WHERE SessionToken = ?', [sessionId]);
19
+ const session = await db_query(db, 'SELECT userid FROM usersession WHERE sessiontoken = ?', [sessionId]);
20
20
  if (session.length > 0) {
21
21
  sessionInfo.userid = session[0].userid;
22
22
 
23
23
  // In your Users table, the primary key is userid, and there is no IsAdmin column, but UserLevel (2 = admin)
24
- const user = await db_query(db, 'SELECT UserLevel, UserTier FROM Users WHERE userid = ?', [session[0].userid]);
24
+ const user = await db_query(db, 'SELECT userlevel, usertier FROM users WHERE userid = ?', [session[0].userid]);
25
25
  if (user.length > 0) {
26
- sessionInfo.UserLevel = user[0].UserLevel;
27
- sessionInfo.IsAdmin = user[0].UserLevel === 2;
28
- sessionInfo.UserTier = user[0].UserTier;
26
+ sessionInfo.userlevel = user[0].userlevel;
27
+ sessionInfo.isadmin = user[0].userlevel === 2;
28
+ sessionInfo.usertier = user[0].usertier;
29
29
  }
30
30
  }
31
31
  return sessionInfo;
@@ -95,7 +95,7 @@ export async function db_query(
95
95
  */
96
96
  export function db_migrate(model: Model, dbType: string): string {
97
97
 
98
- const sanitizedTableName = model.name;
98
+ const sanitizedTableName = model.name.toLowerCase().replace(/\s+/g, '_');
99
99
 
100
100
  // Start with the model's fields
101
101
  let fields = [...model.fields];
@@ -101,7 +101,7 @@ export async function db_query(
101
101
  */
102
102
  export function db_migrate(model: Model, dbType: string): string {
103
103
 
104
- const sanitizedTableName = model.name;
104
+ const sanitizedTableName = model.name.toLowerCase().replace(/\s+/g, '_');
105
105
 
106
106
  // Start with the model's fields
107
107
  let fields = [...model.fields];
@@ -175,7 +175,7 @@ export async function db_query(
175
175
  export function db_migrate(model: Model, dbType: string): string {
176
176
  // Special handling for auth tables - create them first
177
177
 
178
- const sanitizedTableName = model.name;
178
+ const sanitizedTableName = model.name.toLowerCase().replace(/\s+/g, '_');
179
179
 
180
180
  // Start with the model's fields
181
181
  let fields = [...model.fields];