diff --git a/evennia/server/portal/portalsessionhandler.py b/evennia/server/portal/portalsessionhandler.py index 8c24cb655..54827931f 100644 --- a/evennia/server/portal/portalsessionhandler.py +++ b/evennia/server/portal/portalsessionhandler.py @@ -268,6 +268,7 @@ class PortalSessionHandler(SessionHandler): data (dict): The session sync data. """ + session.at_login() session.load_sync_data(data) def server_session_sync(self, serversessions, clean=True): diff --git a/evennia/server/portal/webclient.py b/evennia/server/portal/webclient.py index df8db95c5..36eb80c6a 100644 --- a/evennia/server/portal/webclient.py +++ b/evennia/server/portal/webclient.py @@ -42,26 +42,38 @@ class WebSocketClient(Protocol, Session): client_address = client_address[0] if client_address else None self.init_session("websocket", client_address, self.factory.sessionhandler) - def validationMade(self): + def get_browser_session(self): """ - This is called from the (modified) txws websocket library when - the ws handshake and validation has completed fully. + Get the Client browser session (used for auto-login based on browser session) + + Returns: + csession (ClientSession): This is a django-specific internal representation + of the browser session. """ - try: self.csessid = self.transport.location.split("?", 1)[1] except IndexError: # this may happen for custom webclients not caring for the # browser session. self.csessid = None + return None if self.csessid: - csession = _CLIENT_SESSIONS(session_key=self.csessid) - uid = csession and csession.get("logged_in", False) - if uid: - # the client session is already logged in. - self.uid = uid - self.logged_in = True + return _CLIENT_SESSIONS(session_key=self.csessid) + + def validationMade(self): + """ + This is called from the (modified) txws websocket library when + the ws handshake and validation has completed fully. + + """ + csession = self.get_browser_session() + uid = csession and csession.get("webclient_authenticated_uid", None) + print("In validationMade csession uid=", uid) + if uid: + # the client session is already logged in. + self.uid = uid + self.logged_in = True # watch for dead links self.transport.setTcpKeepAlive(1) @@ -78,6 +90,14 @@ class WebSocketClient(Protocol, Session): """ self.data_out(text=((reason or "",), {})) + + csession = self.get_client_session() + + if csession: + print("In disconnect: csession uid=%s" % csession.get("webclient_authenticated_uid", None)) + #csession["webclient_authenticated_uid"] = None + #csession.save() + self.logged_in = False self.connectionLost(reason) def connectionLost(self, reason): @@ -90,6 +110,7 @@ class WebSocketClient(Protocol, Session): reason (str): Motivation for the lost connection. """ + print("In connectionLost of webclient") self.sessionhandler.disconnect(self) self.transport.close() @@ -116,6 +137,13 @@ class WebSocketClient(Protocol, Session): """ return self.transport.write(line) + def at_login(self): + csession = self.get_browser_session() + print("Weblient at_login. Session: %s" % csession.session_key) + if csession: + csession["webclient_authenticated_uid"] = self.uid + csession.save() + def data_in(self, **kwargs): """ Data User > Evennia. diff --git a/evennia/web/webclient/views.py b/evennia/web/webclient/views.py index 2d1269947..d2faf78e2 100644 --- a/evennia/web/webclient/views.py +++ b/evennia/web/webclient/views.py @@ -19,25 +19,33 @@ def _shared_login(request): """ csession = request.session account = request.user - sesslogin = csession.get("logged_in", None) + # these can have 3 values: + # None - previously unused (auto-login) + # False - actively logged out (don't auto-login) + # - logged in User/Account id + website_uid = csession.get("website_authenticated_uid", None) + webclient_uid = csession.get("webclient_authenticated_uid", None) + print("webclient website_uid=%s, webclient_uid=%s, session_key=%s" % (website_uid, webclient_uid, csession.session_key)) # check if user has authenticated to website if csession.session_key is None: # this is necessary to build the sessid key + print("Webclient created a new browser session key") csession.save() - elif account.is_authenticated(): - if not sesslogin: - # User has already authenticated to website - csession["logged_in"] = account.id - elif sesslogin: + + if webclient_uid: # The webclient has previously registered a login to this browser_session - account = AccountDB.objects.get(id=sesslogin) - try: - # calls our custom authenticate in web/utils/backends.py - account = authenticate(autologin=account) - login(request, account) - except AttributeError: - logger.log_trace() + if not account.is_authenticated(): + # not logged into website + if website_uid is None: + account = AccountDB.objects.get(id=webclient_uid) + try: + # calls our custom authenticate in web/utils/backends.py + account = authenticate(autologin=account) + login(request, account) + csession["website_authenticated_uid"] = webclient_uid + except AttributeError: + logger.log_trace() def webclient(request): diff --git a/evennia/web/website/views.py b/evennia/web/website/views.py index d7930cd74..367d7b850 100644 --- a/evennia/web/website/views.py +++ b/evennia/web/website/views.py @@ -28,23 +28,39 @@ def _shared_login(request): """ csession = request.session account = request.user - sesslogin = csession.get("logged_in", None) + # these can have 3 values: + # None - previously unused (auto-login) + # False - actively logged out (don't auto-login) + # - logged in User/Account id + website_uid = csession.get("website_authenticated_uid", None) + webclient_uid = csession.get("webclient_authenticated_uid", None) + print("website website_uid=%s, webclient_uid=%s, session_key=%s" % (website_uid, webclient_uid, csession.session_key)) if csession.session_key is None: # this is necessary to build the sessid key + print("Website created a new browser session key") csession.save() - elif account.is_authenticated(): - if not sesslogin: - csession["logged_in"] = account.id - elif sesslogin: - # The webclient has previously registered a login to this csession - account = AccountDB.objects.get(id=sesslogin) - try: - # calls our custom authenticate, in web/utils/backend.py - authenticate(autologin=account) - login(request, account) - except AttributeError: - logger.log_trace() + + if account.is_authenticated(): + # Logged into website + if not website_uid: + # fresh website login (just from login page) + csession["website_authenticated_uid"] = account.id + if webclient_uid is None: + # auto-login web client + csession["webclient_authenticated_uid"] = account.id + + elif webclient_uid: + # Not logged into website, but logged into webclient + if not website_uid: + csession["website_authenticated_uid"] = account.id + account = AccountDB.objects.get(id=webclient_uid) + try: + # calls our custom authenticate, in web/utils/backend.py + authenticate(autologin=account) + login(request, account) + except AttributeError: + logger.log_trace() def _gamestats():