Add password protection feature in MultiChatDialog: Implement room password management, including prompts for password entry and error handling for invalid passwords. Update i18n files with localized messages for password prompts in English, German, and Spanish.

This commit is contained in:
Torsten Schulz (local)
2026-03-04 23:32:32 +01:00
parent a117bad342
commit a48e907e50
4 changed files with 66 additions and 3 deletions

View File

@@ -321,6 +321,8 @@ export default {
pendingRoomCreateName: '',
pendingRoomCreateAttempts: 0,
pendingRoomCreateTimer: null,
roomPasswords: {},
passwordPromptActive: false,
// Palette state
paletteWidth: 420,
paletteHeight: 220,
@@ -365,7 +367,7 @@ export default {
selectedRoom(newVal, oldVal) {
if (newVal && this.transportConnected) {
const room = this.getSelectedRoomName();
if (room) this.sendWithToken({ type: 'join', room, password: '' });
if (room) this.sendWithToken({ type: 'join', room, password: this.getRoomPassword(room) });
this.messages = [];
this.usersInRoom = [];
this.selectedTargetUser = null;
@@ -405,6 +407,43 @@ export default {
roomNamesEqual(a, b) {
return (a || '').trim().toLowerCase() === (b || '').trim().toLowerCase();
},
getRoomPassword(roomName) {
if (!roomName) return '';
return this.roomPasswords[roomName] || '';
},
async handleRoomPasswordError(errorCode) {
const room = this.getSelectedRoomName();
if (!room || this.passwordPromptActive) return;
this.passwordPromptActive = true;
try {
const isInvalid = errorCode === 'room_password_invalid';
const promptText = isInvalid
? this.$t('chat.multichat.password.invalidPrompt', { room })
: this.$t('chat.multichat.password.requiredPrompt', { room });
const entered = window.prompt(promptText, '');
if (entered === null) {
this.messages.push({
id: Date.now(),
user: 'System',
text: this.$t('chat.multichat.password.cancelled', { room })
});
return;
}
const password = entered.trim();
if (!password) {
this.messages.push({
id: Date.now(),
user: 'System',
text: this.$t('chat.multichat.password.empty')
});
return;
}
this.roomPasswords[room] = password;
this.sendWithToken({ type: 'join', room, password });
} finally {
this.passwordPromptActive = false;
}
},
tryConfirmRoomCreateSuccess() {
if (!this.pendingRoomCreateName) return false;
const created = this.ownRooms.find((r) => this.roomNamesEqual(r.title, this.pendingRoomCreateName));
@@ -805,7 +844,8 @@ export default {
// Drop references to losers so GC can collect
this.pendingWs = [];
// Prepare handshake like before
const init = { type: 'init', name: this.user?.username || '', room: this.getSelectedRoomName() || '', password: '' };
const initRoom = this.getSelectedRoomName() || '';
const init = { type: 'init', name: this.user?.username || '', room: initRoom, password: this.getRoomPassword(initRoom) };
if (this.debug) console.log('[Chat WS >>]', init);
this.wsSend(init);
if (this.connectAttemptTimeout) clearTimeout(this.connectAttemptTimeout);
@@ -902,7 +942,8 @@ export default {
this.transportConnected = true;
const dt = Date.now() - (this.wsStartAt || Date.now());
console.log('[Chat WS] open in', dt, 'ms', '| protocol:', ws.protocol || '(none)', '| url:', url);
const init = { type: 'init', name: this.user?.username || '', room: this.getSelectedRoomName() || '', password: '' };
const initRoom = this.getSelectedRoomName() || '';
const init = { type: 'init', name: this.user?.username || '', room: initRoom, password: this.getRoomPassword(initRoom) };
if (this.debug) console.log('[Chat WS >>]', init);
this.wsSend(init);
if (this.connectOpenTimer) { clearTimeout(this.connectOpenTimer); this.connectOpenTimer = null; }
@@ -1413,6 +1454,10 @@ export default {
if (!obj) return;
if (obj.type === 'error') {
const text = obj.message || 'chat_error';
if (text === 'room_password_required' || text === 'room_password_invalid') {
this.handleRoomPasswordError(text);
return;
}
this.setStatus('error');
this.messages.push({ id: Date.now(), user: 'System', text: `Fehler: ${text}` });
return;

View File

@@ -114,6 +114,12 @@
"servicesStatus": "Service-Status"
},
"types": {}
},
"password": {
"requiredPrompt": "Der Raum \"{room}\" ist passwortgeschützt. Bitte Passwort eingeben:",
"invalidPrompt": "Falsches Passwort für \"{room}\". Bitte erneut eingeben:",
"cancelled": "Beitritt zu \"{room}\" abgebrochen.",
"empty": "Passwort darf nicht leer sein."
}
},
"randomchat": {

View File

@@ -114,6 +114,12 @@
"servicesStatus": "Service status"
},
"types": {}
},
"password": {
"requiredPrompt": "Room \"{room}\" is password-protected. Please enter password:",
"invalidPrompt": "Wrong password for \"{room}\". Please try again:",
"cancelled": "Join to \"{room}\" was cancelled.",
"empty": "Password must not be empty."
}
},
"randomchat": {

View File

@@ -113,6 +113,12 @@
"servicesStatus": "Estado de servicios"
},
"types": {}
},
"password": {
"requiredPrompt": "La sala \"{room}\" está protegida por contraseña. Introduce la contraseña:",
"invalidPrompt": "Contraseña incorrecta para \"{room}\". Inténtalo de nuevo:",
"cancelled": "Se canceló el acceso a \"{room}\".",
"empty": "La contraseña no puede estar vacía."
}
},
"randomchat": {