feat(pulse): make heartbeat opt-in with transparency toggle
Heartbeat telemetry (домен, имя бота, версии PHP/модуля/OpenCart) больше не отправляется скрытно. Добавлен отдельный флаг pulse.heartbeat_enabled (по умолчанию выключен, opt-in), независимый от pulse.api_key: - ранний return в handleHeartbeat() при выключенном флаге (не трогает кэш/getMe); - провайдер читает флаг и инжектит в сервис; - в админке — переключатель с честным раскрытием состава данных; - debug-лог факта отправки в pushHeartbeat(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -88,6 +88,7 @@ export const useSettingsStore = defineStore('settings', {
|
|||||||
|
|
||||||
pulse: {
|
pulse: {
|
||||||
api_key: '',
|
api_key: '',
|
||||||
|
heartbeat_enabled: false,
|
||||||
batch_size: 50,
|
batch_size: 50,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,16 @@
|
|||||||
При малом значении нагрузка ниже, но обработка занимает больше времени.
|
При малом значении нагрузка ниже, но обработка занимает больше времени.
|
||||||
Рекомендуемое значение: 50.
|
Рекомендуемое значение: 50.
|
||||||
</ItemInput>
|
</ItemInput>
|
||||||
|
|
||||||
|
<ItemBool label="Отправка технических данных разработчику"
|
||||||
|
v-model="settings.items.pulse.heartbeat_enabled"
|
||||||
|
>
|
||||||
|
Чтобы улучшать продукт и быстрее помогать в поддержке, модуль отправляет разработчику
|
||||||
|
минимальный набор технических данных: домен магазина, имя бота и версии PHP, модуля и
|
||||||
|
OpenCart. <strong>Персональные данные покупателей и информация о заказах не
|
||||||
|
передаются.</strong> По умолчанию отправка отключена; включить или отключить её можно
|
||||||
|
в любой момент — на работу магазина это не влияет.
|
||||||
|
</ItemBool>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -103,6 +113,7 @@
|
|||||||
import {onMounted, ref} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import {useSettingsStore} from "@/stores/settings.js";
|
import {useSettingsStore} from "@/stores/settings.js";
|
||||||
import ItemInput from "@/components/Settings/ItemInput.vue";
|
import ItemInput from "@/components/Settings/ItemInput.vue";
|
||||||
|
import ItemBool from "@/components/Settings/ItemBool.vue";
|
||||||
import {apiGet} from "@/utils/http.js";
|
import {apiGet} from "@/utils/http.js";
|
||||||
import SettingsItem from "@/components/SettingsItem.vue";
|
import SettingsItem from "@/components/SettingsItem.vue";
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ HTML,
|
|||||||
|
|
||||||
'pulse' => [
|
'pulse' => [
|
||||||
'api_key' => '',
|
'api_key' => '',
|
||||||
|
'heartbeat_enabled' => false,
|
||||||
'batch_size' => 50,
|
'batch_size' => 50,
|
||||||
'max_attempts' => 3,
|
'max_attempts' => 3,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class TeleCartPulseService
|
|||||||
private TeleCartEvent $eventModel;
|
private TeleCartEvent $eventModel;
|
||||||
private ?string $apiKey;
|
private ?string $apiKey;
|
||||||
private ?PayloadSigner $heartbeatPayloadSigner;
|
private ?PayloadSigner $heartbeatPayloadSigner;
|
||||||
|
private bool $heartbeatEnabled;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
TelegramInitDataDecoder $initDataDecoder,
|
TelegramInitDataDecoder $initDataDecoder,
|
||||||
@@ -30,7 +31,8 @@ class TeleCartPulseService
|
|||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
TeleCartEvent $eventModel,
|
TeleCartEvent $eventModel,
|
||||||
?string $apiKey = null,
|
?string $apiKey = null,
|
||||||
?PayloadSigner $heartbeatPayloadSigner = null
|
?PayloadSigner $heartbeatPayloadSigner = null,
|
||||||
|
bool $heartbeatEnabled = false
|
||||||
) {
|
) {
|
||||||
$this->initDataDecoder = $initDataDecoder;
|
$this->initDataDecoder = $initDataDecoder;
|
||||||
$this->telegramService = $telegramService;
|
$this->telegramService = $telegramService;
|
||||||
@@ -39,6 +41,7 @@ class TeleCartPulseService
|
|||||||
$this->eventModel = $eventModel;
|
$this->eventModel = $eventModel;
|
||||||
$this->apiKey = $apiKey;
|
$this->apiKey = $apiKey;
|
||||||
$this->heartbeatPayloadSigner = $heartbeatPayloadSigner;
|
$this->heartbeatPayloadSigner = $heartbeatPayloadSigner;
|
||||||
|
$this->heartbeatEnabled = $heartbeatEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,6 +135,10 @@ class TeleCartPulseService
|
|||||||
*/
|
*/
|
||||||
public function handleHeartbeat(): void
|
public function handleHeartbeat(): void
|
||||||
{
|
{
|
||||||
|
if (! $this->heartbeatEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->cache->get('telecart_pulse_heartbeat')) {
|
if ($this->cache->get('telecart_pulse_heartbeat')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -193,6 +200,10 @@ class TeleCartPulseService
|
|||||||
*/
|
*/
|
||||||
private function pushHeartbeat(array $json): void
|
private function pushHeartbeat(array $json): void
|
||||||
{
|
{
|
||||||
|
$this->logger->debug('Pushing heartbeat', [
|
||||||
|
'data' => $json,
|
||||||
|
]);
|
||||||
|
|
||||||
$baseUri = rtrim(env('PULSE_API_HOST', 'http://localhost'), '/') . '/';
|
$baseUri = rtrim(env('PULSE_API_HOST', 'http://localhost'), '/') . '/';
|
||||||
|
|
||||||
$client = new Client([
|
$client = new Client([
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class TeleCartPulseServiceProvider extends ServiceProvider
|
|||||||
$this->container->singleton(TeleCartPulseService::class, function (Container $app) {
|
$this->container->singleton(TeleCartPulseService::class, function (Container $app) {
|
||||||
$heartbeatSecret = $app->getConfigValue('pulse.heartbeat_secret') ?? env('PULSE_HEARTBEAT_SECRET');
|
$heartbeatSecret = $app->getConfigValue('pulse.heartbeat_secret') ?? env('PULSE_HEARTBEAT_SECRET');
|
||||||
$heartbeatSigner = $heartbeatSecret ? new PayloadSigner($heartbeatSecret) : null;
|
$heartbeatSigner = $heartbeatSecret ? new PayloadSigner($heartbeatSecret) : null;
|
||||||
|
$heartbeatEnabled = (bool) $app->getConfigValue('pulse.heartbeat_enabled');
|
||||||
|
|
||||||
return new TeleCartPulseService(
|
return new TeleCartPulseService(
|
||||||
$app->get(TelegramInitDataDecoder::class),
|
$app->get(TelegramInitDataDecoder::class),
|
||||||
@@ -31,6 +32,7 @@ class TeleCartPulseServiceProvider extends ServiceProvider
|
|||||||
$app->get(TeleCartEvent::class),
|
$app->get(TeleCartEvent::class),
|
||||||
$app->getConfigValue('pulse.api_key'),
|
$app->getConfigValue('pulse.api_key'),
|
||||||
$heartbeatSigner,
|
$heartbeatSigner,
|
||||||
|
$heartbeatEnabled,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user