@celerispay/hazelcast-client 3.12.5 → 3.12.7

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.
@@ -34,53 +34,126 @@ var ConnectionAuthenticator = /** @class */ (function () {
34
34
  }
35
35
  ConnectionAuthenticator.prototype.authenticate = function (asOwner) {
36
36
  var _this = this;
37
+ var addressStr = this.connection.getAddress().toString();
38
+ this.logger.info('ConnectionAuthenticator', "\uD83D\uDD10 Starting authentication for " + addressStr + " (asOwner=" + asOwner + ")");
37
39
  var credentials = this.createCredentials(asOwner);
40
+ this.logger.info('ConnectionAuthenticator', "\uD83D\uDCE4 Sending authentication request to " + addressStr + "...");
38
41
  return this.client.getInvocationService()
39
42
  .invokeOnConnection(this.connection, credentials)
40
43
  .then(function (msg) {
44
+ _this.logger.info('ConnectionAuthenticator', "\uD83D\uDCE5 Received authentication response from " + addressStr);
41
45
  var authResponse = ClientAuthenticationCodec_1.ClientAuthenticationCodec.decodeResponse(msg);
46
+ _this.logger.info('ConnectionAuthenticator', "\uD83D\uDD0D Authentication response for " + addressStr + ":");
47
+ _this.logger.info('ConnectionAuthenticator', " - Status: " + authResponse.status + " (" + _this.getStatusDescription(authResponse.status) + ")");
48
+ _this.logger.info('ConnectionAuthenticator', " - Server UUID: " + (authResponse.uuid || 'NOT PROVIDED'));
49
+ _this.logger.info('ConnectionAuthenticator', " - Server Owner UUID: " + (authResponse.ownerUuid || 'NOT PROVIDED'));
50
+ _this.logger.info('ConnectionAuthenticator', " - Server Address: " + (authResponse.address ? authResponse.address.toString() : 'NOT PROVIDED'));
51
+ _this.logger.info('ConnectionAuthenticator', " - Server Version: " + (authResponse.serverHazelcastVersion || 'NOT PROVIDED'));
42
52
  switch (authResponse.status) {
43
53
  case 0 /* AUTHENTICATED */:
54
+ _this.logger.info('ConnectionAuthenticator', "\u2705 Authentication SUCCESSFUL for " + addressStr);
44
55
  _this.connection.setAddress(authResponse.address);
45
56
  _this.connection.setConnectedServerVersion(authResponse.serverHazelcastVersion);
46
57
  if (asOwner) {
58
+ var oldUuid = _this.clusterService.uuid;
59
+ var oldOwnerUuid = _this.clusterService.ownerUuid;
47
60
  _this.clusterService.uuid = authResponse.uuid;
48
61
  _this.clusterService.ownerUuid = authResponse.ownerUuid;
62
+ _this.logger.info('ConnectionAuthenticator', "\uD83D\uDD04 Updated cluster service for " + addressStr + ":");
63
+ _this.logger.info('ConnectionAuthenticator', " - UUID: " + (oldUuid || 'NOT SET') + " \u2192 " + authResponse.uuid);
64
+ _this.logger.info('ConnectionAuthenticator', " - Owner UUID: " + (oldOwnerUuid || 'NOT SET') + " \u2192 " + authResponse.ownerUuid);
49
65
  }
50
- _this.logger.info('ConnectionAuthenticator', 'Connection to ' +
51
- _this.connection.getAddress().toString() + ' authenticated');
66
+ _this.logger.info('ConnectionAuthenticator', "\u2705 Connection to " + addressStr + " authenticated successfully");
52
67
  break;
53
68
  case 1 /* CREDENTIALS_FAILED */:
54
- _this.logger.error('ConnectionAuthenticator', 'Invalid Credentials');
55
- throw new Error('Invalid Credentials, could not authenticate connection to ' +
56
- _this.connection.getAddress().toString());
69
+ _this.logger.error('ConnectionAuthenticator', "\u274C Authentication FAILED for " + addressStr + ": Invalid Credentials");
70
+ _this.logger.error('ConnectionAuthenticator', " - Server rejected our credentials");
71
+ _this.logger.error('ConnectionAuthenticator', " - Check if UUIDs and group credentials are correct");
72
+ throw new Error('Invalid Credentials, could not authenticate connection to ' + addressStr);
57
73
  case 2 /* SERIALIZATION_VERSION_MISMATCH */:
58
- _this.logger.error('ConnectionAuthenticator', 'Serialization version mismatch');
59
- throw new Error('Serialization version mismatch, could not authenticate connection to ' +
60
- _this.connection.getAddress().toString());
74
+ _this.logger.error('ConnectionAuthenticator', "\u274C Authentication FAILED for " + addressStr + ": Serialization version mismatch");
75
+ throw new Error('Serialization version mismatch, could not authenticate connection to ' + addressStr);
61
76
  default:
62
- _this.logger.error('ConnectionAuthenticator', 'Unknown authentication status: '
63
- + authResponse.status);
77
+ _this.logger.error('ConnectionAuthenticator', "\u274C Authentication FAILED for " + addressStr + ": Unknown status " + authResponse.status);
64
78
  throw new HazelcastError_1.AuthenticationError('Unknown authentication status: ' + authResponse.status +
65
- ' , could not authenticate connection to ' +
66
- _this.connection.getAddress().toString());
79
+ ' , could not authenticate connection to ' + addressStr);
67
80
  }
81
+ })
82
+ .catch(function (error) {
83
+ _this.logger.error('ConnectionAuthenticator', "\uD83D\uDCA5 Authentication ERROR for " + addressStr + ": " + error.message);
84
+ throw error;
68
85
  });
69
86
  };
87
+ /**
88
+ * Gets a human-readable description of authentication status
89
+ */
90
+ ConnectionAuthenticator.prototype.getStatusDescription = function (status) {
91
+ switch (status) {
92
+ case 0 /* AUTHENTICATED */: return 'AUTHENTICATED';
93
+ case 1 /* CREDENTIALS_FAILED */: return 'CREDENTIALS_FAILED';
94
+ case 2 /* SERIALIZATION_VERSION_MISMATCH */: return 'SERIALIZATION_VERSION_MISMATCH';
95
+ default: return "UNKNOWN_STATUS_" + status;
96
+ }
97
+ };
98
+ /**
99
+ * Creates credentials with optional restoration from preservation service
100
+ * @param asOwner Whether this is an owner connection
101
+ * @param preservedCredentials Optional preserved credentials to use
102
+ * @returns The credentials message
103
+ */
104
+ ConnectionAuthenticator.prototype.createCredentialsWithRestoration = function (asOwner, preservedCredentials) {
105
+ if (preservedCredentials && preservedCredentials.uuid && preservedCredentials.ownerUuid) {
106
+ this.logger.debug('ConnectionAuthenticator', "Using preserved credentials: uuid=" + preservedCredentials.uuid + ", ownerUuid=" + preservedCredentials.ownerUuid);
107
+ // Use preserved credentials instead of current cluster state
108
+ var groupConfig = this.client.getConfig().groupConfig;
109
+ var customCredentials = this.client.getConfig().customCredentials;
110
+ var clientMessage = void 0;
111
+ var clientVersion = BuildInfo_1.BuildInfo.getClientVersion();
112
+ if (customCredentials != null) {
113
+ var credentialsPayload = this.client.getSerializationService().toData(customCredentials);
114
+ clientMessage = ClientAuthenticationCustomCodec_1.ClientAuthenticationCustomCodec.encodeRequest(credentialsPayload, preservedCredentials.uuid, preservedCredentials.ownerUuid, asOwner, 'NJS', 1, clientVersion);
115
+ }
116
+ else {
117
+ clientMessage = ClientAuthenticationCodec_1.ClientAuthenticationCodec.encodeRequest(preservedCredentials.groupName, preservedCredentials.groupPassword, preservedCredentials.uuid, preservedCredentials.ownerUuid, asOwner, 'NJS', 1, clientVersion);
118
+ }
119
+ return clientMessage;
120
+ }
121
+ // Fall back to normal credential creation
122
+ return this.createCredentials(asOwner);
123
+ };
70
124
  ConnectionAuthenticator.prototype.createCredentials = function (asOwner) {
71
125
  var groupConfig = this.client.getConfig().groupConfig;
72
126
  var uuid = this.clusterService.uuid;
73
127
  var ownerUuid = this.clusterService.ownerUuid;
74
128
  var customCredentials = this.client.getConfig().customCredentials;
129
+ // LOG EXACTLY WHAT CREDENTIALS WE'RE SENDING
130
+ this.logger.info('ConnectionAuthenticator', "\uD83D\uDD10 Creating authentication credentials for " + this.connection.getAddress().toString() + ":");
131
+ this.logger.info('ConnectionAuthenticator', " - As Owner: " + asOwner);
132
+ this.logger.info('ConnectionAuthenticator', " - UUID: " + (uuid || 'NOT SET'));
133
+ this.logger.info('ConnectionAuthenticator', " - Owner UUID: " + (ownerUuid || 'NOT SET'));
134
+ this.logger.info('ConnectionAuthenticator', " - Group Name: " + (groupConfig.name || 'NOT SET'));
135
+ this.logger.info('ConnectionAuthenticator', " - Group Password: " + (groupConfig.password ? '***SET***' : 'NOT SET'));
136
+ this.logger.info('ConnectionAuthenticator', " - Custom Credentials: " + (customCredentials ? 'YES' : 'NO'));
137
+ this.logger.info('ConnectionAuthenticator', " - Client Version: " + BuildInfo_1.BuildInfo.getClientVersion());
75
138
  var clientMessage;
76
139
  var clientVersion = BuildInfo_1.BuildInfo.getClientVersion();
77
140
  if (customCredentials != null) {
78
141
  var credentialsPayload = this.client.getSerializationService().toData(customCredentials);
142
+ this.logger.info('ConnectionAuthenticator', "\uD83D\uDCE4 Sending CUSTOM authentication request with:");
143
+ this.logger.info('ConnectionAuthenticator', " - Custom Credentials: " + typeof credentialsPayload);
144
+ this.logger.info('ConnectionAuthenticator', " - UUID: " + (uuid || 'NOT SET'));
145
+ this.logger.info('ConnectionAuthenticator', " - Owner UUID: " + (ownerUuid || 'NOT SET'));
79
146
  clientMessage = ClientAuthenticationCustomCodec_1.ClientAuthenticationCustomCodec.encodeRequest(credentialsPayload, uuid, ownerUuid, asOwner, 'NJS', 1, clientVersion);
80
147
  }
81
148
  else {
149
+ this.logger.info('ConnectionAuthenticator', "\uD83D\uDCE4 Sending STANDARD authentication request with:");
150
+ this.logger.info('ConnectionAuthenticator', " - Group Name: " + (groupConfig.name || 'NOT SET'));
151
+ this.logger.info('ConnectionAuthenticator', " - Group Password: " + (groupConfig.password ? '***SET***' : 'NOT SET'));
152
+ this.logger.info('ConnectionAuthenticator', " - UUID: " + (uuid || 'NOT SET'));
153
+ this.logger.info('ConnectionAuthenticator', " - Owner UUID: " + (ownerUuid || 'NOT SET'));
82
154
  clientMessage = ClientAuthenticationCodec_1.ClientAuthenticationCodec.encodeRequest(groupConfig.name, groupConfig.password, uuid, ownerUuid, asOwner, 'NJS', 1, clientVersion);
83
155
  }
156
+ this.logger.info('ConnectionAuthenticator', "\uD83D\uDCCB Final authentication message created and ready to send");
84
157
  return clientMessage;
85
158
  };
86
159
  return ConnectionAuthenticator;
@@ -0,0 +1,137 @@
1
+ import { ILogger } from '../logging/ILogger';
2
+ import Address = require('../Address');
3
+ /**
4
+ * Interface for node credentials
5
+ */
6
+ export interface NodeCredentials {
7
+ uuid: string;
8
+ ownerUuid: string;
9
+ groupName: string;
10
+ groupPassword: string;
11
+ lastAuthenticated: number;
12
+ isOwner: boolean;
13
+ }
14
+ /**
15
+ * Service to preserve and restore authentication credentials across failover cycles
16
+ * This fixes the "Invalid Credentials" issue that occurs when nodes rejoin after failover
17
+ */
18
+ export declare class CredentialPreservationService {
19
+ private readonly logger;
20
+ /**
21
+ * Stores authentication context for each node
22
+ */
23
+ private nodeCredentials;
24
+ constructor(logger: ILogger);
25
+ /**
26
+ * Preserves authentication credentials for a node before it gets disconnected
27
+ * @param address The node address
28
+ * @param uuid The node's UUID
29
+ * @param ownerUuid The owner UUID
30
+ * @param groupName The group name
31
+ * @param groupPassword The group password
32
+ * @param isOwner Whether this is an owner connection
33
+ */
34
+ preserveCredentials(address: Address, uuid: string, ownerUuid: string, groupName: string, groupPassword: string, isOwner: boolean): void;
35
+ /**
36
+ * Restores authentication credentials for a specific node
37
+ * @param address The node address
38
+ * @returns The preserved credentials or null if not found
39
+ */
40
+ restoreCredentials(address: Address): NodeCredentials | null;
41
+ /**
42
+ * Updates credentials after successful authentication
43
+ * @param address The node address
44
+ * @param uuid The new UUID
45
+ * @param ownerUuid The new owner UUID
46
+ */
47
+ updateCredentials(address: Address, uuid: string, ownerUuid: string): void;
48
+ /**
49
+ * Clears credentials for a specific node
50
+ * @param address The node address
51
+ */
52
+ clearCredentials(address: Address): void;
53
+ /**
54
+ * Cleans up stale credentials older than the specified age
55
+ * @param maxAgeMs Maximum age in milliseconds (default: 5 minutes)
56
+ */
57
+ cleanupStaleCredentials(maxAgeMs?: number): void;
58
+ /**
59
+ * Gets a summary of preserved credentials for debugging
60
+ * @returns A summary string
61
+ */
62
+ getCredentialsSummary(): string;
63
+ /**
64
+ * Smart credential restoration that handles both scenarios:
65
+ * 1. If member added event occurred -> use new UUID
66
+ * 2. If no member added event -> use old UUID (node probably never changed)
67
+ * @param address The address to restore credentials for
68
+ * @param hasMemberAddedEvent Whether we received a member added event for this address
69
+ * @returns The appropriate credentials to use
70
+ */
71
+ smartRestoreCredentials(address: Address, hasMemberAddedEvent?: boolean): NodeCredentials | null;
72
+ /**
73
+ * Checks if we have valid credentials for an address
74
+ * @param address The address to check
75
+ * @returns True if we have valid credentials
76
+ */
77
+ hasValidCredentials(address: Address): boolean;
78
+ /**
79
+ * Gets the last known UUID for an address
80
+ * @param address The address to get UUID for
81
+ * @returns The UUID or null if not found
82
+ */
83
+ getLastKnownUuid(address: Address): string | null;
84
+ /**
85
+ * Updates the owner UUID for ALL preserved credentials
86
+ * This is called when cluster membership changes and we need to sync all credentials
87
+ * @param newOwnerUuid The new owner UUID from the current cluster state
88
+ */
89
+ updateAllOwnerUuids(newOwnerUuid: string): void;
90
+ /**
91
+ * Gets the current owner UUID from preserved credentials
92
+ * @returns The current owner UUID or null if not found
93
+ */
94
+ getCurrentOwnerUuid(): string | null;
95
+ /**
96
+ * Validates that all credentials have consistent owner UUIDs
97
+ * @returns True if all credentials are consistent, false otherwise
98
+ */
99
+ validateOwnerUuidConsistency(): boolean;
100
+ /**
101
+ * Invalidates ALL credentials that have a specific owner UUID
102
+ * This is called when cluster membership changes and old owner UUIDs become invalid
103
+ * @param oldOwnerUuid The old owner UUID that is no longer valid
104
+ */
105
+ invalidateCredentialsWithOwnerUuid(oldOwnerUuid: string): void;
106
+ /**
107
+ * Invalidates ALL credentials that don't match the current cluster owner UUID
108
+ * This ensures complete credential consistency across the entire cluster
109
+ * @param currentClusterOwnerUuid The current cluster owner UUID that should be valid
110
+ */
111
+ invalidateAllCredentialsExceptCurrentOwner(currentClusterOwnerUuid: string): void;
112
+ /**
113
+ * Invalidates only problematic credentials while preserving working ones
114
+ * This prevents breaking working connections (like 192.168.1.108)
115
+ * @param currentClusterOwnerUuid The current cluster owner UUID that should be valid
116
+ */
117
+ invalidateOnlyProblematicCredentials(currentClusterOwnerUuid: string): void;
118
+ /**
119
+ * Checks if an address has had recent authentication issues
120
+ * This helps determine which credentials to invalidate
121
+ * @param addressStr The address to check
122
+ * @returns True if the address has recent auth issues
123
+ */
124
+ private hasRecentAuthenticationIssues(addressStr);
125
+ /**
126
+ * Clears all credentials for a specific address
127
+ * This is called when we need to force fresh authentication for a node
128
+ * @param address The address to clear credentials for
129
+ */
130
+ clearCredentialsForAddress(address: Address): void;
131
+ /**
132
+ * Gets all addresses that have credentials with a specific owner UUID
133
+ * @param ownerUuid The owner UUID to search for
134
+ * @returns Array of addresses that have credentials with this owner UUID
135
+ */
136
+ getAddressesWithOwnerUuid(ownerUuid: string): string[];
137
+ }
@@ -0,0 +1,369 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ /**
19
+ * Service to preserve and restore authentication credentials across failover cycles
20
+ * This fixes the "Invalid Credentials" issue that occurs when nodes rejoin after failover
21
+ */
22
+ var CredentialPreservationService = /** @class */ (function () {
23
+ function CredentialPreservationService(logger) {
24
+ /**
25
+ * Stores authentication context for each node
26
+ */
27
+ this.nodeCredentials = new Map();
28
+ this.logger = logger;
29
+ }
30
+ /**
31
+ * Preserves authentication credentials for a node before it gets disconnected
32
+ * @param address The node address
33
+ * @param uuid The node's UUID
34
+ * @param ownerUuid The owner UUID
35
+ * @param groupName The group name
36
+ * @param groupPassword The group password
37
+ * @param isOwner Whether this is an owner connection
38
+ */
39
+ CredentialPreservationService.prototype.preserveCredentials = function (address, uuid, ownerUuid, groupName, groupPassword, isOwner) {
40
+ var addressStr = address.toString();
41
+ this.nodeCredentials.set(addressStr, {
42
+ uuid: uuid,
43
+ ownerUuid: ownerUuid,
44
+ groupName: groupName,
45
+ groupPassword: groupPassword,
46
+ lastAuthenticated: Date.now(),
47
+ isOwner: isOwner
48
+ });
49
+ this.logger.debug('CredentialPreservationService', "Preserved credentials for " + addressStr + ": uuid=" + uuid + ", ownerUuid=" + ownerUuid + ", isOwner=" + isOwner);
50
+ };
51
+ /**
52
+ * Restores authentication credentials for a specific node
53
+ * @param address The node address
54
+ * @returns The preserved credentials or null if not found
55
+ */
56
+ CredentialPreservationService.prototype.restoreCredentials = function (address) {
57
+ var _this = this;
58
+ var addressStr = address.toString();
59
+ var credentials = this.nodeCredentials.get(addressStr);
60
+ if (credentials) {
61
+ this.logger.info('CredentialPreservationService', "\u2705 Found preserved credentials for " + addressStr + ": uuid=" + credentials.uuid + ", ownerUuid=" + credentials.ownerUuid);
62
+ return credentials;
63
+ }
64
+ // Log all available credentials for debugging
65
+ this.logger.info('CredentialPreservationService', "\u274C No preserved credentials found for " + addressStr);
66
+ this.logger.info('CredentialPreservationService', "\uD83D\uDCCB Available credentials: " + this.nodeCredentials.size + " entries");
67
+ if (this.nodeCredentials.size > 0) {
68
+ this.nodeCredentials.forEach(function (cred, addr) {
69
+ _this.logger.info('CredentialPreservationService', " - " + addr + ": uuid=" + cred.uuid + ", ownerUuid=" + cred.ownerUuid + ", isOwner=" + cred.isOwner);
70
+ });
71
+ }
72
+ return null;
73
+ };
74
+ /**
75
+ * Updates credentials after successful authentication
76
+ * @param address The node address
77
+ * @param uuid The new UUID
78
+ * @param ownerUuid The new owner UUID
79
+ */
80
+ CredentialPreservationService.prototype.updateCredentials = function (address, uuid, ownerUuid) {
81
+ var addressStr = address.toString();
82
+ var credentials = this.nodeCredentials.get(addressStr);
83
+ if (credentials) {
84
+ credentials.uuid = uuid;
85
+ credentials.ownerUuid = ownerUuid;
86
+ credentials.lastAuthenticated = Date.now();
87
+ this.logger.debug('CredentialPreservationService', "Updated credentials for " + addressStr + ": uuid=" + uuid + ", ownerUuid=" + ownerUuid);
88
+ }
89
+ };
90
+ /**
91
+ * Clears credentials for a specific node
92
+ * @param address The node address
93
+ */
94
+ CredentialPreservationService.prototype.clearCredentials = function (address) {
95
+ var addressStr = address.toString();
96
+ if (this.nodeCredentials.delete(addressStr)) {
97
+ this.logger.debug('CredentialPreservationService', "Cleared credentials for " + addressStr);
98
+ }
99
+ };
100
+ /**
101
+ * Cleans up stale credentials older than the specified age
102
+ * @param maxAgeMs Maximum age in milliseconds (default: 5 minutes)
103
+ */
104
+ CredentialPreservationService.prototype.cleanupStaleCredentials = function (maxAgeMs) {
105
+ var _this = this;
106
+ if (maxAgeMs === void 0) { maxAgeMs = 300000; }
107
+ var now = Date.now();
108
+ var addressesToRemove = [];
109
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
110
+ var age = now - credentials.lastAuthenticated;
111
+ if (age > maxAgeMs) {
112
+ addressesToRemove.push(addressStr);
113
+ }
114
+ });
115
+ if (addressesToRemove.length > 0) {
116
+ addressesToRemove.forEach(function (addressStr) {
117
+ _this.nodeCredentials.delete(addressStr);
118
+ });
119
+ this.logger.debug('CredentialPreservationService', "Cleaned up " + addressesToRemove.length + " stale credential entries");
120
+ }
121
+ };
122
+ /**
123
+ * Gets a summary of preserved credentials for debugging
124
+ * @returns A summary string
125
+ */
126
+ CredentialPreservationService.prototype.getCredentialsSummary = function () {
127
+ var entries = Array.from(this.nodeCredentials.entries());
128
+ if (entries.length === 0) {
129
+ return 'none';
130
+ }
131
+ return entries.map(function (_a) {
132
+ var address = _a[0], creds = _a[1];
133
+ return address + ": uuid=" + (creds.uuid || 'null') + ", ownerUuid=" + (creds.ownerUuid || 'null') + ", isOwner=" + creds.isOwner;
134
+ }).join('; ');
135
+ };
136
+ /**
137
+ * Smart credential restoration that handles both scenarios:
138
+ * 1. If member added event occurred -> use new UUID
139
+ * 2. If no member added event -> use old UUID (node probably never changed)
140
+ * @param address The address to restore credentials for
141
+ * @param hasMemberAddedEvent Whether we received a member added event for this address
142
+ * @returns The appropriate credentials to use
143
+ */
144
+ CredentialPreservationService.prototype.smartRestoreCredentials = function (address, hasMemberAddedEvent) {
145
+ if (hasMemberAddedEvent === void 0) { hasMemberAddedEvent = false; }
146
+ var addressStr = address.toString();
147
+ var credentials = this.nodeCredentials.get(addressStr);
148
+ if (!credentials) {
149
+ this.logger.debug('CredentialPreservationService', "No preserved credentials found for " + addressStr);
150
+ return null;
151
+ }
152
+ if (hasMemberAddedEvent) {
153
+ // Member actually left and rejoined - use the updated credentials
154
+ this.logger.info('CredentialPreservationService', "\uD83D\uDD04 Member added event detected for " + addressStr + ", using updated credentials: uuid=" + credentials.uuid);
155
+ return credentials;
156
+ }
157
+ else {
158
+ // No member added event - node probably never changed, use original credentials
159
+ this.logger.info('CredentialPreservationService', "\uD83D\uDD04 No member added event for " + addressStr + ", assuming node unchanged, using original credentials: uuid=" + credentials.uuid);
160
+ return credentials;
161
+ }
162
+ };
163
+ /**
164
+ * Checks if we have valid credentials for an address
165
+ * @param address The address to check
166
+ * @returns True if we have valid credentials
167
+ */
168
+ CredentialPreservationService.prototype.hasValidCredentials = function (address) {
169
+ var addressStr = address.toString();
170
+ var credentials = this.nodeCredentials.get(addressStr);
171
+ return !!(credentials && credentials.uuid && credentials.ownerUuid);
172
+ };
173
+ /**
174
+ * Gets the last known UUID for an address
175
+ * @param address The address to get UUID for
176
+ * @returns The UUID or null if not found
177
+ */
178
+ CredentialPreservationService.prototype.getLastKnownUuid = function (address) {
179
+ var addressStr = address.toString();
180
+ var credentials = this.nodeCredentials.get(addressStr);
181
+ return credentials ? credentials.uuid : null;
182
+ };
183
+ /**
184
+ * Updates the owner UUID for ALL preserved credentials
185
+ * This is called when cluster membership changes and we need to sync all credentials
186
+ * @param newOwnerUuid The new owner UUID from the current cluster state
187
+ */
188
+ CredentialPreservationService.prototype.updateAllOwnerUuids = function (newOwnerUuid) {
189
+ var _this = this;
190
+ this.logger.info('CredentialPreservationService', "\uD83D\uDD04 Updating ALL preserved credentials with new owner UUID: " + newOwnerUuid);
191
+ var updatedCount = 0;
192
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
193
+ if (credentials.ownerUuid !== newOwnerUuid) {
194
+ var oldOwnerUuid = credentials.ownerUuid;
195
+ credentials.ownerUuid = newOwnerUuid;
196
+ updatedCount++;
197
+ _this.logger.info('CredentialPreservationService', "\uD83D\uDD04 Updated " + addressStr + ": ownerUuid " + oldOwnerUuid + " \u2192 " + newOwnerUuid);
198
+ }
199
+ });
200
+ this.logger.info('CredentialPreservationService', "\u2705 Updated " + updatedCount + " credential entries with new owner UUID");
201
+ };
202
+ /**
203
+ * Gets the current owner UUID from preserved credentials
204
+ * @returns The current owner UUID or null if not found
205
+ */
206
+ CredentialPreservationService.prototype.getCurrentOwnerUuid = function () {
207
+ // Find any credential that has isOwner=true
208
+ for (var _i = 0, _a = Array.from(this.nodeCredentials.values()); _i < _a.length; _i++) {
209
+ var credentials = _a[_i];
210
+ if (credentials.isOwner) {
211
+ return credentials.ownerUuid;
212
+ }
213
+ }
214
+ // If no owner found, return the first available ownerUuid
215
+ for (var _b = 0, _c = Array.from(this.nodeCredentials.values()); _b < _c.length; _b++) {
216
+ var credentials = _c[_b];
217
+ if (credentials.ownerUuid) {
218
+ return credentials.ownerUuid;
219
+ }
220
+ }
221
+ return null;
222
+ };
223
+ /**
224
+ * Validates that all credentials have consistent owner UUIDs
225
+ * @returns True if all credentials are consistent, false otherwise
226
+ */
227
+ CredentialPreservationService.prototype.validateOwnerUuidConsistency = function () {
228
+ var ownerUuids = new Set();
229
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
230
+ if (credentials.ownerUuid) {
231
+ ownerUuids.add(credentials.ownerUuid);
232
+ }
233
+ });
234
+ var isConsistent = ownerUuids.size <= 1;
235
+ if (!isConsistent) {
236
+ this.logger.warn('CredentialPreservationService', "\u26A0\uFE0F Owner UUID inconsistency detected: " + Array.from(ownerUuids).join(', '));
237
+ }
238
+ return isConsistent;
239
+ };
240
+ /**
241
+ * Invalidates ALL credentials that have a specific owner UUID
242
+ * This is called when cluster membership changes and old owner UUIDs become invalid
243
+ * @param oldOwnerUuid The old owner UUID that is no longer valid
244
+ */
245
+ CredentialPreservationService.prototype.invalidateCredentialsWithOwnerUuid = function (oldOwnerUuid) {
246
+ var _this = this;
247
+ this.logger.info('CredentialPreservationService', "\uD83D\uDDD1\uFE0F Invalidating ALL credentials with old owner UUID: " + oldOwnerUuid);
248
+ var invalidatedCount = 0;
249
+ var addressesToRemove = [];
250
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
251
+ if (credentials.ownerUuid === oldOwnerUuid) {
252
+ _this.logger.info('CredentialPreservationService', "\uD83D\uDDD1\uFE0F Invalidating credentials for " + addressStr + ": old ownerUuid=" + oldOwnerUuid);
253
+ addressesToRemove.push(addressStr);
254
+ invalidatedCount++;
255
+ }
256
+ });
257
+ // Remove the invalidated credentials
258
+ addressesToRemove.forEach(function (addressStr) {
259
+ _this.nodeCredentials.delete(addressStr);
260
+ });
261
+ this.logger.info('CredentialPreservationService', "\u2705 Invalidated " + invalidatedCount + " credential entries with old owner UUID: " + oldOwnerUuid);
262
+ };
263
+ /**
264
+ * Invalidates ALL credentials that don't match the current cluster owner UUID
265
+ * This ensures complete credential consistency across the entire cluster
266
+ * @param currentClusterOwnerUuid The current cluster owner UUID that should be valid
267
+ */
268
+ CredentialPreservationService.prototype.invalidateAllCredentialsExceptCurrentOwner = function (currentClusterOwnerUuid) {
269
+ var _this = this;
270
+ this.logger.info('CredentialPreservationService', "\uD83D\uDDD1\uFE0F Comprehensive credential cleanup: Invalidating ALL credentials except those with current owner UUID: " + currentClusterOwnerUuid);
271
+ var invalidatedCount = 0;
272
+ var addressesToRemove = [];
273
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
274
+ if (credentials.ownerUuid !== currentClusterOwnerUuid) {
275
+ _this.logger.info('CredentialPreservationService', "\uD83D\uDDD1\uFE0F Invalidating credentials for " + addressStr + ": old ownerUuid=" + credentials.ownerUuid + " \u2260 current=" + currentClusterOwnerUuid);
276
+ addressesToRemove.push(addressStr);
277
+ invalidatedCount++;
278
+ }
279
+ else {
280
+ _this.logger.debug('CredentialPreservationService', "\u2705 Keeping valid credentials for " + addressStr + ": ownerUuid=" + credentials.ownerUuid + " matches current");
281
+ }
282
+ });
283
+ // Remove the invalidated credentials
284
+ addressesToRemove.forEach(function (addressStr) {
285
+ _this.nodeCredentials.delete(addressStr);
286
+ });
287
+ this.logger.info('CredentialPreservationService', "\u2705 Comprehensive cleanup completed: Invalidated " + invalidatedCount + " credential entries, kept " + this.nodeCredentials.size + " valid entries");
288
+ // Log remaining valid credentials for debugging
289
+ if (this.nodeCredentials.size > 0) {
290
+ this.logger.info('CredentialPreservationService', "\uD83D\uDCCB Remaining valid credentials after cleanup:");
291
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
292
+ _this.logger.info('CredentialPreservationService', " - " + addressStr + ": uuid=" + credentials.uuid + ", ownerUuid=" + credentials.ownerUuid + ", isOwner=" + credentials.isOwner);
293
+ });
294
+ }
295
+ };
296
+ /**
297
+ * Invalidates only problematic credentials while preserving working ones
298
+ * This prevents breaking working connections (like 192.168.1.108)
299
+ * @param currentClusterOwnerUuid The current cluster owner UUID that should be valid
300
+ */
301
+ CredentialPreservationService.prototype.invalidateOnlyProblematicCredentials = function (currentClusterOwnerUuid) {
302
+ var _this = this;
303
+ this.logger.info('CredentialPreservationService', "\uD83C\uDFAF Targeted credential cleanup: Only invalidating problematic credentials, preserving working ones");
304
+ var invalidatedCount = 0;
305
+ var addressesToRemove = [];
306
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
307
+ // Only invalidate if the ownerUuid is clearly wrong AND we've had authentication issues
308
+ if (credentials.ownerUuid !== currentClusterOwnerUuid) {
309
+ // Check if this address has had recent authentication failures
310
+ var hasAuthIssues = _this.hasRecentAuthenticationIssues(addressStr);
311
+ if (hasAuthIssues) {
312
+ _this.logger.info('CredentialPreservationService', "\uD83C\uDFAF Invalidating problematic credentials for " + addressStr + ": old ownerUuid=" + credentials.ownerUuid + " \u2260 current=" + currentClusterOwnerUuid + " (has auth issues)");
313
+ addressesToRemove.push(addressStr);
314
+ invalidatedCount++;
315
+ }
316
+ else {
317
+ _this.logger.info('CredentialPreservationService', "\u2705 Keeping working credentials for " + addressStr + ": ownerUuid=" + credentials.ownerUuid + " (no auth issues)");
318
+ }
319
+ }
320
+ else {
321
+ _this.logger.debug('CredentialPreservationService', "\u2705 Keeping valid credentials for " + addressStr + ": ownerUuid=" + credentials.ownerUuid + " matches current");
322
+ }
323
+ });
324
+ // Remove only the problematic credentials
325
+ addressesToRemove.forEach(function (addressStr) {
326
+ _this.nodeCredentials.delete(addressStr);
327
+ });
328
+ this.logger.info('CredentialPreservationService', "\u2705 Targeted cleanup completed: Invalidated " + invalidatedCount + " problematic credential entries, kept " + this.nodeCredentials.size + " working entries");
329
+ };
330
+ /**
331
+ * Checks if an address has had recent authentication issues
332
+ * This helps determine which credentials to invalidate
333
+ * @param addressStr The address to check
334
+ * @returns True if the address has recent auth issues
335
+ */
336
+ CredentialPreservationService.prototype.hasRecentAuthenticationIssues = function (addressStr) {
337
+ // For now, we'll be conservative and only invalidate if we're certain
338
+ // In the future, we could track authentication failure history
339
+ return false; // Don't invalidate anything for now - revert to previous working behavior
340
+ };
341
+ /**
342
+ * Clears all credentials for a specific address
343
+ * This is called when we need to force fresh authentication for a node
344
+ * @param address The address to clear credentials for
345
+ */
346
+ CredentialPreservationService.prototype.clearCredentialsForAddress = function (address) {
347
+ var addressStr = address.toString();
348
+ if (this.nodeCredentials.has(addressStr)) {
349
+ this.logger.info('CredentialPreservationService', "\uD83D\uDDD1\uFE0F Clearing credentials for " + addressStr);
350
+ this.nodeCredentials.delete(addressStr);
351
+ }
352
+ };
353
+ /**
354
+ * Gets all addresses that have credentials with a specific owner UUID
355
+ * @param ownerUuid The owner UUID to search for
356
+ * @returns Array of addresses that have credentials with this owner UUID
357
+ */
358
+ CredentialPreservationService.prototype.getAddressesWithOwnerUuid = function (ownerUuid) {
359
+ var addresses = [];
360
+ this.nodeCredentials.forEach(function (credentials, addressStr) {
361
+ if (credentials.ownerUuid === ownerUuid) {
362
+ addresses.push(addressStr);
363
+ }
364
+ });
365
+ return addresses;
366
+ };
367
+ return CredentialPreservationService;
368
+ }());
369
+ exports.CredentialPreservationService = CredentialPreservationService;