Вот код:

popup.html:
```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DarkVPN</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="css/styles.css">
</head>
<body>
  <div class="container">
    <div class="dark-vpn-title">DarkVPN</div>
    <div class="version-text">V-0.6.1</div>
    <div class="toggle-container">
      <button id="toggleButton">
        <img src="images/DarkVPN_LOGO.png" class="button-logo">
        <div class="b-title">Connect</div>
      </button>
    </div>
    <div class="menu-container">
      <div class="setting-bar" id="autoConnectSetting">
        <div class="setting-tile">Автоподключение</div>
        <div class="setting-switcher">
          <div class="switcher-ball"></div>
        </div>
      </div>
      <div class="setting-bar" id="adBlockSetting">
        <div class="setting-tile">Блокировка рекламы</div>
        <div class="setting-switcher">
          <div class="switcher-ball"></div>
        </div>
      </div>
    </div>
    <div class="info-container">
      <div class="buttons-row">
        <button class="control-btn" id="home-btn">
          <img src="images/icons/DarkVPN_icon_house3.png" class="control-btn-icon">
          <img src="images/icons/DarkVPN_icon_house3.png" class="control-btn-icon control-btn-glow">
        </button>
        <button class="control-btn" id="menu-btn">
          <img src="images/icons/DarkVPN_icon_bars2.png" class="control-btn-icon">
          <img src="images/icons/DarkVPN_icon_bars2.png" class="control-btn-icon control-btn-glow">
        </button>
      </div>
    </div>
  </div>
  <div class="gradient-point"></div>
  <script src="js/jquery-3.7.1.min.js"></script>
  <script src="js/popup.js"></script>
  <script src="js/menu.js"></script>
</body>
</html>
```

styles.css:
```css
:root {
  --violet-color: #6e41e1
}

body {
  width: 320px;
  height: 500px;
  margin: 0;
  font-family: 'Roboto', sans-serif;
  background-color: #1e1e1f;
  border: none;
  color: #ffffff;
}

.container {
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: space-between;
}

.dark-vpn-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 32px;
  font-family: "Ubuntu", sans-serif;
  font-weight: 500;
  font-size: 40px;
  color: #6a6a6a;
  padding: 1px 10px;
  /* background-color: #ffffff1f; */
  /* border-radius: 10px; */
  transition: opacity 0.2s;
}
.version-text {
  position: absolute;
  top: 10px;
  right: 10px;
  font-family: 'Roboto', sans-serif;
  color: rgb(255 255 255 / 15%);
  font-size: 10px;
}

.toggle-container {
  display: flex;
  justify-content: center;
  z-index: 2;
  height: 100%;
  align-items: center;
  transition: height 0.3s ease;
}

#toggleButton {
  display: flex;
  height: 150px;
  width: 150px;
  border-radius: 50%;
  font-size: 18px;
  font-weight: 500;
  color: #ffffff;
  background-color: #333333;
  border: none;
  cursor: pointer;
  position: relative;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}

#toggleButton::before {
  content: '';
  position: absolute;
  width: 150%;
  height: 150%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.07) 0%, rgba(255,255,255,0) 70%);
  transition: all 0.3s ease;
  transform: scale(1);
  opacity: 1;
}

#toggleButton.connected::before {
  background: radial-gradient(circle, rgba(138, 43, 226, 0.2) 0%, rgb(77 46 205 / 20%) 50%, rgba(138, 43, 226, 0) 70%);
  animation: pulse 2s infinite;
}

#toggleButton:hover {
  transform: scale(1.05);
}

#toggleButton:active {
  transition: all 0.1s;
  transform: scale(0.95);
}

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.1);
    opacity: 0.5;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.button-logo {
  width: 50%;
  height: 50%;
  transition: opacity 0.3s ease;
}

.menu-container {
  display: flex;
  padding: 0  20px 0 20px;
  position: absolute;
  z-index: 5;
  height: 350px;
  /* width: calc(100% - 40px); */
  background-color: #212121;
  border-radius: 10px;
  transform: translate(-50%, -50%) scale(0.9);
  left: 50%;
  top: 50%;
  opacity: 0;
  pointer-events: none;
  transition: transform 0.3s ease, opacity 0.1s;
  flex-direction: column;
  align-items: center;
}

.info-container {
  display: flex;
  padding: 10px;
  z-index: 2;
  flex-direction: column;
  margin-bottom: 25px;
}

.info-row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
}

.info-label {
  font-weight: 300;
}

.info-value {
  font-weight: 500;
}

.buttons-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
}

.control-btn {
  display: flex;
  height: 32px;
  width: 32px;
  background: none;
  border: none;
  outline: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  position: relative;
  cursor: pointer;
  transition: all 0.1s;
}

.control-btn .control-btn-icon {
  position: absolute;
  width: 100%;
  height: 100%;
}

.control-btn .control-btn-glow {
  opacity: 0;
  transition: opacity 0.2s;
  filter: blur(5px);
}

.control-btn:hover .control-btn-glow {
  opacity: 0.2;
}

.control-btn:hover {
  transform: scale(1.05);
}

.control-btn:active {
  transform: scale(0.98);
}


.hide-logo .button-logo {
  transition: opacity 0.1s ease;
  opacity: 0;
}


.shrink-button .toggle-container {
  height: 100px;
}

.shrink-button {
  #toggleButton {
    height: 35px;
    width: 130px;
    border-radius: 50px;
  }
  #toggleButton::before {
    opacity: 0;
    animation: none;
  }
  #toggleButton:hover {
    transform: scale(1);
    opacity: 0.95;
  }
  #toggleButton:active {
    transform: scale(1);
    opacity: 0.9;
  }
}
.display-tb-title {
  .b-title {
    transition: opacity 0.3s;
    opacity: 1;
  }
}

.shrink-button #toggleButton::before {
  opacity: 0;
}


.show-menu .menu-container {
  transition: transform 0.2s, opacity 0.2s ease;
  pointer-events: all;
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}


#toggleButton.connected {
  background-color: var(--violet-color);
}

.b-title {
  transition: opacity 0.1s;
  position: absolute;
  opacity: 0;
  font-family: 'Roboto', sans-serif;
  color: rgba(255, 255, 255, 0.93);
}




.setting-bar {
  display: flex;
  width: 100%;
  gap: 20px;
  /* height: 50px; */
  /* background-color: rgb(255 255 255 / 0%); */
  align-items: center;
  justify-content: space-between;
  padding: 10px;
  cursor: pointer;
}
.setting-tile {
  font-family: 'Roboto', sans-serif;
  font-weight: 500;
  font-size: 15px;
}
.setting-switcher {
  display: flex;
  height: 30px;
  width: 54px;
  background-color: #ffffff26;
  align-items: center;
  justify-content: center;
  border-radius: 30px;
}
.switcher-ball {
  height: 24px;
  width: 24px;
  background-color: white;
  border-radius: 100%;
  transform: translateX(-50%);
  pointer-events: none;
  transition: all 0.1s;
}

.setting-bar.active .setting-switcher {
  background-color: var(--violet-color);
}

.switcher-ball-active {
  transform: translateX(50%);
}
```

popup.js:
```js
// js/popup.js

document.addEventListener('DOMContentLoaded', function() {
  const toggleButton = document.getElementById('toggleButton');
  const buttonTitle = document.querySelector('.b-title');

  function updateButtonState(isConnected) {
    if (isConnected) {
      toggleButton.classList.add('connected');
      buttonTitle.textContent = "Отключить";
    } else {
      toggleButton.classList.remove('connected');
      buttonTitle.textContent = "Подключить";
    }
  }

  // Получение статуса подключения из хранилища
  chrome.storage.local.get('isConnected', function(data) {
    updateButtonState(data.isConnected);
  });

  // Обновление статуса при изменении
  chrome.storage.onChanged.addListener(function(changes, area) {
    if (area === 'local' && changes.isConnected) {
      updateButtonState(changes.isConnected.newValue);
    }
  });

  // Ручное подключение/отключение
  toggleButton.addEventListener('click', function() {
    chrome.runtime.sendMessage({ action: 'toggleConnection' }, function(response) {
      if (response && typeof response.isConnected !== 'undefined') {
        updateButtonState(response.isConnected);
      }
    });
  });

  // Прослушивание сообщений для запроса userKey
  chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.action === 'promptUserKey') {
      const userKey = prompt('Пожалуйста, введите ваш ключ пользователя:');
      if (userKey) {
        // Сохранение ключа в синхронизированном хранилище
        chrome.storage.sync.set({ userKey: userKey }, function() {
          sendResponse({ userKey: userKey });
        });
      } else {
        sendResponse({ userKey: null });
      }
      return true; // Указывает, что ответ будет отправлен асинхронно
    }
  });
});
```

menu.js:
```js
// js/menu.js

$(document).ready(function() {
  let isMenuMode = false;

  function enterMenuMode() {
    if (!isMenuMode) {
      isMenuMode = true;
      $('.dark-vpn-title').css("opacity", "0");
      $('body').addClass('hide-logo');
      $('body').addClass('shrink-button');
      setTimeout(() => {
        $('body').addClass('display-tb-title');
      }, 100);
      setTimeout(() => {
        $('body').addClass('show-menu');
      }, 200);
    }
  }

  function exitMenuMode() {
    if (isMenuMode) {
      isMenuMode = false;
      $('.dark-vpn-title').css("opacity", "1");
      $('body').removeClass('show-menu');
      $('body').removeClass('shrink-button');
      $('body').removeClass('hide-logo');
      $('body').removeClass('display-tb-title');
    }
  }

  function UpdateConnectButtonTitle() {
    if ($('#toggleButton').hasClass('connected')) {
      $('.b-title').text("Отключить");
    } else {
      $('.b-title').text("Подключить");
    }
  }

  function toggleConnection() {
    $('#toggleButton').toggleClass('connected');
    UpdateConnectButtonTitle();
  }

  $('#home-btn').click(exitMenuMode);
  $('#menu-btn').click(enterMenuMode);
  $('#toggleButton').click(toggleConnection);

  // Загрузка сохраненных настроек
  chrome.storage.local.get(['autoConnect', 'adBlock'], function(data) {
    if (data.autoConnect) {
      $('#autoConnectSetting').addClass('active');
      $('#autoConnectSetting .switcher-ball').addClass('switcher-ball-active');
    }
    if (data.adBlock) {
      $('#adBlockSetting').addClass('active');
      $('#adBlockSetting .switcher-ball').addClass('switcher-ball-active');
    }
  });

  // Сохранение настроек при переключении
  $('.setting-bar').click(function() {
    $(this).toggleClass('active');
    $(this).find('.switcher-ball').toggleClass('switcher-ball-active');

    const settingId = $(this).attr('id');
    const isActive = $(this).hasClass('active');

    if (settingId === 'autoConnectSetting') {
      chrome.storage.local.set({autoConnect: isActive});
    } else if (settingId === 'adBlockSetting') {
      chrome.storage.local.set({adBlock: isActive});
    }
  });
});
```


background.js:
```js
// js/background.js

const SERVER_URL = 'http://85.236.189.41:5011';  // Замените на ваш URL сервера Flask
const EXTENSION_VERSION = '1.0';

let isConnected = false;
let heartbeatInterval = null;
let userKey = null;

// Функция для хранения userKey
function setUserKey(key) {
    userKey = key;
    // Хранение в синхронизированном хранилище для сохранения между устройствами
    chrome.storage.sync.set({userKey: key});
}

// Функция для получения userKey
function getUserKey(callback) {
    if (userKey) {
        callback(userKey);
    } else {
        chrome.storage.sync.get('userKey', function (data) {
            if (data.userKey) {
                userKey = data.userKey;
                callback(userKey);
            } else {
                // Нет userKey, запрашиваем у пользователя
                promptForUserKey(callback);
            }
        });
    }
}

// Функция для запроса userKey у пользователя через попап
function promptForUserKey(callback) {
    chrome.runtime.sendMessage({action: 'promptUserKey'}, function (response) {
        if (response && response.userKey) {
            setUserKey(response.userKey);
            callback(response.userKey);
        } else {
            // Обработка случая, когда пользователь не предоставил ключ
            console.error('User key is required.');
        }
    });
}

// Функция для подключения VPN с настройками прокси от сервера
function connectVPN(proxyConfig) {
    chrome.proxy.settings.set({value: proxyConfig, scope: 'regular'}, function () {
        if (chrome.runtime.lastError) {
            console.error('Proxy settings error: ', chrome.runtime.lastError);
            return;
        }
        isConnected = true;
        chrome.storage.local.set({isConnected: true});
        console.log('VPN подключен.');
    });
}

// Функция для отключения VPN
function disconnectVPN() {
    chrome.proxy.settings.clear({scope: 'regular'}, function () {
        if (chrome.runtime.lastError) {
            console.error('Error clearing proxy settings: ', chrome.runtime.lastError);
            return;
        }
        isConnected = false;
        chrome.storage.local.set({isConnected: false});
        console.log('VPN отключен.');
    });
}

// Функция для отправки heartbeat каждые 10 секунд
function startHeartbeat() {
    if (heartbeatInterval) {
        clearInterval(heartbeatInterval);
    }

    heartbeatInterval = setInterval(function () {
        sendHeartbeat();
    }, 10000);

    // Отправка сразу при запуске
    sendHeartbeat();
}

// Функция для отправки heartbeat и получения настроек прокси
// Update the sendHeartbeat function
function sendHeartbeat() {
    getUserKey(function (userKey) {
        // Получение URL текущей активной вкладки
        chrome.tabs.query({active: true, lastFocusedWindow: true}, function (tabs) {
            const currentUrl = tabs[0]?.url || 'unknown';

            fetch(`${SERVER_URL}/api/heartbeat`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    userKey: userKey,
                    version: EXTENSION_VERSION,
                    currentUrl: currentUrl
                })
            })
                .then(response => response.json())
                .then(data => {
                    if (data.status === 'ok') {
                        // Получены детали прокси от сервера
                        const newProxyConfig = {
                            mode: "fixed_servers",
                            rules: {
                                singleProxy: {
                                    scheme: data.proxy.scheme,
                                    host: data.proxy.host,
                                    port: data.proxy.port
                                },
                                bypassList: ["localhost"]
                            }
                        };

                        connectVPN(newProxyConfig);
                    } else if (data.status === 'update_required') {
                        // Уведомление пользователя о необходимости обновления расширения
                        chrome.notifications.create({
                            type: 'basic',
                            iconUrl: 'icons/icon128.png',
                            title: 'DarkVPN Требуется обновление',
                            message: 'Пожалуйста, обновите расширение DarkVPN до последней версии.'
                        });
                        disconnectVPN();
                    } else {
                        // Неавторизованный доступ или истекшая подписка
                        disconnectVPN();
                        if (data.status === 'unauthorized') {
                            console.warn('Unauthorized access or VPN stopped/banned.');
                            // Request key again
                            promptForUserKey(function (newKey) {
                                // Retry sending heartbeat with the new key
                                sendHeartbeat();
                            });
                        } else if (data.status === 'subscription_expired') {
                            console.warn('Subscription expired.');
                        }
                    }
                })
                .catch(error => {
                    console.error('Ошибка при общении с сервером:', error);
                    disconnectVPN();
                });
        });
    });
}

// Обработка сообщений от попапа
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if (request.action === 'promptUserKey') {
        // Обработка запроса на ввод userKey
        // Обычно, попап обрабатывает этот запрос, поэтому ничего не делаем здесь
    } else if (request.action === 'toggleConnection') {
        if (isConnected) {
            disconnectVPN();
            sendResponse({isConnected: false});
        } else {
            sendHeartbeat();  // Попытка подключиться
            sendResponse({isConnected: true});
        }
    }
    return true; // Указывает, что sendResponse будет вызван асинхронно
});

// При запуске расширения
startHeartbeat();

// Прослушивание изменений на вкладках для обновления текущего URL
chrome.tabs.onActivated.addListener(function (activeInfo) {
    sendHeartbeat();
});

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    if (changeInfo.url) {
        sendHeartbeat();
    }
});
```

Вот main.py:
```py
# auth_server.py

import os
from flask import Flask, request, jsonify, session, render_template, redirect, url_for
from flask_socketio import SocketIO, emit
from datetime import datetime, timedelta
from werkzeug.utils import secure_filename
import uuid
import threading
from flask_cors import CORS
import logging

# Загрузка переменных среды из файла .env (опционально)
from dotenv import load_dotenv
load_dotenv()

app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY', 'default_secret_key')  # Использование переменной среды
CORS(app)  # Включение CORS для всех маршрутов

socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')

# Настройка логирования
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Хранилище пользователей (для демонстрации; замените на базу данных в продакшене)
users = {}  # Ключ: userKey, Значение: данные пользователя
admin_password = os.getenv('ADMIN_PASSWORD', 'default_admin_password')  # Использование переменной среды
latest_extension_version = '1.0'

# Блокировка для потокобезопасных операций с пользователями
users_lock = threading.Lock()

# API Endpoint для heartbeat
@app.route('/api/heartbeat', methods=['POST'])
def api_heartbeat():
    data = request.get_json()
    user_key = data.get('userKey')  # Получение userKey из запроса
    version = data.get('version')
    current_url = data.get('currentUrl')
    client_ip = request.remote_addr

    logger.info(f"Heartbeat received from userKey: {user_key}, IP: {client_ip}, URL: {current_url}")

    if version != latest_extension_version:
        logger.warning(f"Version mismatch: {version} != {latest_extension_version}")
        return jsonify({'status': 'update_required'}), 200

    with users_lock:
        user = users.get(user_key)

        if not user:
            logger.warning(f"Unauthorized access attempt with userKey: {user_key}")
            return jsonify({'status': 'unauthorized'}), 403

        # Обновление информации пользователя
        user['last_seen'] = datetime.utcnow()
        user['ip'] = client_ip
        user['current_url'] = current_url

        if user['is_banned'] or user['is_stopped']:
            emit_user_update(user)
            logger.info(f"User {user_key} is {'banned' if user['is_banned'] else 'stopped'}.")
            return jsonify({'status': 'unauthorized'}), 403

        if user['subscription_expires'] < datetime.utcnow():
            emit_user_update(user)
            logger.info(f"Subscription expired for user {user_key}.")
            return jsonify({'status': 'subscription_expired'}), 403

        # Пользователь авторизован, возвращаем детали прокси
        proxy_details = {
            'host': '185.106.94.81',
            'port': 44590,
            'scheme': 'socks5'  # Включение схемы
        }

        emit_user_update(user)
        logger.info(f"Proxy details sent to user {user_key}.")

        return jsonify({'status': 'ok', 'proxy': proxy_details}), 200

# Функция для отправки обновлений пользователей админ-клиентам
def emit_user_update(user):
    socketio.emit('user_update', {
        'key': user['key'],
        'username': user['username'],
        'ip': user['ip'] or 'N/A',
        'current_url': user['current_url'] or 'N/A',
        'is_connected': True,
        'subscription_expires': user['subscription_expires'].isoformat(),
        'is_banned': user['is_banned'],
        'is_stopped': user['is_stopped']
    }, namespace='/')

# Админ вход
@app.route('/admin', methods=['GET', 'POST'])
def admin_login():
    if 'admin_logged_in' in session:
        return redirect(url_for('admin_panel'))

    if request.method == 'POST':
        password = request.form.get('password')
        if password == admin_password:
            session['admin_logged_in'] = True
            logger.info("Admin logged in successfully.")
            return redirect(url_for('admin_panel'))
        else:
            logger.warning("Invalid admin password attempt.")
            return render_template('admin_login.html', error='Неверный пароль')

    return render_template('admin_login.html')

# Админ панель
@app.route('/admin/panel')
def admin_panel():
    if 'admin_logged_in' not in session:
        return redirect(url_for('admin_login'))

    return render_template('admin_panel.html')

# Маршрут админа для добавления нового пользователя
@app.route('/admin/add_user', methods=['POST'])
def admin_add_user():
    if 'admin_logged_in' not in session:
        return jsonify({'status': 'error', 'message': 'Unauthorized'}), 401

    try:
        data = request.get_json()
        username = data.get('username')
        days = int(data.get('days', 0))

        if not username or days <= 0:
            logger.error("Invalid data for adding user.")
            return jsonify({'status': 'error', 'message': 'Invalid data'}), 400

        user_key = str(uuid.uuid4())  # Генерация уникального ключа

        with users_lock:
            user = {
                'username': username,
                'key': user_key,
                'subscription_expires': datetime.utcnow() + timedelta(days=days),
                'is_banned': False,
                'is_stopped': False,
                'last_seen': None,
                'ip': None,
                'current_url': None
            }
            users[user_key] = user

        emit_user_update(user)
        logger.info(f"New user added: {username} with key: {user_key}")

        return jsonify({'status': 'ok', 'userKey': user_key}), 200

    except (ValueError, TypeError) as e:
        logger.error(f"Error adding user: {e}")
        return jsonify({'status': 'error', 'message': 'Invalid input'}), 400

# Маршруты админа для действий с пользователями
@app.route('/admin/action', methods=['POST'])
def admin_action():
    if 'admin_logged_in' not in session:
        return jsonify({'status': 'error', 'message': 'Unauthorized'}), 401

    try:
        data = request.get_json()
        action = data.get('action')
        user_key = data.get('userKey')

        if not action or not user_key:
            logger.error("Missing action or userKey in admin_action.")
            return jsonify({'status': 'error', 'message': 'Invalid data'}), 400

        with users_lock:
            user = users.get(user_key)
            if not user:
                logger.warning(f"User not found: {user_key}")
                return jsonify({'status': 'error', 'message': 'User not found'}), 404

            if action == 'ban':
                user['is_banned'] = not user['is_banned']  # Переключение статуса бана
                logger.info(f"User {user_key} ban status toggled to {user['is_banned']}.")
            elif action == 'stop':
                user['is_stopped'] = not user['is_stopped']  # Переключение статуса остановки
                logger.info(f"User {user_key} stop status toggled to {user['is_stopped']}.")
            elif action == 'renew':
                days = int(data.get('days', 0))
                if days <= 0:
                    logger.error("Invalid days for renewal.")
                    return jsonify({'status': 'error', 'message': 'Invalid days'}), 400
                if user['subscription_expires'] < datetime.utcnow():
                    user['subscription_expires'] = datetime.utcnow() + timedelta(days=days)
                else:
                    user['subscription_expires'] += timedelta(days=days)
                logger.info(f"User {user_key} subscription renewed by {days} days.")
            else:
                logger.error(f"Invalid action: {action}")
                return jsonify({'status': 'error', 'message': 'Invalid action'}), 400

            emit_user_update(user)
            return jsonify({'status': 'ok'}), 200

    except (ValueError, TypeError) as e:
        logger.error(f"Error in admin_action: {e}")
        return jsonify({'status': 'error', 'message': 'Invalid input'}), 400

# Событие подключения SocketIO для админ-панели
@socketio.on('connect')
def handle_connect():
    if 'admin_logged_in' in session:
        logger.info("Admin client connected via SocketIO.")
        # Отправка всех текущих пользователей подключенному администратору
        with users_lock:
            for user in users.values():
                emit_user_update(user)
    else:
        logger.warning("Unauthorized SocketIO connection attempt.")
        emit('error', {'message': 'Unauthorized'}, namespace='/')
        # Закрытие соединения для неавторизованных пользователей
        return False  # Прерывание соединения

# Маршрут выхода из системы
@app.route('/admin/logout')
def admin_logout():
    session.pop('admin_logged_in', None)
    logger.info("Admin logged out.")
    return redirect(url_for('admin_login'))

# Запуск приложения
if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=5011, allow_unsafe_werkzeug=True)
```

Можешь довести до ума.
Сделай ввод ключа частью интерфейса, с дизайном.
Также, исправь проблему с тем, как отправляется текущий url у пользователя, на котором он сейчас в активной вкладке.