fix(bot): свой разговор на каждый вход — чужие цифры не остаются в браузере

Ключ разговора в localStorage теперь привязан к тому, кто вошёл:
'liderra_chat_id_u<id>' в кабинете, 'liderra_chat_id_guest' на лендинге.
Смена вошедшего (вход/выход/вход под другим) очищает переписку на экране
и заводит новый ключ — иначе следующий человек за тем же компьютером
видел бы баланс и проекты прошлого клиента (окошко долбилось бы в чужой
разговор и получало 404 от серверной проверки владельца).
This commit is contained in:
Дмитрий
2026-07-13 12:11:48 +03:00
parent 550486b61c
commit 303bca9081
2 changed files with 63 additions and 9 deletions
+36 -5
View File
@@ -13,7 +13,6 @@
if (window.__liderraChat) return;
window.__liderraChat = true;
var KEY = 'liderra_chat_id';
var POLL_MS = 1000;
var POLL_LIMIT = 25; // 25 секунд — дальше сдаёмся и говорим честно
@@ -26,12 +25,29 @@
];
var FAILED = 'Что-то пошло не так, ответ не пришёл. Попробуйте ещё раз или напишите на support@liderra.ru.';
var chatId = localStorage.getItem(KEY);
if (!chatId || !/^[a-f0-9]{32}$/.test(chatId)) {
chatId = (crypto.randomUUID ? crypto.randomUUID() : String(Math.random())).replace(/[^a-f0-9]/g, '').slice(0, 32).padEnd(32, '0');
localStorage.setItem(KEY, chatId);
// Ключ разговора — СВОЙ на каждый вход: переписка вошедшего содержит его личные цифры
// (баланс, проекты), и следующий человек за тем же компьютером не должен их увидеть.
function keyFor(user) {
return user ? 'liderra_chat_id_u' + user : 'liderra_chat_id_guest';
}
function newChatId() {
return (crypto.randomUUID ? crypto.randomUUID() : String(Math.random()))
.replace(/[^a-f0-9]/g, '').slice(0, 32).padEnd(32, '0');
}
function chatIdFor(key) {
var id = localStorage.getItem(key);
if (!id || !/^[a-f0-9]{32}$/.test(id)) {
id = newChatId();
localStorage.setItem(key, id);
}
return id;
}
var KEY = keyFor(window.__liderraChatUser || null);
var chatId = chatIdFor(KEY);
var lastId = 0;
var busy = false;
@@ -225,4 +241,19 @@
input.value = '';
send(text);
};
// Скрипт грузится один раз за вкладку. Если в этой же вкладке вошли под другим клиентом
// (или вышли), окошко обязано забыть прежний разговор — иначе чужие цифры останутся
// на экране, а сервер будет отвечать 404 на чужой ключ.
window.__liderraChatSetUser = function (user) {
var next = keyFor(user || null);
if (next === KEY) return;
KEY = next;
chatId = chatIdFor(KEY);
lastId = 0;
busy = false;
while (body.firstChild) body.removeChild(body.firstChild);
if (panel.classList.contains('lch-open')) loadHistory();
};
})();
@@ -1,15 +1,29 @@
<script setup lang="ts">
/**
* Окошко чата Лидерры. Сам чат — /chat-widget.js (один файл, без сборки):
* тот же скрипт работает и на лендинге. Здесь — только подключение,
* по образцу прежнего JivoWidget (условная подгрузка скрипта).
* Окошко чата Лидерры. Сам чат — /chat-widget.js (один файл, без сборки): тот же скрипт
* работает и на лендинге. Здесь — подключение и передача того, КТО вошёл: по этому id окошко
* заводит отдельный разговор. Личные цифры одного клиента не должны попасть другому
* за тем же компьютером.
*/
import { onMounted } from 'vue';
import { onMounted, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useAuthStore } from '../../stores/auth';
declare global {
interface Window {
__liderraChatUser?: number | null;
__liderraChatSetUser?: (user: number | null) => void;
}
}
const SCRIPT_ID = 'liderra-chat-widget-js';
const { user } = storeToRefs(useAuthStore());
function injectChat(): void {
window.__liderraChatUser = user.value?.id ?? null;
if (document.getElementById(SCRIPT_ID) !== null) {
window.__liderraChatSetUser?.(window.__liderraChatUser);
return;
}
const script = document.createElement('script');
@@ -20,6 +34,15 @@ function injectChat(): void {
}
onMounted(injectChat);
// Вошли под другим клиентом в той же вкладке — окошко забывает прежний разговор.
watch(
() => user.value?.id ?? null,
(id) => {
window.__liderraChatUser = id;
window.__liderraChatSetUser?.(id);
},
);
</script>
<template>