Search code examples
flaskflask-socketioflask-session

Flask SocketI) need to detect duplicate connections on opening new tab


I need to detect the duplicate session when user opens a new tab. Since I am using it for survey, I am not having any of the user's data. I am working on anonymous users.

Reading through documentation and various other thread I understood that I need to send client a session data which will be a uuid and check if the user is already authenticated for new connection.

My code is below -

from flask import Flask, render_template, session
from flask_session import Session
from flask_socketio import SocketIO, send, emit
from flask_login import LoginManager, UserMixin, current_user, login_user, logout_user, AnonymousUserMixin
import time, json, uuid, os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'top-secret!'
app.config['SESSION_TYPE'] = 'filesystem'
login_manager = LoginManager(app)
login_manager.init_app(app)
Session(app)
socketio = SocketIO(app, cors_allowed_origins="*", logger=True, manage_session=False)


class User(UserMixin, object):
    def __init__(self, id=None):
        self.id = id

@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)


time_now = 0
msg = "Hello User. Please wait other users to join. Survey will start once minimum users will join. Max waiting time " \
      "is 5 min "

# connected_msg_json = json.dumps(connected_msg, indent=4)
client_count = 0


@socketio.on('message')
def handle_message(msg):
    print("Connected with the client with data " + msg)


@socketio.on('connect')
def test_connect():
    print("Connected")
    f = open('data.json')
    data = json.load(f)
    minUserCount = data['minimumNoOfUser']
    global client_count, time_now
    if current_user.is_authenticated:
        pass
    else:
        client_count += 1
        login_user(User(id=uuid.uuid1()))
    if client_count == 0:
        time_now = int(time.time())

    print("Total no of connected client " + str(client_count))
    print("About to send the time when first user connected " + str(time_now))
    send(time_now)
    if client_count > minUserCount:
        send("Continue", broadcast=True)


@socketio.on('disconnect')
def test_disconnect():
    print('Client disconnected')
    logout_user()
    global client_count
    client_count -= 1
    print("Total no of connected client " + str(client_count))

Since I need to make sure that survey opens when there are minimum no of unique users, I decided to login the users upon connection. And if the user is already authenticated then I believe it means it's the new connection via tab.

Now I am not sure if my code is okay but the packages are incorrect or both. I have tried to resolved the error but I am stuck with this error -

ImportError: cannot import name 'ContextVar' from 'werkzeug.local' (/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/werkzeug/local.py)

This appears when I put line

app.config['SESSION_TYPE'] = 'filesystem'

else I get different error about secret key not being set.

My requirements.txt are:

Flask==2.0.2
Flask-Cors==3.0.10
Flask-SocketIO==4.3.1
gevent==21.8.0
gevent-websocket==0.10.1
greenlet==1.1.2
gunicorn==20.1.0
python-engineio==3.13.2
python-socketio==4.6.0
simple-websocket==0.5.0
websocket-client==1.2.1
websockets==10.1
Werkzeug==0.14.1


Solution

  • you need to update werkzeug to 2.0 +