ultimate-jekyll-manager 0.0.119 → 0.0.120

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 (28) hide show
  1. package/CLAUDE.md +102 -2
  2. package/README.md +171 -2
  3. package/TODO.md +10 -2
  4. package/_backup/form-manager.backup.js +1020 -0
  5. package/dist/assets/js/libs/auth/pages.js +64 -136
  6. package/dist/assets/js/libs/form-manager.js +643 -775
  7. package/dist/assets/js/pages/account/sections/api-keys.js +37 -52
  8. package/dist/assets/js/pages/account/sections/connections.js +37 -46
  9. package/dist/assets/js/pages/account/sections/delete.js +46 -66
  10. package/dist/assets/js/pages/account/sections/profile.js +37 -56
  11. package/dist/assets/js/pages/account/sections/security.js +100 -126
  12. package/dist/assets/js/pages/admin/notifications/new/index.js +72 -157
  13. package/dist/assets/js/pages/blog/index.js +29 -51
  14. package/dist/assets/js/pages/contact/index.js +110 -144
  15. package/dist/assets/js/pages/download/index.js +38 -86
  16. package/dist/assets/js/pages/oauth2/index.js +17 -17
  17. package/dist/assets/js/pages/payment/checkout/index.js +23 -36
  18. package/dist/assets/js/pages/test/libraries/form-manager/index.js +194 -0
  19. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signin.html +2 -2
  20. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html +2 -2
  21. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/contact.html +10 -37
  22. package/dist/defaults/dist/pages/test/libraries/form-manager.html +181 -0
  23. package/dist/gulp/tasks/serve.js +18 -0
  24. package/dist/lib/logger.js +1 -1
  25. package/firebase-debug.log +392 -0
  26. package/package.json +6 -6
  27. package/.playwright-mcp/page-2025-10-22T19-11-27-666Z.png +0 -0
  28. package/.playwright-mcp/page-2025-10-22T19-11-57-357Z.png +0 -0
@@ -1,4 +1,8 @@
1
- // Security section module
1
+ /**
2
+ * Security Section JavaScript
3
+ */
4
+
5
+ // Libraries
2
6
  import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';
3
7
  import { FormManager } from '__main_assets__/js/libs/form-manager.js';
4
8
  import { getPrerenderedIcon } from '__main_assets__/js/libs/prerendered-icons.js';
@@ -6,7 +10,11 @@ import { getPrerenderedIcon } from '__main_assets__/js/libs/prerendered-icons.js
6
10
  let webManager = null;
7
11
  let firebaseAuth = null;
8
12
  let signinMethodForms = new Map(); // Store FormManager instances for signin methods
9
- let signoutAllForm = null; // FormManager instance for sign out all sessions
13
+ let signoutAllFormManager = null; // FormManager instance for sign out all sessions
14
+
15
+ // Check query string for popup parameter
16
+ const url = new URL(window.location.href);
17
+ const useAuthPopup = url.searchParams.get('authPopup') === 'true' || window !== window.top;
10
18
 
11
19
  // Initialize security section
12
20
  export function init(wm) {
@@ -17,7 +25,9 @@ export function init(wm) {
17
25
 
18
26
  // Load security data
19
27
  export function loadData(account) {
20
- if (!account) return;
28
+ if (!account) {
29
+ return;
30
+ }
21
31
 
22
32
  console.log('[DEBUG] security.js - loadData() called with account:', account);
23
33
 
@@ -106,7 +116,7 @@ async function updateSigninMethods() {
106
116
  $googleEmail: !!$googleEmail,
107
117
  $googleForm: !!$googleForm,
108
118
  $connectButton: !!$connectButton,
109
- $disconnectButton: !!$disconnectButton
119
+ $disconnectButton: !!$disconnectButton,
110
120
  });
111
121
 
112
122
  if ($googleEmail && $connectButton && $disconnectButton) {
@@ -161,7 +171,9 @@ function update2FAStatus(twoFactorData) {
161
171
  // Update active sessions
162
172
  async function updateActiveSessions(account) {
163
173
  const $sessionsList = document.getElementById('active-sessions-list');
164
- if (!$sessionsList) return;
174
+ if (!$sessionsList) {
175
+ return;
176
+ }
165
177
 
166
178
  const sessions = [];
167
179
 
@@ -179,7 +191,7 @@ async function updateActiveSessions(account) {
179
191
  region: account.activity.geolocation?.region,
180
192
  country: account.activity.geolocation?.country,
181
193
  timestamp: account.activity.created?.timestamp,
182
- timestampUNIX: account.activity.created?.timestampUNIX
194
+ timestampUNIX: account.activity.created?.timestampUNIX,
183
195
  };
184
196
  sessions.push(currentSession);
185
197
  }
@@ -195,9 +207,7 @@ async function updateActiveSessions(account) {
195
207
  tries: 2,
196
208
  body: {
197
209
  command: 'user:get-active-sessions',
198
- payload: {
199
- // id: 'app',
200
- },
210
+ payload: {},
201
211
  },
202
212
  });
203
213
 
@@ -240,7 +250,6 @@ async function updateActiveSessions(account) {
240
250
  sessions.push(sessionObj);
241
251
  });
242
252
  }
243
-
244
253
  } catch (error) {
245
254
  console.error('Failed to get active sessions:', error);
246
255
  }
@@ -259,7 +268,7 @@ async function updateActiveSessions(account) {
259
268
  region: account.lastActivity.geolocation?.region,
260
269
  country: account.lastActivity.geolocation?.country,
261
270
  timestamp: account.lastActivity.timestamp,
262
- timestampUNIX: account.lastActivity.timestampUNIX
271
+ timestampUNIX: account.lastActivity.timestampUNIX,
263
272
  };
264
273
 
265
274
  // Only add if it's different from current session (different IP or timestamp)
@@ -319,21 +328,16 @@ function initializeSigninMethodForms() {
319
328
  console.log('[DEBUG] security.js - Initializing password FormManager');
320
329
 
321
330
  const formManager = new FormManager($passwordForm, {
322
- allowMultipleSubmissions: false,
323
- autoDisable: true,
324
- showSpinner: true,
325
- submitButtonSuccessText: 'Email Sent'
331
+ allowResubmit: false,
332
+ submittingText: 'Sending...',
333
+ submittedText: 'Email Sent!',
326
334
  });
327
335
 
328
336
  signinMethodForms.set('password', formManager);
329
337
 
330
- formManager.addEventListener('submit', async () => {
331
- try {
332
- await handleChangePassword();
333
- } catch (error) {
334
- formManager.showError(error);
335
- formManager.setFormState('ready');
336
- }
338
+ formManager.on('submit', async () => {
339
+ await handleChangePassword();
340
+ formManager.showSuccess('Password reset email sent!');
337
341
  });
338
342
  }
339
343
 
@@ -345,44 +349,24 @@ function initializeSigninMethodForms() {
345
349
  console.log('[DEBUG] security.js - Google form exists:', !!$googleForm);
346
350
 
347
351
  const formManager = new FormManager($googleForm, {
348
- autoDisable: true,
349
- showSpinner: true
352
+ submittingText: 'Connecting...',
350
353
  });
351
354
 
352
355
  signinMethodForms.set('google', formManager);
353
356
  console.log('[DEBUG] security.js - Google FormManager initialized and stored');
354
357
 
355
- formManager.addEventListener('submit', async (event) => {
356
- event.preventDefault();
357
- const { submitButton } = event.detail;
358
-
358
+ formManager.on('submit', async ({ $submitButton }) => {
359
359
  // Determine action from the clicked button's data-action attribute
360
- const action = submitButton?.getAttribute('data-action');
361
-
362
- try {
363
- if (action === 'disconnect') {
364
- await disconnectGoogleProvider();
365
- } else if (action === 'connect') {
366
- await connectGoogleProvider();
367
- }
360
+ const action = $submitButton?.getAttribute('data-action');
368
361
 
369
- // Set form state back to ready first
370
- formManager.setFormState('ready');
371
-
372
- // Then update display (this will set the button text correctly again)
373
- updateSigninMethods();
374
- } catch (error) {
375
- // Reset form state
376
- formManager.setFormState('ready');
377
-
378
- // If user cancelled, also update the display to ensure button state is correct
379
- if (error.message === 'Disconnection cancelled') {
380
- updateSigninMethods();
381
- } else {
382
- // Show error for other failures
383
- formManager.showError(error);
384
- }
362
+ if (action === 'disconnect') {
363
+ await disconnectGoogleProvider();
364
+ } else if (action === 'connect') {
365
+ await connectGoogleProvider();
385
366
  }
367
+
368
+ // Update display after success
369
+ updateSigninMethods();
386
370
  });
387
371
  }
388
372
 
@@ -397,44 +381,31 @@ function initializeSigninMethodForms() {
397
381
  function initializeSignoutAllForm() {
398
382
  const $form = document.getElementById('signout-all-sessions-form');
399
383
 
400
- if ($form && !signoutAllForm) {
401
- signoutAllForm = new FormManager($form, {
402
- autoDisable: true,
403
- showSpinner: true
384
+ if ($form && !signoutAllFormManager) {
385
+ signoutAllFormManager = new FormManager($form, {
386
+ submittingText: 'Signing out...',
404
387
  });
405
388
 
406
- signoutAllForm.addEventListener('submit', async (event) => {
407
- event.preventDefault();
408
-
389
+ signoutAllFormManager.on('submit', async () => {
409
390
  // 1ms wait to allow form state to update and show processing
410
391
  await new Promise(resolve => setTimeout(resolve, 1));
411
392
 
412
- try {
413
- // Confirm sign out
414
- if (!confirm('Are you sure you want to sign out of all sessions? This will log you out everywhere, including this device.')) {
415
- return signoutAllForm.setFormState('ready');
416
- }
393
+ // Confirm sign out
394
+ if (!confirm('Are you sure you want to sign out of all sessions? This will log you out everywhere, including this device.')) {
395
+ throw new Error('Sign out cancelled.');
396
+ }
417
397
 
418
- // Sign out of all sessions
419
- await webManager.auth().signOut();
398
+ // Sign out of all sessions
399
+ await webManager.auth().signOut();
420
400
 
421
- // Show success message
422
- webManager.utilities().showNotification('Successfully signed out of all sessions.', 'success');
401
+ // Show success message
402
+ signoutAllFormManager.showSuccess('Successfully signed out of all sessions.');
423
403
 
424
- // Note: The page will likely redirect due to auth state change
425
- // so we might not need to reset form state
426
- } catch (error) {
427
- if (error.message !== 'Sign out cancelled') {
428
- signoutAllForm.showError(error);
429
- }
430
- signoutAllForm.setFormState('ready');
431
- }
404
+ // Note: The page will likely redirect due to auth state change
432
405
  });
433
406
  }
434
407
  }
435
408
 
436
-
437
-
438
409
  // Connect Google provider
439
410
  async function connectGoogleProvider() {
440
411
  // Dynamic import of Firebase auth methods
@@ -442,35 +413,38 @@ async function connectGoogleProvider() {
442
413
 
443
414
  const provider = new GoogleAuthProvider();
444
415
 
445
- try {
446
- // Try popup first for better UX
447
- const result = await linkWithPopup(firebaseAuth.currentUser, provider);
448
- webManager.utilities().showNotification('Google account connected successfully', 'success');
416
+ // Use popup if query parameter is set, otherwise use redirect
417
+ if (useAuthPopup) {
418
+ try {
419
+ const result = await linkWithPopup(firebaseAuth.currentUser, provider);
420
+ webManager.utilities().showNotification('Google account connected successfully', 'success');
449
421
 
450
- // Force refresh of the current user to get updated provider data
451
- await firebaseAuth.currentUser.reload();
422
+ // Force refresh of the current user to get updated provider data
423
+ await firebaseAuth.currentUser.reload();
452
424
 
453
- return result;
454
- } catch (error) {
455
- // Check if we should fallback to redirect
456
- if (error.code === 'auth/popup-blocked'
457
- || error.code === 'auth/popup-closed-by-user'
458
- || error.code === 'auth/cancelled-popup-request') {
425
+ return result;
426
+ } catch (error) {
427
+ // Check if we should fallback to redirect
428
+ if (error.code === 'auth/popup-blocked'
429
+ || error.code === 'auth/popup-closed-by-user'
430
+ || error.code === 'auth/cancelled-popup-request') {
459
431
 
460
- console.log('Popup failed, falling back to redirect:', error.code);
432
+ console.log('Popup failed, falling back to redirect:', error.code);
461
433
 
462
- // Fallback to redirect
463
- try {
434
+ // Fallback to redirect
464
435
  await linkWithRedirect(firebaseAuth.currentUser, provider);
465
436
  // This will redirect the page, so no immediate result
466
- } catch (redirectError) {
467
- throw redirectError;
437
+ } else if (error.code === 'auth/credential-already-in-use') {
438
+ throw new Error('This Google account is already linked to another user');
439
+ } else {
440
+ throw error;
468
441
  }
469
- } else if (error.code === 'auth/credential-already-in-use') {
470
- throw new Error('This Google account is already linked to another user');
471
- } else {
472
- throw error;
473
442
  }
443
+ } else {
444
+ // Use redirect by default
445
+ console.log('Using redirect for Google account linking');
446
+ await linkWithRedirect(firebaseAuth.currentUser, provider);
447
+ // This will redirect the page, so no immediate result
474
448
  }
475
449
  }
476
450
 
@@ -481,7 +455,7 @@ async function disconnectGoogleProvider() {
481
455
 
482
456
  // Confirm disconnection
483
457
  if (!confirm('Are you sure you want to disconnect your Google account?')) {
484
- throw new Error('Disconnection cancelled');
458
+ throw new Error('Disconnection cancelled.');
485
459
  }
486
460
 
487
461
  // Dynamic import of Firebase auth methods
@@ -508,22 +482,16 @@ async function disconnectGoogleProvider() {
508
482
 
509
483
  // Handle change password
510
484
  async function handleChangePassword() {
511
- try {
512
- const user = webManager.auth().getUser();
513
- if (!user || !user.email) {
514
- throw new Error('Please log in to reset your password.');
515
- }
485
+ const user = webManager.auth().getUser();
486
+ if (!user || !user.email) {
487
+ throw new Error('Please log in to reset your password.');
488
+ }
516
489
 
517
- // Import Firebase auth method
518
- const { sendPasswordResetEmail } = await import('@firebase/auth');
490
+ // Import Firebase auth method
491
+ const { sendPasswordResetEmail } = await import('@firebase/auth');
519
492
 
520
- // Send password reset email
521
- await sendPasswordResetEmail(firebaseAuth, user.email);
522
- webManager.utilities().showNotification('Password reset email sent. Please check your inbox.', 'info');
523
- } catch (error) {
524
- console.error('Failed to send password reset:', error);
525
- throw new Error(error.message || 'Failed to send password reset email. Please try again.');
526
- }
493
+ // Send password reset email
494
+ await sendPasswordResetEmail(firebaseAuth, user.email);
527
495
  }
528
496
 
529
497
  // Handle 2FA button click
@@ -540,10 +508,11 @@ async function handle2FAClick(event) {
540
508
  }
541
509
  }
542
510
 
543
-
544
511
  // Get device from user agent string
545
512
  function getDeviceFromUserAgent(userAgent) {
546
- if (!userAgent) return 'Unknown Device';
513
+ if (!userAgent) {
514
+ return 'Unknown Device';
515
+ }
547
516
 
548
517
  const ua = userAgent.toLowerCase();
549
518
 
@@ -568,7 +537,9 @@ function getDeviceFromUserAgent(userAgent) {
568
537
 
569
538
  // Get browser from user agent string
570
539
  function getBrowserFromUserAgent(userAgent) {
571
- if (!userAgent) return 'Unknown Browser';
540
+ if (!userAgent) {
541
+ return 'Unknown Browser';
542
+ }
572
543
 
573
544
  const ua = userAgent.toLowerCase();
574
545
 
@@ -585,7 +556,9 @@ function getBrowserFromUserAgent(userAgent) {
585
556
 
586
557
  // Get platform name from platform string
587
558
  function getPlatformName(platform) {
588
- if (!platform) return 'Unknown Device';
559
+ if (!platform) {
560
+ return 'Unknown Device';
561
+ }
589
562
 
590
563
  const platformLower = platform.toLowerCase();
591
564
 
@@ -652,7 +625,6 @@ function formatSessionLocation(session) {
652
625
  return parts.length > 0 ? parts.join(', ') : null;
653
626
  }
654
627
 
655
-
656
628
  // Generate fake sessions for development mode
657
629
  function generateFakeSessions() {
658
630
  const now = Date.now();
@@ -665,42 +637,44 @@ function generateFakeSessions() {
665
637
  platform: 'Windows',
666
638
  ip: '98.137.246.8',
667
639
  timestamp: new Date(now - (3 * oneHour)).toISOString(),
668
- timestampUNIX: Math.floor((now - (3 * oneHour)) / 1000)
640
+ timestampUNIX: Math.floor((now - (3 * oneHour)) / 1000),
669
641
  },
670
642
  'session_def456': {
671
643
  _current: false,
672
644
  platform: 'Darwin', // macOS
673
645
  ip: '192.168.1.42',
674
646
  timestamp: new Date(now - (8 * oneHour)).toISOString(),
675
- timestampUNIX: Math.floor((now - (8 * oneHour)) / 1000)
647
+ timestampUNIX: Math.floor((now - (8 * oneHour)) / 1000),
676
648
  },
677
649
  'session_ghi789': {
678
650
  _current: false,
679
651
  platform: 'Linux',
680
652
  ip: '45.62.189.3',
681
653
  timestamp: new Date(now - (oneDay)).toISOString(),
682
- timestampUNIX: Math.floor((now - (oneDay)) / 1000)
654
+ timestampUNIX: Math.floor((now - (oneDay)) / 1000),
683
655
  },
684
656
  'session_jkl012': {
685
657
  _current: false,
686
658
  platform: 'Win32',
687
659
  ip: '203.0.113.45',
688
660
  timestamp: new Date(now - (2 * oneDay)).toISOString(),
689
- timestampUNIX: Math.floor((now - (2 * oneDay)) / 1000)
661
+ timestampUNIX: Math.floor((now - (2 * oneDay)) / 1000),
690
662
  },
691
663
  'session_mno345': {
692
664
  _current: false,
693
665
  platform: 'Mac',
694
666
  ip: '172.217.16.195',
695
667
  timestamp: new Date(now - (5 * oneDay)).toISOString(),
696
- timestampUNIX: Math.floor((now - (5 * oneDay)) / 1000)
697
- }
668
+ timestampUNIX: Math.floor((now - (5 * oneDay)) / 1000),
669
+ },
698
670
  };
699
671
  }
700
672
 
701
673
  // Format date helper
702
674
  function formatDate(timestamp) {
703
- if (!timestamp) return 'Unknown';
675
+ if (!timestamp) {
676
+ return 'Unknown';
677
+ }
704
678
 
705
679
  const date = new Date(timestamp);
706
680
  const now = new Date();