mbkauthe 1.1.7 → 1.1.9
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.
- package/index.js +9 -0
- package/lib/info.js +4 -457
- package/lib/main.js +1 -0
- package/package.json +2 -1
- package/views/loginmbkauthe.handlebars +520 -207
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import express from "express"; // Add this line
|
|
2
2
|
import router from "./lib/main.js";
|
|
3
|
+
import { getLatestVersion } from "./lib/info.js";
|
|
3
4
|
import { engine } from "express-handlebars";
|
|
4
5
|
import dotenv from "dotenv";
|
|
5
6
|
import path from "path";
|
|
@@ -63,6 +64,14 @@ app.engine("handlebars", engine({
|
|
|
63
64
|
|
|
64
65
|
app.set("view engine", "handlebars");
|
|
65
66
|
|
|
67
|
+
import { createRequire } from "module";
|
|
68
|
+
const require = createRequire(import.meta.url);
|
|
69
|
+
const packageJson = require("./package.json");
|
|
70
|
+
const latestVersion = await getLatestVersion();
|
|
71
|
+
if(latestVersion !== packageJson.version) {
|
|
72
|
+
console.warn(`Warning: The current version (${packageJson.version}) is not the latest version (${latestVersion}). Please update mbkauthe.`);
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
export { validateSession, checkRolePermission, validateSessionAndRole, getUserData, authenticate, authapi } from "./lib/validateSessionAndRole.js";
|
|
67
76
|
export { dblogin } from "./lib/pool.js";
|
|
68
77
|
export default router;
|
package/lib/info.js
CHANGED
|
@@ -18,6 +18,7 @@ const router = express.Router();
|
|
|
18
18
|
router.get(["/mbkauthe/login"], (req, res) => {
|
|
19
19
|
return res.render("loginmbkauthe", {
|
|
20
20
|
layout: false,
|
|
21
|
+
customURL: mbkautheVar.loginRedirectURL || '/home',
|
|
21
22
|
userLoggedIn: !!req.session?.user,
|
|
22
23
|
UserName: req.session?.user?.username || ''
|
|
23
24
|
});
|
|
@@ -104,8 +105,8 @@ router.get(["/mbkauthe/info", "/mbkauthe/i"], async (_, res) => {
|
|
|
104
105
|
|
|
105
106
|
try {
|
|
106
107
|
pkgl = await getPackageLock();
|
|
107
|
-
|
|
108
|
-
latestVersion = "Under Development"; // Placeholder for the latest version
|
|
108
|
+
latestVersion = await getLatestVersion();
|
|
109
|
+
//latestVersion = "Under Development"; // Placeholder for the latest version
|
|
109
110
|
} catch (err) {
|
|
110
111
|
console.error("Error fetching package-lock.json:", err);
|
|
111
112
|
pkgl = { error: "Failed to fetch package-lock.json" };
|
|
@@ -499,460 +500,6 @@ router.get(["/mbkauthe/info", "/mbkauthe/i"], async (_, res) => {
|
|
|
499
500
|
`);
|
|
500
501
|
}
|
|
501
502
|
});
|
|
502
|
-
const DOCUMENTATION_TITLE = "Project Documentation";
|
|
503
|
-
const CACHE_TTL = 3600000; // 1 hour in milliseconds
|
|
504
|
-
|
|
505
|
-
// Cache for the rendered HTML
|
|
506
|
-
let cachedHtml = null;
|
|
507
|
-
let cacheTimestamp = 0;
|
|
508
|
-
|
|
509
|
-
router.get(["/mbkauthe/"], async (_, res) => {
|
|
510
|
-
try {
|
|
511
|
-
// Check cache first
|
|
512
|
-
const now = Date.now();
|
|
513
|
-
if (cachedHtml && (now - cacheTimestamp) < CACHE_TTL) {
|
|
514
|
-
return res.send(cachedHtml);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// Read and process file
|
|
518
|
-
let readmePath;
|
|
519
|
-
if (process.env.test === "true") {
|
|
520
|
-
readmePath = path.join(process.cwd(), "README.md");
|
|
521
|
-
}
|
|
522
|
-
else {
|
|
523
|
-
readmePath = path.join(process.cwd(), "./node_modules/mbkauthe/README.md");
|
|
524
|
-
}
|
|
525
|
-
const data = await fs.promises.readFile(readmePath, "utf8");
|
|
526
|
-
|
|
527
|
-
// Convert markdown to HTML
|
|
528
|
-
let html = marked(data, {
|
|
529
|
-
breaks: true,
|
|
530
|
-
gfm: true,
|
|
531
|
-
smartypants: true
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
// Process HTML with cheerio
|
|
535
|
-
const $ = cheerio.load(html);
|
|
536
|
-
|
|
537
|
-
// Add IDs to headers for anchor links
|
|
538
|
-
$('h1, h2, h3, h4, h5, h6').each(function () {
|
|
539
|
-
const id = $(this).text()
|
|
540
|
-
.toLowerCase()
|
|
541
|
-
.replace(/\s+/g, '-')
|
|
542
|
-
.replace(/[^\w-]+/g, '');
|
|
543
|
-
$(this).attr('id', id);
|
|
544
|
-
$(this).addClass('header-anchor');
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
// Fix table of contents links and add icons
|
|
548
|
-
$('a[href^="#"]').each(function () {
|
|
549
|
-
const href = $(this).attr('href');
|
|
550
|
-
const id = href.substring(1)
|
|
551
|
-
.toLowerCase()
|
|
552
|
-
.replace(/\s+/g, '-')
|
|
553
|
-
.replace(/[^\w-]+/g, '');
|
|
554
|
-
$(this).attr('href', `#${id}`);
|
|
555
|
-
$(this).addClass('toc-link');
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
// Add copy buttons to code blocks
|
|
559
|
-
$('pre').each(function () {
|
|
560
|
-
const $pre = $(this);
|
|
561
|
-
const $button = $(`<button class="copy-button" aria-label="Copy code">📋</button>`);
|
|
562
|
-
$pre.prepend($button);
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
// Create the full HTML response
|
|
566
|
-
const htmlContent = generateFullHtml($.html());
|
|
567
|
-
|
|
568
|
-
// Update cache
|
|
569
|
-
cachedHtml = htmlContent;
|
|
570
|
-
cacheTimestamp = now;
|
|
571
|
-
|
|
572
|
-
res.send(htmlContent);
|
|
573
|
-
} catch (err) {
|
|
574
|
-
console.error("Error processing documentation:", err);
|
|
575
|
-
res.status(500).send(generateErrorHtml());
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
function generateFullHtml(contentHtml) {
|
|
580
|
-
return `<!DOCTYPE html>
|
|
581
|
-
<html lang="en">
|
|
582
|
-
<head>
|
|
583
|
-
<meta charset="UTF-8">
|
|
584
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
585
|
-
<meta name="description" content="Project documentation generated from README.md">
|
|
586
|
-
<title>${DOCUMENTATION_TITLE}</title>
|
|
587
|
-
<style>
|
|
588
|
-
:root {
|
|
589
|
-
--primary-color: #bb86fc;
|
|
590
|
-
--primary-dark: #9a67ea;
|
|
591
|
-
--secondary-color: #03dac6;
|
|
592
|
-
--secondary-dark: #018786;
|
|
593
|
-
--background-dark: #121212;
|
|
594
|
-
--background-darker: #1e1e1e;
|
|
595
|
-
--background-light: #2d2d2d;
|
|
596
|
-
--text-primary: #e0e0e0;
|
|
597
|
-
--text-secondary: #a0a0a0;
|
|
598
|
-
--error-color: #cf6679;
|
|
599
|
-
--success-color: #4caf50;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
body {
|
|
603
|
-
font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
|
|
604
|
-
line-height: 1.6;
|
|
605
|
-
margin: 0;
|
|
606
|
-
padding: 0;
|
|
607
|
-
background-color: var(--background-dark);
|
|
608
|
-
color: var(--text-primary);
|
|
609
|
-
max-width: 1200px;
|
|
610
|
-
margin: 0 auto;
|
|
611
|
-
padding: 2rem;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
.header-anchor {
|
|
615
|
-
position: relative;
|
|
616
|
-
padding-left: 1.5rem;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
.header-anchor::before {
|
|
620
|
-
content: "#";
|
|
621
|
-
position: absolute;
|
|
622
|
-
left: 0;
|
|
623
|
-
color: var(--text-secondary);
|
|
624
|
-
opacity: 0;
|
|
625
|
-
transition: opacity 0.2s;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
.header-anchor:hover::before {
|
|
629
|
-
opacity: 1;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
pre {
|
|
633
|
-
position: relative;
|
|
634
|
-
background: var(--background-darker);
|
|
635
|
-
padding: 1.5rem;
|
|
636
|
-
border-radius: 8px;
|
|
637
|
-
overflow-x: auto;
|
|
638
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
.copy-button {
|
|
642
|
-
position: absolute;
|
|
643
|
-
top: 0.5rem;
|
|
644
|
-
right: 0.5rem;
|
|
645
|
-
background: var(--background-light);
|
|
646
|
-
color: var(--text-primary);
|
|
647
|
-
border: none;
|
|
648
|
-
border-radius: 4px;
|
|
649
|
-
padding: 0.25rem 0.5rem;
|
|
650
|
-
cursor: pointer;
|
|
651
|
-
opacity: 0;
|
|
652
|
-
transition: opacity 0.2s, background 0.2s;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
pre:hover .copy-button {
|
|
656
|
-
opacity: 1;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
.copy-button:hover {
|
|
660
|
-
background: var(--primary-color);
|
|
661
|
-
color: var(--background-dark);
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
.copy-button.copied {
|
|
665
|
-
background: var(--success-color);
|
|
666
|
-
color: white;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
code {
|
|
670
|
-
font-family: 'Fira Code', 'Courier New', monospace;
|
|
671
|
-
background: var(--background-darker);
|
|
672
|
-
padding: 0.2rem 0.4rem;
|
|
673
|
-
border-radius: 4px;
|
|
674
|
-
color: var(--secondary-color);
|
|
675
|
-
font-size: 0.9em;
|
|
676
|
-
word-wrap: break-word;
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
h1, h2, h3, h4, h5, h6 {
|
|
680
|
-
color: var(--primary-color);
|
|
681
|
-
margin-top: 1.8em;
|
|
682
|
-
margin-bottom: 0.8em;
|
|
683
|
-
scroll-margin-top: 1em;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
h1 {
|
|
687
|
-
font-size: 2.4rem;
|
|
688
|
-
border-bottom: 2px solid var(--primary-color);
|
|
689
|
-
padding-bottom: 0.5rem;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
h2 { font-size: 2rem; }
|
|
693
|
-
h3 { font-size: 1.6rem; }
|
|
694
|
-
|
|
695
|
-
a {
|
|
696
|
-
color: var(--secondary-color);
|
|
697
|
-
text-decoration: none;
|
|
698
|
-
transition: color 0.2s;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
a:hover {
|
|
702
|
-
color: var(--primary-color);
|
|
703
|
-
text-decoration: underline;
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
.toc-link {
|
|
707
|
-
display: inline-block;
|
|
708
|
-
padding: 0.2rem 0;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
.toc-link::before {
|
|
712
|
-
content: "→ ";
|
|
713
|
-
opacity: 0;
|
|
714
|
-
transition: opacity 0.2s;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
.toc-link:hover::before {
|
|
718
|
-
opacity: 1;
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
blockquote {
|
|
722
|
-
border-left: 4px solid var(--primary-color);
|
|
723
|
-
padding-left: 1.5rem;
|
|
724
|
-
margin-left: 0;
|
|
725
|
-
color: var(--text-secondary);
|
|
726
|
-
font-style: italic;
|
|
727
|
-
background: rgba(187, 134, 252, 0.05);
|
|
728
|
-
border-radius: 0 4px 4px 0;
|
|
729
|
-
padding: 1rem;
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
table {
|
|
733
|
-
border-collapse: collapse;
|
|
734
|
-
width: 100%;
|
|
735
|
-
margin: 1.5rem 0;
|
|
736
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
th, td {
|
|
740
|
-
border: 1px solid #444;
|
|
741
|
-
padding: 0.75rem;
|
|
742
|
-
text-align: left;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
th {
|
|
746
|
-
background-color: var(--background-darker);
|
|
747
|
-
font-weight: 600;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
tr:nth-child(even) {
|
|
751
|
-
background-color: rgba(255, 255, 255, 0.05);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
tr:hover {
|
|
755
|
-
background-color: rgba(187, 134, 252, 0.1);
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
img {
|
|
759
|
-
max-width: 100%;
|
|
760
|
-
height: auto;
|
|
761
|
-
border-radius: 8px;
|
|
762
|
-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
hr {
|
|
766
|
-
border: none;
|
|
767
|
-
height: 1px;
|
|
768
|
-
background-color: #444;
|
|
769
|
-
margin: 2rem 0;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
/* Dark mode toggle */
|
|
773
|
-
.theme-toggle {
|
|
774
|
-
position: fixed;
|
|
775
|
-
bottom: 1rem;
|
|
776
|
-
right: 1rem;
|
|
777
|
-
background: var(--background-light);
|
|
778
|
-
border: none;
|
|
779
|
-
border-radius: 50%;
|
|
780
|
-
width: 3rem;
|
|
781
|
-
height: 3rem;
|
|
782
|
-
display: flex;
|
|
783
|
-
align-items: center;
|
|
784
|
-
justify-content: center;
|
|
785
|
-
cursor: pointer;
|
|
786
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
787
|
-
z-index: 100;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
/* Responsive design */
|
|
791
|
-
@media (max-width: 768px) {
|
|
792
|
-
body {
|
|
793
|
-
padding: 1rem;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
h1 {
|
|
797
|
-
font-size: 2rem;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
h2 {
|
|
801
|
-
font-size: 1.7rem;
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
pre {
|
|
805
|
-
padding: 1rem;
|
|
806
|
-
font-size: 0.9em;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
/* Print styles */
|
|
811
|
-
@media print {
|
|
812
|
-
body {
|
|
813
|
-
background-color: white;
|
|
814
|
-
color: black;
|
|
815
|
-
padding: 0;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
a {
|
|
819
|
-
color: #0066cc;
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
pre, code {
|
|
823
|
-
background-color: #f5f5f5;
|
|
824
|
-
color: #333;
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
</style>
|
|
828
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Fira+Code&display=swap" rel="stylesheet">
|
|
829
|
-
</head>
|
|
830
|
-
<body>
|
|
831
|
-
<a href="/mbkauthe/info/" class="toc-link">mbkauthe Info</a>
|
|
832
|
-
<main>
|
|
833
|
-
${contentHtml}
|
|
834
|
-
</main>
|
|
835
|
-
|
|
836
|
-
<button class="theme-toggle" aria-label="Toggle theme">🌓</button>
|
|
837
|
-
|
|
838
|
-
<script>
|
|
839
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
840
|
-
// Smooth scrolling for TOC links
|
|
841
|
-
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
842
|
-
anchor.addEventListener('click', function(e) {
|
|
843
|
-
e.preventDefault();
|
|
844
|
-
const targetId = this.getAttribute('href');
|
|
845
|
-
const targetElement = document.querySelector(targetId);
|
|
846
|
-
|
|
847
|
-
if (targetElement) {
|
|
848
|
-
targetElement.scrollIntoView({
|
|
849
|
-
behavior: 'smooth',
|
|
850
|
-
block: 'start'
|
|
851
|
-
});
|
|
852
|
-
|
|
853
|
-
// Update URL without page jump
|
|
854
|
-
history.pushState(null, null, targetId);
|
|
855
|
-
}
|
|
856
|
-
});
|
|
857
|
-
});
|
|
858
|
-
|
|
859
|
-
// Copy button functionality
|
|
860
|
-
document.querySelectorAll('.copy-button').forEach(button => {
|
|
861
|
-
button.addEventListener('click', function() {
|
|
862
|
-
const pre = this.parentElement;
|
|
863
|
-
const code = pre.querySelector('code') || pre;
|
|
864
|
-
const range = document.createRange();
|
|
865
|
-
range.selectNode(code);
|
|
866
|
-
window.getSelection().removeAllRanges();
|
|
867
|
-
window.getSelection().addRange(range);
|
|
868
|
-
|
|
869
|
-
try {
|
|
870
|
-
const successful = document.execCommand('copy');
|
|
871
|
-
if (successful) {
|
|
872
|
-
this.textContent = '✓ Copied!';
|
|
873
|
-
this.classList.add('copied');
|
|
874
|
-
setTimeout(() => {
|
|
875
|
-
this.textContent = '📋';
|
|
876
|
-
this.classList.remove('copied');
|
|
877
|
-
}, 2000);
|
|
878
|
-
}
|
|
879
|
-
} catch (err) {
|
|
880
|
-
console.error('Failed to copy:', err);
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
window.getSelection().removeAllRanges();
|
|
884
|
-
});
|
|
885
|
-
});
|
|
886
|
-
|
|
887
|
-
// Highlight current section in view
|
|
888
|
-
const observerOptions = {
|
|
889
|
-
root: null,
|
|
890
|
-
rootMargin: '0px',
|
|
891
|
-
threshold: 0.5
|
|
892
|
-
};
|
|
893
|
-
|
|
894
|
-
const observer = new IntersectionObserver(function(entries) {
|
|
895
|
-
entries.forEach(function(entry) {
|
|
896
|
-
const id = entry.target.getAttribute('id');
|
|
897
|
-
if (entry.isIntersecting) {
|
|
898
|
-
document.querySelectorAll('a[href="#' + id + '"]').forEach(function(link) {
|
|
899
|
-
link.style.fontWeight = '600';
|
|
900
|
-
link.style.color = 'var(--primary-color)';
|
|
901
|
-
});
|
|
902
|
-
} else {
|
|
903
|
-
document.querySelectorAll('a[href="#' + id + '"]').forEach(function(link) {
|
|
904
|
-
link.style.fontWeight = '';
|
|
905
|
-
link.style.color = '';
|
|
906
|
-
});
|
|
907
|
-
}
|
|
908
|
-
});
|
|
909
|
-
}, observerOptions);
|
|
910
|
-
|
|
911
|
-
document.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(function(heading) {
|
|
912
|
-
if (heading.id) {
|
|
913
|
-
observer.observe(heading);
|
|
914
|
-
}
|
|
915
|
-
});
|
|
916
|
-
|
|
917
|
-
// Theme toggle functionality
|
|
918
|
-
const themeToggle = document.querySelector('.theme-toggle');
|
|
919
|
-
themeToggle.addEventListener('click', function() {
|
|
920
|
-
document.body.classList.toggle('light-theme');
|
|
921
|
-
const isLight = document.body.classList.contains('light-theme');
|
|
922
|
-
this.textContent = isLight ? '🌙' : '🌓';
|
|
923
|
-
localStorage.setItem('themePreference', isLight ? 'light' : 'dark');
|
|
924
|
-
});
|
|
925
|
-
|
|
926
|
-
// Load saved theme preference
|
|
927
|
-
const savedTheme = localStorage.getItem('themePreference');
|
|
928
|
-
if (savedTheme === 'light') {
|
|
929
|
-
document.body.classList.add('light-theme');
|
|
930
|
-
themeToggle.textContent = '🌙';
|
|
931
|
-
}
|
|
932
|
-
});
|
|
933
|
-
</script>
|
|
934
|
-
</body>
|
|
935
|
-
</html>`;
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
function generateErrorHtml() {
|
|
939
|
-
return `<!DOCTYPE html>
|
|
940
|
-
<html lang="en">
|
|
941
|
-
<head>
|
|
942
|
-
<meta charset="UTF-8">
|
|
943
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
944
|
-
<title>Error Loading Documentation</title>
|
|
945
|
-
</head>
|
|
946
|
-
<body>
|
|
947
|
-
<h1>Error Loading Documentation</h1>
|
|
948
|
-
<p>Failed to load README.md file. Please try again later.</p>
|
|
949
|
-
<p>If the problem persists, contact your system administrator.</p>
|
|
950
|
-
<a href="/">Return to Home</a>
|
|
951
|
-
<div class="error-details">
|
|
952
|
-
Error: ${err.message || 'Unknown error'}
|
|
953
|
-
</div>
|
|
954
|
-
</body>
|
|
955
|
-
</html>`;
|
|
956
|
-
}
|
|
957
503
|
|
|
504
|
+
export { getLatestVersion };
|
|
958
505
|
export default router;
|
package/lib/main.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mbkauthe",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "MBKTechStudio's reusable authentication system for Node.js applications.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"node-fetch": "^3.3.2",
|
|
40
40
|
"path": "^0.12.7",
|
|
41
41
|
"pg": "^8.14.1",
|
|
42
|
+
"speakeasy": "^2.0.0",
|
|
42
43
|
"url": "^0.11.4"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
@@ -1,257 +1,570 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="en"
|
|
2
|
+
<html lang="en">
|
|
3
|
+
{{> script/showmessage }}
|
|
3
4
|
|
|
4
5
|
<head>
|
|
5
|
-
<
|
|
6
|
-
<
|
|
6
|
+
<meta charset="UTF-8">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
8
|
<meta name="description"
|
|
8
9
|
content="Log in to portal.mbktechstudio.com to access your resources and manage projects securely.">
|
|
9
10
|
<meta name="keywords" content="MBK Tech Studio, Web-Portal, Web, Portal, Admin-Panel, Admin, login">
|
|
10
|
-
<meta property="og:title" content="
|
|
11
|
+
<meta property="og:title" content="Login | MBK Tech Studio" />
|
|
11
12
|
<meta property="og:image" content="https://www.mbktechstudio.com/Assets/Images/Icon/logo.png" />
|
|
12
13
|
<meta property="og:url" content="https://portal.mbktechstudio.com/login">
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
<title>Login | MBK Tech Studio Portal</title>
|
|
15
|
+
<link rel="icon" type="image/x-icon" href="https://mbktechstudio.com/Assets/Images/Icon/dgicon.svg">
|
|
16
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
|
17
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
18
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
19
|
+
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
|
20
|
+
rel="stylesheet">
|
|
18
21
|
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
|
19
22
|
<style>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
:root {
|
|
24
|
+
--primary: #4361ee;
|
|
25
|
+
--primary-dark: #3a0ca3;
|
|
26
|
+
--primary-light: rgba(67, 97, 238, 0.1);
|
|
27
|
+
--secondary: #f72585;
|
|
28
|
+
--secondary-light: rgba(247, 37, 133, 0.1);
|
|
29
|
+
--dark: #121212;
|
|
30
|
+
--dark-light: #1e1e1e;
|
|
31
|
+
--darker: #0a0a0a;
|
|
32
|
+
--light: #f8f9fa;
|
|
33
|
+
--lighter: #ffffff;
|
|
34
|
+
--gray: #cccccc;
|
|
35
|
+
--gray-dark: #888888;
|
|
36
|
+
--success: #4cc9f0;
|
|
37
|
+
--warning: #f8961e;
|
|
38
|
+
--danger: #ef233c;
|
|
39
|
+
--gradient: linear-gradient(135deg, var(--primary), var(--secondary));
|
|
40
|
+
--glass: rgba(30, 30, 30, 0.5);
|
|
41
|
+
--glass-border: rgba(255, 255, 255, 0.1);
|
|
42
|
+
--transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.1);
|
|
43
|
+
--shadow-sm: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
44
|
+
--shadow-md: 0 8px 30px rgba(0, 0, 0, 0.2);
|
|
45
|
+
--shadow-lg: 0 15px 40px rgba(0, 0, 0, 0.3);
|
|
46
|
+
--radius-sm: 8px;
|
|
47
|
+
--radius-md: 12px;
|
|
48
|
+
--radius-lg: 16px;
|
|
49
|
+
--radius-xl: 24px;
|
|
32
50
|
}
|
|
33
51
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
* {
|
|
53
|
+
margin: 0;
|
|
54
|
+
padding: 0;
|
|
55
|
+
box-sizing: border-box;
|
|
56
|
+
font-family: 'Poppins', sans-serif;
|
|
38
57
|
}
|
|
39
58
|
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
body {
|
|
60
|
+
background: var(--dark);
|
|
61
|
+
color: var(--light);
|
|
62
|
+
line-height: 1.6;
|
|
63
|
+
overflow-x: hidden;
|
|
64
|
+
min-height: 100vh;
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-direction: column;
|
|
42
67
|
}
|
|
43
68
|
|
|
44
|
-
|
|
45
|
-
|
|
69
|
+
/* Header - Consistent with index */
|
|
70
|
+
header {
|
|
71
|
+
position: fixed;
|
|
72
|
+
top: 0;
|
|
73
|
+
left: 0;
|
|
74
|
+
width: 100%;
|
|
75
|
+
z-index: 1000;
|
|
76
|
+
transition: var(--transition);
|
|
77
|
+
background: linear-gradient(to bottom, rgba(10, 10, 10, 0.9), rgba(10, 10, 10, 0.7));
|
|
78
|
+
backdrop-filter: blur(10px);
|
|
79
|
+
border-bottom: 1px solid var(--glass-border);
|
|
46
80
|
}
|
|
47
81
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
82
|
+
nav {
|
|
83
|
+
padding: 15px 5%;
|
|
84
|
+
max-width: 1400px;
|
|
85
|
+
margin: 0 auto;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.navbar {
|
|
89
|
+
display: flex;
|
|
90
|
+
justify-content: space-between;
|
|
91
|
+
align-items: center;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.logo {
|
|
95
|
+
display: flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
gap: 10px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.logo img {
|
|
101
|
+
height: 30px;
|
|
102
|
+
width: auto;
|
|
103
|
+
transition: var(--transition);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.logo:hover img {
|
|
107
|
+
transform: rotate(15deg);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.logo-text {
|
|
111
|
+
font-size: 1.8rem;
|
|
112
|
+
font-weight: 700;
|
|
113
|
+
background: var(--gradient);
|
|
114
|
+
-webkit-background-clip: text;
|
|
115
|
+
background-clip: text;
|
|
116
|
+
color: transparent;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Login Container */
|
|
120
|
+
.login-container {
|
|
121
|
+
flex: 1;
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
justify-content: center;
|
|
125
|
+
padding: 120px 5% 80px;
|
|
126
|
+
position: relative;
|
|
127
|
+
overflow: hidden;
|
|
128
|
+
background: radial-gradient(circle at 70% 20%, rgba(67, 97, 238, 0.15), transparent 60%);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.login-box {
|
|
132
|
+
background: var(--dark-light);
|
|
133
|
+
border-radius: var(--radius-xl);
|
|
134
|
+
padding: 3rem;
|
|
135
|
+
width: 100%;
|
|
136
|
+
max-width: 500px;
|
|
137
|
+
box-shadow: var(--shadow-lg);
|
|
138
|
+
border: 1px solid var(--glass-border);
|
|
139
|
+
position: relative;
|
|
140
|
+
z-index: 2;
|
|
141
|
+
transition: var(--transition);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.login-box:hover {
|
|
145
|
+
box-shadow: var(--shadow-lg);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.login-title {
|
|
149
|
+
text-align: center;
|
|
150
|
+
margin-bottom: 2rem;
|
|
151
|
+
font-size: 2rem;
|
|
152
|
+
position: relative;
|
|
153
|
+
color: var(--lighter);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.login-title::after {
|
|
157
|
+
content: '';
|
|
51
158
|
position: absolute;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
159
|
+
bottom: -10px;
|
|
160
|
+
left: 50%;
|
|
161
|
+
transform: translateX(-50%);
|
|
162
|
+
width: 80px;
|
|
163
|
+
height: 4px;
|
|
164
|
+
background: var(--gradient);
|
|
165
|
+
border-radius: 2px;
|
|
55
166
|
}
|
|
56
167
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
168
|
+
/* Form Elements */
|
|
169
|
+
.form-group {
|
|
170
|
+
position: relative;
|
|
171
|
+
margin-bottom: 2rem;
|
|
60
172
|
}
|
|
61
173
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
174
|
+
.form-input {
|
|
175
|
+
width: 100%;
|
|
176
|
+
padding: 15px 20px;
|
|
177
|
+
background: var(--darker);
|
|
178
|
+
border: 2px solid var(--glass-border);
|
|
179
|
+
border-radius: var(--radius-sm);
|
|
180
|
+
color: var(--light);
|
|
181
|
+
font-size: 1rem;
|
|
182
|
+
transition: var(--transition);
|
|
66
183
|
}
|
|
67
184
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
185
|
+
.form-input:focus {
|
|
186
|
+
outline: none;
|
|
187
|
+
border-color: var(--primary);
|
|
188
|
+
box-shadow: 0 0 0 3px var(--primary-light);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.form-label {
|
|
192
|
+
position: absolute;
|
|
193
|
+
top: 15px;
|
|
194
|
+
left: 20px;
|
|
195
|
+
color: var(--gray);
|
|
196
|
+
transition: var(--transition);
|
|
197
|
+
pointer-events: none;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.form-input:focus+.form-label,
|
|
201
|
+
.form-input:not(:placeholder-shown)+.form-label {
|
|
202
|
+
top: -10px;
|
|
203
|
+
left: 15px;
|
|
204
|
+
font-size: 0.8rem;
|
|
205
|
+
background: var(--dark-light);
|
|
206
|
+
padding: 0 5px;
|
|
207
|
+
color: var(--primary);
|
|
72
208
|
}
|
|
73
209
|
|
|
210
|
+
.input-icon {
|
|
211
|
+
position: absolute;
|
|
212
|
+
right: 20px;
|
|
213
|
+
top: 50%;
|
|
214
|
+
transform: translateY(-50%);
|
|
215
|
+
color: var(--gray);
|
|
216
|
+
cursor: pointer;
|
|
217
|
+
transition: var(--transition);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.input-icon:hover {
|
|
221
|
+
color: var(--primary);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.btn-login {
|
|
225
|
+
width: 100%;
|
|
226
|
+
padding: 15px;
|
|
227
|
+
border-radius: var(--radius-sm);
|
|
228
|
+
background: var(--primary);
|
|
229
|
+
color: white;
|
|
230
|
+
font-weight: 600;
|
|
231
|
+
font-size: 1rem;
|
|
232
|
+
border: none;
|
|
233
|
+
cursor: pointer;
|
|
234
|
+
transition: var(--transition);
|
|
235
|
+
box-shadow: var(--shadow-sm);
|
|
236
|
+
margin-top: 1rem;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.btn-login:hover {
|
|
240
|
+
background: var(--primary-dark);
|
|
241
|
+
transform: translateY(-3px);
|
|
242
|
+
box-shadow: var(--shadow-md);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.btn-login:disabled {
|
|
246
|
+
background: var(--gray-dark);
|
|
247
|
+
cursor: not-allowed;
|
|
248
|
+
transform: none;
|
|
249
|
+
box-shadow: none;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* Additional Links */
|
|
253
|
+
.login-links {
|
|
254
|
+
display: flex;
|
|
255
|
+
justify-content: space-between;
|
|
256
|
+
margin-top: 1.5rem;
|
|
257
|
+
font-size: 0.9rem;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.login-link {
|
|
261
|
+
color: var(--gray);
|
|
262
|
+
transition: var(--transition);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.login-link:hover {
|
|
266
|
+
color: var(--primary);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* Terms Info */
|
|
270
|
+
.terms-info {
|
|
271
|
+
margin-top: 2rem;
|
|
272
|
+
font-size: 0.8rem;
|
|
273
|
+
color: var(--gray);
|
|
274
|
+
text-align: center;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.terms-link {
|
|
278
|
+
color: var(--primary);
|
|
279
|
+
font-weight: 500;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* Recaptcha */
|
|
74
283
|
.recaptcha-container {
|
|
284
|
+
margin: 2rem 0;
|
|
75
285
|
display: flex;
|
|
76
286
|
justify-content: center;
|
|
77
|
-
|
|
78
|
-
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* 2FA Token Container */
|
|
290
|
+
.token-container {
|
|
291
|
+
animation: fadeInUp 0.4s ease-out;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.token-container.disable {
|
|
295
|
+
display: none;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.token-container.enable {
|
|
299
|
+
display: block;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* Floating Elements */
|
|
303
|
+
.ai-element {
|
|
304
|
+
position: absolute;
|
|
305
|
+
opacity: 0.1;
|
|
306
|
+
z-index: 1;
|
|
307
|
+
animation: float 6s ease-in-out infinite;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.ai-element:nth-child(1) {
|
|
311
|
+
top: 20%;
|
|
312
|
+
left: 10%;
|
|
313
|
+
font-size: 5rem;
|
|
314
|
+
animation-delay: 0s;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.ai-element:nth-child(2) {
|
|
318
|
+
top: 60%;
|
|
319
|
+
left: 80%;
|
|
320
|
+
font-size: 4rem;
|
|
321
|
+
animation-delay: 1s;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.ai-element:nth-child(3) {
|
|
325
|
+
top: 30%;
|
|
326
|
+
left: 70%;
|
|
327
|
+
font-size: 3rem;
|
|
328
|
+
animation-delay: 2s;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.ai-element:nth-child(4) {
|
|
332
|
+
top: 80%;
|
|
333
|
+
left: 20%;
|
|
334
|
+
font-size: 6rem;
|
|
335
|
+
animation-delay: 3s;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
@keyframes float {
|
|
339
|
+
|
|
340
|
+
0%,
|
|
341
|
+
100% {
|
|
342
|
+
transform: translateY(0) rotate(0deg);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
50% {
|
|
346
|
+
transform: translateY(-20px) rotate(5deg);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
@keyframes fadeInUp {
|
|
351
|
+
from {
|
|
352
|
+
opacity: 0;
|
|
353
|
+
transform: translateY(20px);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
to {
|
|
357
|
+
opacity: 1;
|
|
358
|
+
transform: translateY(0);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* Responsive Styles */
|
|
363
|
+
@media (max-width: 768px) {
|
|
364
|
+
.login-box {
|
|
365
|
+
padding: 2rem;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.login-title {
|
|
369
|
+
font-size: 1.8rem;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
@media (max-width: 576px) {
|
|
374
|
+
.login-box {
|
|
375
|
+
padding: 1.5rem;
|
|
376
|
+
border-radius: var(--radius-lg);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.login-links {
|
|
380
|
+
flex-direction: column;
|
|
381
|
+
gap: 0.5rem;
|
|
382
|
+
align-items: center;
|
|
383
|
+
}
|
|
79
384
|
}
|
|
80
385
|
</style>
|
|
81
386
|
</head>
|
|
82
|
-
{{> header1 }}
|
|
83
387
|
|
|
84
388
|
<body>
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
<div class="
|
|
88
|
-
<
|
|
89
|
-
<
|
|
389
|
+
<header>
|
|
390
|
+
<nav>
|
|
391
|
+
<div class="navbar">
|
|
392
|
+
<a class="logo">
|
|
393
|
+
<img src="https://mbktechstudio.com/Assets/Images/Icon/dgicon.svg" alt="MBK Tech Studio Logo">
|
|
394
|
+
<span class="logo-text">MBK Authe</span>
|
|
395
|
+
</a>
|
|
396
|
+
</div>
|
|
397
|
+
</nav>
|
|
398
|
+
</header>
|
|
399
|
+
|
|
400
|
+
<section class="login-container">
|
|
401
|
+
<!-- Floating AI elements -->
|
|
402
|
+
<i class="fas fa-robot ai-element"></i>
|
|
403
|
+
<i class="fas fa-microchip ai-element"></i>
|
|
404
|
+
<i class="fas fa-user-astronaut ai-element"></i>
|
|
405
|
+
<i class="fas fa-satellite-dish ai-element"></i>
|
|
406
|
+
<i class="fas fa-cloud ai-element"></i>
|
|
407
|
+
<i class="fas fa-shield-alt ai-element"></i>
|
|
408
|
+
|
|
409
|
+
<div class="login-box">
|
|
410
|
+
<h1 class="login-title">Login</h1>
|
|
411
|
+
|
|
412
|
+
<form id="loginForm" method="POST">
|
|
413
|
+
<div class="form-group">
|
|
414
|
+
<input id="loginUsername" class="form-input" type="text" name="username" placeholder=" " required
|
|
415
|
+
pattern="^[a-z0-9.]+$"
|
|
416
|
+
title="Username must contain lowercase letters, numbers, and periods only, no spaces, no special characters."
|
|
417
|
+
oninput="this.value = this.value.toLowerCase().replace(/[^a-z0-9.]/g, '')" />
|
|
418
|
+
<label class="form-label">Username</label>
|
|
419
|
+
<i class="fas fa-info-circle input-icon" onclick="usernameinfo()"></i>
|
|
90
420
|
</div>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<label>Password</label>
|
|
107
|
-
<span class="password-toggle-icon">
|
|
108
|
-
<i class="fa fa-eye"></i>
|
|
109
|
-
</span>
|
|
110
|
-
</div>
|
|
111
|
-
<div class="user-box" id="tokenCon" style="display: none;">
|
|
112
|
-
<input id="token" type="text" class="no-spinner" name="token" pattern="\d{6}"
|
|
113
|
-
title="Token must be exactly 6 digits" maxlength="6" minlength="6" />
|
|
114
|
-
<label>Token</label>
|
|
115
|
-
<span class="info-icon" onclick="tokeninfo()">
|
|
116
|
-
<i class="fa fa-info-circle"></i>
|
|
117
|
-
</span>
|
|
118
|
-
</div>
|
|
119
|
-
<div class="wrap">
|
|
120
|
-
<div class="button">
|
|
121
|
-
<button style="font-size: 17px;" type="submit">Login</button>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
</form>
|
|
125
|
-
{{#if userLoggedIn }}
|
|
126
|
-
{{> alreadyloggedin UserName=UserName }}
|
|
127
|
-
{{/if }}
|
|
128
|
-
<p class="info maincssp">
|
|
129
|
-
<span class="">
|
|
130
|
-
<i class="fa fa-info-circle"></i>
|
|
131
|
-
</span>By Logging In, You Are Automatically Agreeing To Our
|
|
132
|
-
<a class="links" href="/info/Terms&Conditions">Use Of Terms & Conditions
|
|
133
|
-
</a>
|
|
134
|
-
</p>
|
|
421
|
+
|
|
422
|
+
<div class="form-group">
|
|
423
|
+
<input id="loginPassword" class="form-input" type="password" name="Password" placeholder=" "
|
|
424
|
+
required />
|
|
425
|
+
<label class="form-label">Password</label>
|
|
426
|
+
<i class="fas fa-eye input-icon" id="togglePassword"></i>
|
|
427
|
+
</div>
|
|
428
|
+
|
|
429
|
+
<div class="form-group token-container disable" id="tokenCon">
|
|
430
|
+
<input id="token" class="form-input" type="text" name="token" placeholder=" " pattern="\d{6}"
|
|
431
|
+
title="Token must be exactly 6 digits" maxlength="6" minlength="6" />
|
|
432
|
+
<label class="form-label">2FA Token</label>
|
|
433
|
+
<i class="fas fa-info-circle input-icon" onclick="tokeninfo()"></i>
|
|
434
|
+
</div>
|
|
435
|
+
|
|
135
436
|
<div class="recaptcha-container">
|
|
136
437
|
<div class="g-recaptcha" data-theme="dark" data-sitekey="6LfhaPgqAAAAAPgOw7r3rNOHKKfh5d7K3MMJeUHo">
|
|
137
438
|
</div>
|
|
138
439
|
</div>
|
|
139
|
-
|
|
440
|
+
|
|
441
|
+
<button type="submit" class="btn-login" id="loginButton">
|
|
442
|
+
<span id="loginButtonText">Login</span>
|
|
443
|
+
</button>
|
|
444
|
+
|
|
445
|
+
<div class="login-links">
|
|
446
|
+
<a onclick="fpass()" class="login-link">Forgot Password?</a>
|
|
447
|
+
<a href="https://www.mbktechstudio.com/Support" target="_blank" class="login-link">Need Help?</a>
|
|
448
|
+
</div>
|
|
449
|
+
|
|
450
|
+
<p class="terms-info">
|
|
451
|
+
By logging in, you agree to our
|
|
452
|
+
<a href="/info/Terms&Conditions" class="terms-link">Terms & Conditions</a>
|
|
453
|
+
and
|
|
454
|
+
<a href="/info/PrivacyPolicy" class="terms-link">Privacy Policy</a>.
|
|
455
|
+
</p>
|
|
456
|
+
</form>
|
|
140
457
|
</div>
|
|
141
458
|
</section>
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
"
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
459
|
+
|
|
460
|
+
<script>
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
// Toggle password visibility
|
|
464
|
+
const togglePassword = document.getElementById('togglePassword');
|
|
465
|
+
const passwordInput = document.getElementById('loginPassword');
|
|
466
|
+
|
|
467
|
+
togglePassword.addEventListener('click', function () {
|
|
468
|
+
const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
|
|
469
|
+
passwordInput.setAttribute('type', type);
|
|
470
|
+
togglePassword.classList.toggle('fa-eye');
|
|
471
|
+
togglePassword.classList.toggle('fa-eye-slash');
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
function fpass() {
|
|
475
|
+
showMessage(`If you have forgotten your password, please contact support at <a href="https://www.mbktechstudio.com/Support" target="_blank">https://www.mbktechstudio.com/Support</a> to reset it.`, `Forgot Password`);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Info dialogs
|
|
479
|
+
function usernameinfo() {
|
|
480
|
+
showMessage(`If you are a member of the MBK Tech Studio team, your username is the first part of your email address (e.g., for abc.xyz@mbktechstudio.com, your username is abc.xyz). If you are a guest or have forgotten your username and password, please contact support.`, `What is my username?`);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function tokeninfo() {
|
|
484
|
+
showMessage(`The 2FA token is a 6-digit code generated by your authenticator app (such as Google Authenticator, Microsoft Authenticator, or Authy). Enter the code shown in your app to complete login. If you have not set up 2FA or are having trouble, please contact support.`, `What is the 2FA token?`);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Form submission
|
|
488
|
+
document.getElementById('loginForm').addEventListener('submit', function (event) {
|
|
489
|
+
event.preventDefault();
|
|
490
|
+
|
|
491
|
+
const username = document.getElementById('loginUsername').value.trim();
|
|
492
|
+
const password = document.getElementById('loginPassword').value.trim();
|
|
493
|
+
const token = document.getElementById('token') ? document.getElementById('token').value.trim() : '';
|
|
494
|
+
const recaptchaResponse = grecaptcha.getResponse();
|
|
495
|
+
const loginButton = document.getElementById('loginButton');
|
|
496
|
+
const loginButtonText = document.getElementById('loginButtonText');
|
|
497
|
+
|
|
498
|
+
if (!username || !password) {
|
|
499
|
+
showMessage('Username and password are required', 'Login Error');
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
loginButton.disabled = true;
|
|
504
|
+
loginButtonText.textContent = 'Authenticating...';
|
|
505
|
+
|
|
506
|
+
fetch('/mbkauthe/api/login', {
|
|
507
|
+
method: 'POST',
|
|
508
|
+
headers: {
|
|
509
|
+
'Content-Type': 'application/json'
|
|
510
|
+
},
|
|
511
|
+
body: JSON.stringify({
|
|
512
|
+
username,
|
|
513
|
+
password,
|
|
514
|
+
token,
|
|
515
|
+
recaptcha: recaptchaResponse
|
|
516
|
+
})
|
|
517
|
+
})
|
|
518
|
+
.then(response => response.json())
|
|
519
|
+
.then(data => {
|
|
520
|
+
if (data.success) {
|
|
521
|
+
loginButtonText.textContent = 'Success! Redirecting...';
|
|
522
|
+
sessionStorage.setItem('sessionId', data.sessionId);
|
|
523
|
+
|
|
524
|
+
// Redirect to the appropriate page
|
|
525
|
+
const redirectUrl = new URLSearchParams(window.location.search).get('redirect');
|
|
526
|
+
window.location.href = redirectUrl ? decodeURIComponent(redirectUrl) : '{{customURL}}';
|
|
191
527
|
} else {
|
|
192
|
-
|
|
528
|
+
// Handle errors
|
|
529
|
+
grecaptcha.reset();
|
|
530
|
+
loginButton.disabled = false;
|
|
531
|
+
loginButtonText.textContent = 'Login';
|
|
532
|
+
|
|
533
|
+
if (data.message === "Please Enter 2FA code") {
|
|
534
|
+
console.log('2FA required');
|
|
535
|
+
document.getElementById('tokenCon').classList.remove('disable');
|
|
536
|
+
document.getElementById('tokenCon').classList.add('enable');
|
|
537
|
+
document.getElementById('tokenCon').style.animation = 'fadeInUp 0.4s ease-out';
|
|
538
|
+
showMessage('Please enter your 2FA token', '2FA Required');
|
|
539
|
+
} else {
|
|
540
|
+
showMessage(data.message || 'Login failed. Please try again.', 'Login Error');
|
|
541
|
+
}
|
|
193
542
|
}
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
.then(data => {
|
|
197
|
-
if (data.success) {
|
|
198
|
-
sessionStorage.setItem('sessionId', data.sessionId);
|
|
199
|
-
clearAllCookies();
|
|
200
|
-
const redirectUrl = new URLSearchParams(window.location.search).get('redirect');
|
|
201
|
-
loginButton.innerText = "Redirecting.....";
|
|
202
|
-
window.location.href = redirectUrl ? decodeURIComponent(redirectUrl) : '/chatbot';
|
|
203
|
-
} else {
|
|
543
|
+
})
|
|
544
|
+
.catch(error => {
|
|
204
545
|
grecaptcha.reset();
|
|
205
|
-
showMessage(data.message, "Error");
|
|
206
|
-
document.getElementById('loginMessage').innerText = data.message;
|
|
207
|
-
if (data.code === 401 && data.message === "Invalid 2FA code") {
|
|
208
|
-
console.log("data.message");
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
})
|
|
212
|
-
.catch(error => {
|
|
213
|
-
grecaptcha.reset();
|
|
214
|
-
if (error.message === "Please Enter 2FA code") {
|
|
215
|
-
showMessage("Please enter the 2FA code", "Error");
|
|
216
|
-
const tokenCon = document.getElementById('tokenCon');
|
|
217
|
-
const tokenInput = document.getElementById('token');
|
|
218
|
-
tokenCon.style.display = "block";
|
|
219
|
-
tokenInput.setAttribute('required', '');
|
|
220
|
-
} else {
|
|
221
|
-
console.error('Error:', error);
|
|
222
|
-
showMessage(error.message, "Error");
|
|
223
546
|
loginButton.disabled = false;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
toggleIcon.innerHTML = '<i class="fa fa-eye"></i>'; // Change icon to open eye
|
|
547
|
+
loginButtonText.textContent = 'Login';
|
|
548
|
+
console.error('Error:', error);
|
|
549
|
+
showMessage('An error occurred. Please try again.', 'Login Error');
|
|
550
|
+
});
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
// Check for URL parameters
|
|
554
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
555
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
556
|
+
const usernameFromUrl = urlParams.get('username');
|
|
557
|
+
const passwordFromUrl = urlParams.get('password');
|
|
558
|
+
|
|
559
|
+
if (usernameFromUrl) {
|
|
560
|
+
document.getElementById('loginUsername').value = usernameFromUrl;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (passwordFromUrl) {
|
|
564
|
+
document.getElementById('loginPassword').value = passwordFromUrl;
|
|
243
565
|
}
|
|
244
566
|
});
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const usernameFromUrl = urlParams.get('username');
|
|
248
|
-
const passwordFromUrl = urlParams.get('password');
|
|
249
|
-
if (usernameFromUrl && !document.getElementById('loginUsername').value) {
|
|
250
|
-
document.getElementById('loginUsername').value = usernameFromUrl;
|
|
251
|
-
}
|
|
252
|
-
if (passwordFromUrl && !document.getElementById('loginPassword').value) {
|
|
253
|
-
document.getElementById('loginPassword').value = passwordFromUrl;
|
|
254
|
-
}
|
|
255
|
-
</script>
|
|
567
|
+
</script>
|
|
568
|
+
</body>
|
|
256
569
|
|
|
257
570
|
</html>
|