shogun-core 5.2.1 โ 5.3.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.
- package/README.md +145 -1143
- package/dist/browser/shogun-core.js +304 -29
- package/dist/browser/shogun-core.js.map +1 -1
- package/dist/examples/auth-test.js +81 -24
- package/dist/examples/crypto-identity-example.js +17 -7
- package/dist/gundb/db.js +297 -23
- package/dist/managers/CryptoIdentityManager.js +7 -6
- package/dist/types/gundb/db.d.ts +28 -2
- package/dist/types/managers/CryptoIdentityManager.d.ts +2 -1
- package/package.json +1 -57
|
@@ -15,12 +15,17 @@ async function authTest() {
|
|
|
15
15
|
// Use AutoQuickStart for easy setup with multiple peers for reliability
|
|
16
16
|
const quickStart = new api_1.AutoQuickStart({
|
|
17
17
|
peers: [
|
|
18
|
+
"https://lindanode.scobrudot.dev/gun",
|
|
19
|
+
"https://shogunnode.scobrudot.dev/gun",
|
|
18
20
|
"https://peer.wallie.io/gun",
|
|
19
21
|
"https://gun-manhattan.herokuapp.com/gun",
|
|
20
22
|
"https://gun.defucc.me/gun",
|
|
23
|
+
"http://localhost:8765/gun",
|
|
21
24
|
],
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
wire: true,
|
|
26
|
+
axe: true,
|
|
27
|
+
radisk: false,
|
|
28
|
+
localStorage: false,
|
|
24
29
|
enableGunDebug: true,
|
|
25
30
|
enableConnectionMonitoring: true,
|
|
26
31
|
});
|
|
@@ -34,47 +39,98 @@ async function authTest() {
|
|
|
34
39
|
}
|
|
35
40
|
const api = quickStart.api;
|
|
36
41
|
const db = api.database;
|
|
42
|
+
console.log("peers:", db.gun._.opt.peers);
|
|
37
43
|
console.log("- Database instance:", db ? "Available" : "Not available");
|
|
38
44
|
console.log("- Current user:", db.getCurrentUser()?.alias || "None");
|
|
39
45
|
console.log("- Is logged in:", db.isLoggedIn());
|
|
40
46
|
console.log("");
|
|
41
47
|
// === TEST 1: BASIC SIGNUP AND LOGIN ===
|
|
42
48
|
console.log("๐งช === TEST 1: BASIC SIGNUP AND LOGIN ===\n");
|
|
43
|
-
const testUsername =
|
|
44
|
-
const testPassword = "
|
|
49
|
+
const testUsername = "scobru";
|
|
50
|
+
const testPassword = "francos88";
|
|
51
|
+
// Clean up any existing session
|
|
52
|
+
console.log("๐งน Cleaning up any existing session...");
|
|
53
|
+
db.logout();
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1 second
|
|
55
|
+
// Force reset auth state for problematic users
|
|
56
|
+
if (testUsername === "scobru") {
|
|
57
|
+
console.log("๐ง Performing aggressive cleanup for problematic user...");
|
|
58
|
+
db.aggressiveAuthCleanup();
|
|
59
|
+
await new Promise((resolve) => setTimeout(resolve, 3000)); // Wait 3 seconds
|
|
60
|
+
console.log("โ Aggressive cleanup completed");
|
|
61
|
+
}
|
|
62
|
+
console.log("โ Session cleanup completed\n");
|
|
45
63
|
console.log(`Testing with username: ${testUsername}`);
|
|
46
64
|
console.log(`Password: ${testPassword}\n`);
|
|
47
65
|
// Test signup
|
|
48
66
|
console.log("๐ Attempting signup...");
|
|
49
67
|
const signupStartTime = Date.now();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
// Check if user already exists before signup
|
|
69
|
+
console.log(`๐ Pre-signup check for user: ${testUsername}`);
|
|
70
|
+
const preSignupCheck = await new Promise((resolve) => {
|
|
71
|
+
const timeout = setTimeout(() => {
|
|
72
|
+
console.log("โฐ Pre-signup check timeout");
|
|
73
|
+
resolve(false);
|
|
74
|
+
}, 3000);
|
|
75
|
+
db.gun.get(`~@${testUsername}`).once((data) => {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
console.log("๐ Pre-signup data:", data ? "User exists" : "User not found");
|
|
78
|
+
if (data) {
|
|
79
|
+
console.log("๐ User pub:", data.pub ? `${data.pub.substring(0, 20)}...` : "None");
|
|
80
|
+
console.log("๐ User keys:", Object.keys(data));
|
|
81
|
+
}
|
|
82
|
+
resolve(!!data && !!data.pub);
|
|
62
83
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
84
|
+
});
|
|
85
|
+
if (preSignupCheck) {
|
|
86
|
+
console.log("โ ๏ธ User already exists, skipping signup and going directly to login");
|
|
67
87
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
else {
|
|
89
|
+
try {
|
|
90
|
+
// Add timeout for signup
|
|
91
|
+
const signupPromise = db.signUp(testUsername, testPassword);
|
|
92
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Signup timeout after 30 seconds")), 30000));
|
|
93
|
+
const signupResult = (await Promise.race([
|
|
94
|
+
signupPromise,
|
|
95
|
+
timeoutPromise,
|
|
96
|
+
]));
|
|
97
|
+
const signupDuration = Date.now() - signupStartTime;
|
|
98
|
+
console.log(`โ Signup completed in ${signupDuration}ms`);
|
|
99
|
+
console.log("Signup result:", {
|
|
100
|
+
success: signupResult.success,
|
|
101
|
+
userPub: signupResult.userPub
|
|
102
|
+
? `${signupResult.userPub.substring(0, 20)}...`
|
|
103
|
+
: "None",
|
|
104
|
+
username: signupResult.username,
|
|
105
|
+
isNewUser: signupResult.isNewUser,
|
|
106
|
+
error: signupResult.error || "None",
|
|
107
|
+
});
|
|
108
|
+
if (!signupResult.success) {
|
|
109
|
+
console.log("โน๏ธ Signup failed, user might already exist. Will try login...");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.log("โน๏ธ Signup threw exception, user might already exist. Will try login...");
|
|
114
|
+
console.log("Exception details:", error);
|
|
115
|
+
}
|
|
71
116
|
}
|
|
117
|
+
// Wait a moment before attempting login
|
|
118
|
+
console.log("โณ Waiting 2 seconds before login attempt...");
|
|
119
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
72
120
|
console.log("");
|
|
73
121
|
// Test login
|
|
74
122
|
console.log("๐ Attempting login...");
|
|
75
123
|
const loginStartTime = Date.now();
|
|
76
124
|
try {
|
|
77
|
-
|
|
125
|
+
// Skip user existence check and try direct login
|
|
126
|
+
console.log("๐ Attempting direct login (bypassing user existence check)...");
|
|
127
|
+
// Add timeout for login
|
|
128
|
+
const loginPromise = db.login(testUsername, testPassword);
|
|
129
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Login timeout after 30 seconds")), 30000));
|
|
130
|
+
const loginResult = (await Promise.race([
|
|
131
|
+
loginPromise,
|
|
132
|
+
timeoutPromise,
|
|
133
|
+
]));
|
|
78
134
|
const loginDuration = Date.now() - loginStartTime;
|
|
79
135
|
console.log(`โ Login completed in ${loginDuration}ms`);
|
|
80
136
|
console.log("Login result:", {
|
|
@@ -87,6 +143,7 @@ async function authTest() {
|
|
|
87
143
|
});
|
|
88
144
|
if (!loginResult.success) {
|
|
89
145
|
console.error("โ Login failed:", loginResult.error);
|
|
146
|
+
console.log("โน๏ธ If this is a new user, try running the test again after a few seconds");
|
|
90
147
|
return;
|
|
91
148
|
}
|
|
92
149
|
// Verify user state
|
|
@@ -12,15 +12,20 @@ async function cryptoIdentityExample() {
|
|
|
12
12
|
// 1. Inizializza ShogunCore
|
|
13
13
|
const core = new index_1.ShogunCore({
|
|
14
14
|
gunOptions: {
|
|
15
|
-
peers: [
|
|
16
|
-
|
|
15
|
+
peers: [
|
|
16
|
+
"https://peer.wallie.io/gun",
|
|
17
|
+
"https://shogunnode.scobrudot.dev/gun",
|
|
18
|
+
"https://shogunnode2.scobrudot.dev/gun",
|
|
19
|
+
"https://lindanode.scobrudot.dev/gun",
|
|
20
|
+
],
|
|
21
|
+
radisk: false,
|
|
17
22
|
localStorage: false,
|
|
18
23
|
},
|
|
19
24
|
});
|
|
20
25
|
console.log("โ
ShogunCore inizializzato");
|
|
21
26
|
// 2. Registra un nuovo utente (genera automaticamente SEA pair)
|
|
22
|
-
const username = `
|
|
23
|
-
const signupResult = await core.signUp(username, "
|
|
27
|
+
const username = `scobru`;
|
|
28
|
+
const signupResult = await core.signUp(username, "francos88");
|
|
24
29
|
if (!signupResult.success) {
|
|
25
30
|
console.error("โ Registrazione fallita:", signupResult.error);
|
|
26
31
|
return;
|
|
@@ -52,7 +57,7 @@ async function cryptoIdentityExample() {
|
|
|
52
57
|
}
|
|
53
58
|
// 5. Esempio di login con utente esistente
|
|
54
59
|
console.log("\n๐ Test login con utente esistente...");
|
|
55
|
-
const loginResult = await core.login(username, "
|
|
60
|
+
const loginResult = await core.login(username, "francos88");
|
|
56
61
|
if (loginResult.success) {
|
|
57
62
|
console.log("โ
Login riuscito");
|
|
58
63
|
// Le identitร crypto esistenti vengono recuperate automaticamente
|
|
@@ -82,8 +87,13 @@ async function multiAuthExample() {
|
|
|
82
87
|
console.log("\n๐ Esempio con diversi metodi di autenticazione");
|
|
83
88
|
const core = new index_1.ShogunCore({
|
|
84
89
|
gunOptions: {
|
|
85
|
-
peers: [
|
|
86
|
-
|
|
90
|
+
peers: [
|
|
91
|
+
"https://peer.wallie.io/gun",
|
|
92
|
+
"https://shogunnode.scobrudot.dev/gun",
|
|
93
|
+
"https://shogunnode2.scobrudot.dev/gun",
|
|
94
|
+
"https://lindanode.scobrudot.dev/gun",
|
|
95
|
+
],
|
|
96
|
+
radisk: false,
|
|
87
97
|
localStorage: false,
|
|
88
98
|
},
|
|
89
99
|
});
|
package/dist/gundb/db.js
CHANGED
|
@@ -129,7 +129,7 @@ class DataBase {
|
|
|
129
129
|
this.node = this.gun.get(appScope);
|
|
130
130
|
console.log("[DB] App scope node initialized");
|
|
131
131
|
// Initialize CryptoIdentityManager
|
|
132
|
-
this._cryptoIdentityManager = new CryptoIdentityManager_1.CryptoIdentityManager(this.core);
|
|
132
|
+
this._cryptoIdentityManager = new CryptoIdentityManager_1.CryptoIdentityManager(this.core, this);
|
|
133
133
|
console.log("[DB] CryptoIdentityManager initialized");
|
|
134
134
|
if (sessionResult.success) {
|
|
135
135
|
console.log("[DB] Session automatically restored");
|
|
@@ -577,6 +577,10 @@ class DataBase {
|
|
|
577
577
|
// Log out user
|
|
578
578
|
try {
|
|
579
579
|
currentUser.leave();
|
|
580
|
+
// Force clear any pending authentication
|
|
581
|
+
if (currentUser._ && currentUser._.sea) {
|
|
582
|
+
currentUser._.sea = null;
|
|
583
|
+
}
|
|
580
584
|
}
|
|
581
585
|
catch (gunError) {
|
|
582
586
|
console.error("Error during Gun logout:", gunError);
|
|
@@ -715,6 +719,8 @@ class DataBase {
|
|
|
715
719
|
this.gun.user().create(normalizedUsername, password, (ack) => {
|
|
716
720
|
if (ack.err) {
|
|
717
721
|
console.error(`User creation error: ${ack.err}`);
|
|
722
|
+
// Reset auth state after failed creation to prevent blocking future operations
|
|
723
|
+
this.resetAuthState();
|
|
718
724
|
resolve({ success: false, error: ack.err });
|
|
719
725
|
}
|
|
720
726
|
else {
|
|
@@ -767,6 +773,8 @@ class DataBase {
|
|
|
767
773
|
this.gun.user().auth(pair, (ack) => {
|
|
768
774
|
if (ack.err) {
|
|
769
775
|
console.error(`Authentication after creation failed: ${ack.err}`);
|
|
776
|
+
// Reset auth state on error to prevent blocking future operations
|
|
777
|
+
this.resetAuthState();
|
|
770
778
|
resolve({ success: false, error: ack.err });
|
|
771
779
|
}
|
|
772
780
|
else {
|
|
@@ -792,6 +800,8 @@ class DataBase {
|
|
|
792
800
|
this.gun.user().auth(normalizedUsername, password, (ack) => {
|
|
793
801
|
if (ack.err) {
|
|
794
802
|
console.error(`Authentication after creation failed: ${ack.err}`);
|
|
803
|
+
// Reset auth state on error to prevent blocking future operations
|
|
804
|
+
this.resetAuthState();
|
|
795
805
|
resolve({ success: false, error: ack.err });
|
|
796
806
|
}
|
|
797
807
|
else {
|
|
@@ -822,13 +832,33 @@ class DataBase {
|
|
|
822
832
|
* @param pair Optional SEA pair for Web3 login
|
|
823
833
|
* @returns Promise resolving to signup result
|
|
824
834
|
*/
|
|
825
|
-
async signUp(username, password, pair) {
|
|
835
|
+
async signUp(username, password, pair, retryCount = 0, maxRetries = 3) {
|
|
826
836
|
try {
|
|
827
837
|
// Validate credentials with enhanced security
|
|
828
838
|
const validation = this.validateSignupCredentials(username, password, pair);
|
|
829
839
|
if (!validation.valid) {
|
|
830
840
|
return { success: false, error: validation.error };
|
|
831
841
|
}
|
|
842
|
+
// Check if authentication is in progress and retry if needed
|
|
843
|
+
if (this.isAuthInProgress()) {
|
|
844
|
+
if (retryCount < maxRetries) {
|
|
845
|
+
console.warn(`Authentication in progress during signup, retrying... (${retryCount + 1}/${maxRetries})`);
|
|
846
|
+
this.resetAuthState();
|
|
847
|
+
const baseDelay = 100 * Math.pow(2, retryCount);
|
|
848
|
+
const jitter = Math.random() * 100;
|
|
849
|
+
const delay = Math.min(baseDelay + jitter, 2000);
|
|
850
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
851
|
+
return this.signUp(username, password, pair, retryCount + 1, maxRetries);
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
console.error("Max retries exceeded for signup due to concurrent operations");
|
|
855
|
+
this.resetAuthState();
|
|
856
|
+
return {
|
|
857
|
+
success: false,
|
|
858
|
+
error: "Signup failed after multiple retries due to concurrent operations",
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
}
|
|
832
862
|
let createResult;
|
|
833
863
|
if (pair) {
|
|
834
864
|
// For Web3/plugin authentication, use pair-based creation
|
|
@@ -839,6 +869,8 @@ class DataBase {
|
|
|
839
869
|
createResult = await this.createNewUser(username, password);
|
|
840
870
|
}
|
|
841
871
|
if (!createResult.success) {
|
|
872
|
+
// Reset auth state after failed creation to prevent blocking future operations
|
|
873
|
+
this.resetAuthState();
|
|
842
874
|
return { success: false, error: createResult.error };
|
|
843
875
|
}
|
|
844
876
|
// Add a small delay to ensure user is properly registered
|
|
@@ -1453,33 +1485,134 @@ class DataBase {
|
|
|
1453
1485
|
}
|
|
1454
1486
|
}
|
|
1455
1487
|
/**
|
|
1456
|
-
*
|
|
1488
|
+
* Resets Gun.js authentication state to allow new auth operations
|
|
1489
|
+
*/
|
|
1490
|
+
resetAuthState() {
|
|
1491
|
+
try {
|
|
1492
|
+
const currentUser = this.gun.user();
|
|
1493
|
+
if (currentUser && currentUser._) {
|
|
1494
|
+
// Reset the authentication flag
|
|
1495
|
+
if (currentUser._.sea) {
|
|
1496
|
+
currentUser._.sea = null;
|
|
1497
|
+
}
|
|
1498
|
+
// Reset the ing flag that prevents concurrent operations
|
|
1499
|
+
if (currentUser._.ing) {
|
|
1500
|
+
currentUser._.ing = false;
|
|
1501
|
+
}
|
|
1502
|
+
// Force clear any pending authentication callbacks
|
|
1503
|
+
if (currentUser._.auth) {
|
|
1504
|
+
currentUser._.auth = null;
|
|
1505
|
+
}
|
|
1506
|
+
// Clear any pending operations
|
|
1507
|
+
if (currentUser._.act) {
|
|
1508
|
+
currentUser._.act = null;
|
|
1509
|
+
}
|
|
1510
|
+
// Clear any pending callbacks
|
|
1511
|
+
if (currentUser._.cb) {
|
|
1512
|
+
currentUser._.cb = null;
|
|
1513
|
+
}
|
|
1514
|
+
// Clear any pending retries
|
|
1515
|
+
if (currentUser._.retries) {
|
|
1516
|
+
currentUser._.retries = 0;
|
|
1517
|
+
}
|
|
1518
|
+
// Clear any pending timeouts
|
|
1519
|
+
if (currentUser._.timeout) {
|
|
1520
|
+
clearTimeout(currentUser._.timeout);
|
|
1521
|
+
currentUser._.timeout = null;
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
// Also try to call leave() to ensure clean state
|
|
1525
|
+
try {
|
|
1526
|
+
currentUser.leave();
|
|
1527
|
+
}
|
|
1528
|
+
catch (leaveError) {
|
|
1529
|
+
// Ignore leave errors, just trying to clean up
|
|
1530
|
+
}
|
|
1531
|
+
// Force clear the user reference to ensure clean state
|
|
1532
|
+
this.user = null;
|
|
1533
|
+
console.log("Auth state reset completed");
|
|
1534
|
+
}
|
|
1535
|
+
catch (error) {
|
|
1536
|
+
console.warn("Error resetting auth state:", error);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
/**
|
|
1540
|
+
* Performs authentication with Gun with retry mechanism
|
|
1457
1541
|
*/
|
|
1458
|
-
async performAuthentication(username, password, pair) {
|
|
1542
|
+
async performAuthentication(username, password, pair, retryCount = 0, maxRetries = 3) {
|
|
1459
1543
|
return new Promise((resolve) => {
|
|
1460
|
-
if
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1544
|
+
// Check if there's already an authentication operation in progress
|
|
1545
|
+
const currentUser = this.gun.user();
|
|
1546
|
+
if (currentUser && currentUser._ && currentUser._.ing) {
|
|
1547
|
+
if (retryCount < maxRetries) {
|
|
1548
|
+
console.warn(`Authentication already in progress, retrying... (${retryCount + 1}/${maxRetries})`);
|
|
1549
|
+
this.resetAuthState();
|
|
1550
|
+
// For the first retry, try to create a fresh authentication context
|
|
1551
|
+
if (retryCount === 0) {
|
|
1552
|
+
this.createFreshAuthContext();
|
|
1468
1553
|
}
|
|
1554
|
+
// Add exponential backoff delay with jitter
|
|
1555
|
+
const baseDelay = 200 * Math.pow(2, retryCount);
|
|
1556
|
+
const jitter = Math.random() * 200;
|
|
1557
|
+
const delay = Math.min(baseDelay + jitter, 3000);
|
|
1558
|
+
setTimeout(() => {
|
|
1559
|
+
this.performAuthentication(username, password, pair, retryCount + 1, maxRetries)
|
|
1560
|
+
.then(resolve)
|
|
1561
|
+
.catch((error) => resolve({ success: false, error: String(error) }));
|
|
1562
|
+
}, delay);
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
else {
|
|
1566
|
+
console.error("Max retries exceeded for authentication");
|
|
1567
|
+
this.resetAuthState();
|
|
1568
|
+
resolve({
|
|
1569
|
+
success: false,
|
|
1570
|
+
error: "Authentication failed after multiple retries",
|
|
1571
|
+
});
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
this.performAuthenticationInternal(username, password, pair, resolve);
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* Internal authentication method with timeout
|
|
1580
|
+
*/
|
|
1581
|
+
performAuthenticationInternal(username, password, pair, resolve) {
|
|
1582
|
+
let resolved = false;
|
|
1583
|
+
const timeout = 15000; // 15 second timeout for individual auth attempts
|
|
1584
|
+
const timeoutId = setTimeout(() => {
|
|
1585
|
+
if (!resolved) {
|
|
1586
|
+
resolved = true;
|
|
1587
|
+
console.error(`Authentication timeout for ${username} after ${timeout}ms`);
|
|
1588
|
+
this.resetAuthState();
|
|
1589
|
+
resolve({
|
|
1590
|
+
success: false,
|
|
1591
|
+
error: `Authentication timeout after ${timeout}ms`,
|
|
1469
1592
|
});
|
|
1470
1593
|
}
|
|
1594
|
+
}, timeout);
|
|
1595
|
+
const authCallback = (ack) => {
|
|
1596
|
+
if (resolved)
|
|
1597
|
+
return;
|
|
1598
|
+
resolved = true;
|
|
1599
|
+
clearTimeout(timeoutId);
|
|
1600
|
+
if (ack.err) {
|
|
1601
|
+
console.error(`Login error for ${username}: ${ack.err}`);
|
|
1602
|
+
// Reset auth state on error to prevent blocking future attempts
|
|
1603
|
+
this.resetAuthState();
|
|
1604
|
+
resolve({ success: false, error: ack.err });
|
|
1605
|
+
}
|
|
1471
1606
|
else {
|
|
1472
|
-
|
|
1473
|
-
if (ack.err) {
|
|
1474
|
-
console.error(`Login error for ${username}: ${ack.err}`);
|
|
1475
|
-
resolve({ success: false, error: ack.err });
|
|
1476
|
-
}
|
|
1477
|
-
else {
|
|
1478
|
-
resolve({ success: true, ack });
|
|
1479
|
-
}
|
|
1480
|
-
});
|
|
1607
|
+
resolve({ success: true, ack });
|
|
1481
1608
|
}
|
|
1482
|
-
}
|
|
1609
|
+
};
|
|
1610
|
+
if (pair) {
|
|
1611
|
+
this.gun.user().auth(pair, authCallback);
|
|
1612
|
+
}
|
|
1613
|
+
else {
|
|
1614
|
+
this.gun.user().auth(username, password, authCallback);
|
|
1615
|
+
}
|
|
1483
1616
|
}
|
|
1484
1617
|
/**
|
|
1485
1618
|
* Builds login result object
|
|
@@ -1513,9 +1646,28 @@ class DataBase {
|
|
|
1513
1646
|
try {
|
|
1514
1647
|
const loginResult = await this.performAuthentication(username, password, pair);
|
|
1515
1648
|
if (!loginResult.success) {
|
|
1649
|
+
// Provide more specific error messages based on the error type
|
|
1650
|
+
let errorMessage = `User '${username}' not found. Please check your username or register first.`;
|
|
1651
|
+
if (loginResult.error) {
|
|
1652
|
+
if (loginResult.error.includes("already being created or authenticated")) {
|
|
1653
|
+
errorMessage =
|
|
1654
|
+
"Authentication is already in progress. Please wait and try again.";
|
|
1655
|
+
}
|
|
1656
|
+
else if (loginResult.error.includes("Wrong user or password")) {
|
|
1657
|
+
errorMessage =
|
|
1658
|
+
"Invalid username or password. Please check your credentials.";
|
|
1659
|
+
}
|
|
1660
|
+
else if (loginResult.error.includes("User already created")) {
|
|
1661
|
+
errorMessage =
|
|
1662
|
+
"User already exists. Please try logging in instead.";
|
|
1663
|
+
}
|
|
1664
|
+
else {
|
|
1665
|
+
errorMessage = loginResult.error;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1516
1668
|
return {
|
|
1517
1669
|
success: false,
|
|
1518
|
-
error:
|
|
1670
|
+
error: errorMessage,
|
|
1519
1671
|
};
|
|
1520
1672
|
}
|
|
1521
1673
|
// Add a small delay to ensure user state is properly set
|
|
@@ -1934,6 +2086,128 @@ class DataBase {
|
|
|
1934
2086
|
isAuthenticated() {
|
|
1935
2087
|
return this.user?.is?.pub ? true : false;
|
|
1936
2088
|
}
|
|
2089
|
+
/**
|
|
2090
|
+
* Check if an authentication operation is currently in progress
|
|
2091
|
+
*/
|
|
2092
|
+
isAuthInProgress() {
|
|
2093
|
+
try {
|
|
2094
|
+
const currentUser = this.gun.user();
|
|
2095
|
+
return !!(currentUser && currentUser._ && currentUser._.ing);
|
|
2096
|
+
}
|
|
2097
|
+
catch (error) {
|
|
2098
|
+
console.warn("Error checking auth progress:", error);
|
|
2099
|
+
return false;
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* Force reset authentication state (useful for debugging or recovery)
|
|
2104
|
+
*/
|
|
2105
|
+
forceResetAuthState() {
|
|
2106
|
+
this.resetAuthState();
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* Aggressive cleanup for problematic users
|
|
2110
|
+
* This method performs a complete reset of all authentication state
|
|
2111
|
+
*/
|
|
2112
|
+
aggressiveAuthCleanup() {
|
|
2113
|
+
try {
|
|
2114
|
+
console.log("๐งน Performing aggressive auth cleanup...");
|
|
2115
|
+
// Reset all auth state
|
|
2116
|
+
this.resetAuthState();
|
|
2117
|
+
// Clear all Gun.js internal state
|
|
2118
|
+
const currentUser = this.gun.user();
|
|
2119
|
+
if (currentUser && currentUser._) {
|
|
2120
|
+
// Clear all possible internal flags
|
|
2121
|
+
const internalState = currentUser._;
|
|
2122
|
+
Object.keys(internalState).forEach((key) => {
|
|
2123
|
+
if (typeof internalState[key] === "boolean") {
|
|
2124
|
+
internalState[key] = false;
|
|
2125
|
+
}
|
|
2126
|
+
else if (typeof internalState[key] === "object" &&
|
|
2127
|
+
internalState[key] !== null) {
|
|
2128
|
+
if (key === "sea" ||
|
|
2129
|
+
key === "auth" ||
|
|
2130
|
+
key === "act" ||
|
|
2131
|
+
key === "cb") {
|
|
2132
|
+
internalState[key] = null;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
// Force logout
|
|
2138
|
+
try {
|
|
2139
|
+
currentUser.leave();
|
|
2140
|
+
}
|
|
2141
|
+
catch (error) {
|
|
2142
|
+
// Ignore errors
|
|
2143
|
+
}
|
|
2144
|
+
// Clear user reference
|
|
2145
|
+
this.user = null;
|
|
2146
|
+
// Clear all session storage
|
|
2147
|
+
if (typeof sessionStorage !== "undefined") {
|
|
2148
|
+
try {
|
|
2149
|
+
const keys = Object.keys(sessionStorage);
|
|
2150
|
+
keys.forEach((key) => {
|
|
2151
|
+
if (key.includes("gun") ||
|
|
2152
|
+
key.includes("user") ||
|
|
2153
|
+
key.includes("auth")) {
|
|
2154
|
+
sessionStorage.removeItem(key);
|
|
2155
|
+
}
|
|
2156
|
+
});
|
|
2157
|
+
}
|
|
2158
|
+
catch (error) {
|
|
2159
|
+
// Ignore errors
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
// Clear all local storage
|
|
2163
|
+
if (typeof localStorage !== "undefined") {
|
|
2164
|
+
try {
|
|
2165
|
+
const keys = Object.keys(localStorage);
|
|
2166
|
+
keys.forEach((key) => {
|
|
2167
|
+
if (key.includes("gun") ||
|
|
2168
|
+
key.includes("user") ||
|
|
2169
|
+
key.includes("auth")) {
|
|
2170
|
+
localStorage.removeItem(key);
|
|
2171
|
+
}
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2174
|
+
catch (error) {
|
|
2175
|
+
// Ignore errors
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
console.log("โ Aggressive auth cleanup completed");
|
|
2179
|
+
}
|
|
2180
|
+
catch (error) {
|
|
2181
|
+
console.error("Error during aggressive cleanup:", error);
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
/**
|
|
2185
|
+
* Creates a completely fresh authentication context
|
|
2186
|
+
* This is a more aggressive approach when normal reset doesn't work
|
|
2187
|
+
*/
|
|
2188
|
+
createFreshAuthContext() {
|
|
2189
|
+
try {
|
|
2190
|
+
// Reset all auth state
|
|
2191
|
+
this.resetAuthState();
|
|
2192
|
+
// Create a completely new user instance
|
|
2193
|
+
const freshUser = this.gun.user();
|
|
2194
|
+
this.user = freshUser;
|
|
2195
|
+
// Clear any cached authentication data
|
|
2196
|
+
if (typeof sessionStorage !== "undefined") {
|
|
2197
|
+
try {
|
|
2198
|
+
sessionStorage.removeItem("gunSessionData");
|
|
2199
|
+
sessionStorage.removeItem("gunUserData");
|
|
2200
|
+
}
|
|
2201
|
+
catch (error) {
|
|
2202
|
+
console.warn("Error clearing session storage:", error);
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
console.log("Fresh authentication context created");
|
|
2206
|
+
}
|
|
2207
|
+
catch (error) {
|
|
2208
|
+
console.error("Error creating fresh auth context:", error);
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
1937
2211
|
}
|
|
1938
2212
|
exports.DataBase = DataBase;
|
|
1939
2213
|
// Errors
|
|
@@ -21,8 +21,9 @@ const errorHandler_1 = require("../utils/errorHandler");
|
|
|
21
21
|
* Genera automaticamente tutte le identitร crypto disponibili dopo l'autenticazione SEA
|
|
22
22
|
*/
|
|
23
23
|
class CryptoIdentityManager {
|
|
24
|
-
constructor(core) {
|
|
24
|
+
constructor(core, db) {
|
|
25
25
|
this.core = core;
|
|
26
|
+
this.db = db;
|
|
26
27
|
this.pgpManager = new pgp_1.PGPManager();
|
|
27
28
|
this.mlsManager = new mls_1.MLSManager("default-user");
|
|
28
29
|
this.sframeManager = new sframe_1.SFrameManager();
|
|
@@ -144,7 +145,7 @@ class CryptoIdentityManager {
|
|
|
144
145
|
}
|
|
145
146
|
// Salva su GunDB nel percorso privato dell'utente
|
|
146
147
|
const saveResult = await new Promise((resolve, reject) => {
|
|
147
|
-
this.
|
|
148
|
+
this.db.gun
|
|
148
149
|
.user()
|
|
149
150
|
.get("crypto-identities")
|
|
150
151
|
.put(encryptedIdentities, (ack) => {
|
|
@@ -164,7 +165,7 @@ class CryptoIdentityManager {
|
|
|
164
165
|
name: "SHA-256",
|
|
165
166
|
});
|
|
166
167
|
await new Promise((resolve, reject) => {
|
|
167
|
-
this.
|
|
168
|
+
this.db.gun
|
|
168
169
|
.user()
|
|
169
170
|
.get("crypto-identities-hash")
|
|
170
171
|
.put(identitiesHash, (ack) => {
|
|
@@ -205,7 +206,7 @@ class CryptoIdentityManager {
|
|
|
205
206
|
console.log(`๐ [CryptoIdentityManager] Retrieving crypto identities for: ${username}`);
|
|
206
207
|
// Recupera le identitร criptate da GunDB
|
|
207
208
|
const encryptedIdentities = await new Promise((resolve, reject) => {
|
|
208
|
-
this.
|
|
209
|
+
this.db.gun
|
|
209
210
|
.user()
|
|
210
211
|
.get("crypto-identities")
|
|
211
212
|
.once((data) => {
|
|
@@ -257,7 +258,7 @@ class CryptoIdentityManager {
|
|
|
257
258
|
async hasStoredIdentities(username) {
|
|
258
259
|
try {
|
|
259
260
|
const hasIdentities = await new Promise((resolve) => {
|
|
260
|
-
this.
|
|
261
|
+
this.db.gun
|
|
261
262
|
.user()
|
|
262
263
|
.get("crypto-identities")
|
|
263
264
|
.once((data) => {
|
|
@@ -344,7 +345,7 @@ class CryptoIdentityManager {
|
|
|
344
345
|
};
|
|
345
346
|
}
|
|
346
347
|
// Ottieni il SEA pair dell'utente corrente
|
|
347
|
-
const userInstance = this.
|
|
348
|
+
const userInstance = this.db.gun.user();
|
|
348
349
|
const seaPair = userInstance?._?.sea;
|
|
349
350
|
if (!seaPair) {
|
|
350
351
|
return {
|