Skip to content

Commit

Permalink
Keep an extra file in ~/.cache/lutris when in the process of logging …
Browse files Browse the repository at this point in the history
…in with WebConnectDialog; is_authenticated() is then false when this file is present, so even though we have cookies at this time, Lutris won't think we're already authenticated.

This means if you just close out of the WebConnectDialog, you are not considered to be logged in anyway- this extra file remains in that case.

Should help with #5406
  • Loading branch information
danieljohnson2 committed May 4, 2024
1 parent f3218bd commit 6fc1684
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 4 deletions.
11 changes: 10 additions & 1 deletion lutris/gui/dialogs/webconnect_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import os
from gettext import gettext as _
from typing import TYPE_CHECKING

import gi

if TYPE_CHECKING:
from lutris.services.base import OnlineService

try:
gi.require_version("WebKit2", "4.1")
except ValueError:
Expand All @@ -19,8 +23,11 @@
class WebConnectDialog(ModalDialog):
"""Login form for external services"""

def __init__(self, service, parent=None):
def __init__(self, service: "OnlineService", parent=None):
service.is_login_in_progress = True

self.context = WebKit2.WebContext.new()

if "http_proxy" in os.environ:
proxy = WebKit2.NetworkProxySettings.new(os.environ["http_proxy"])
self.context.set_network_proxy_settings(WebKit2.NetworkProxyMode.CUSTOM, proxy)
Expand Down Expand Up @@ -79,12 +86,14 @@ def on_navigation(self, widget, load_event):
resource = widget.get_main_resource()
resource.get_data(None, self._get_response_data_finish, None)
else:
self.service.is_login_in_progress = False
self.service.login_callback(url)
self.destroy()
return True

def _get_response_data_finish(self, resource, result, user_data=None):
html_response = resource.get_data_finish(result)
self.service.is_login_in_progress = False
self.service.login_callback(html_response)
self.destroy()

Expand Down
2 changes: 1 addition & 1 deletion lutris/gui/widgets/sidebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def service_reloaded_cb(self, error):
if error:
if isinstance(error, AuthTokenExpiredError):
self.service.logout()
self.service.login(parent=self.get_toplevel())
self.service.login(parent=self.get_toplevel()) # login will trigger reload if successful
else:
display_error(error, parent=self.get_toplevel())
schedule_at_idle(self.enable_refresh_button, delay_seconds=2.0)
Expand Down
26 changes: 25 additions & 1 deletion lutris/services/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import shutil
from gettext import gettext as _
from pathlib import Path
from typing import List

from gi.repository import Gio
Expand Down Expand Up @@ -406,6 +407,7 @@ class OnlineService(BaseService):
cache_path = NotImplemented
requires_login_page = False

login_url = NotImplemented
login_window_width = 390
login_window_height = 500
login_user_agent = DEFAULT_USER_AGENT
Expand All @@ -431,9 +433,31 @@ def login(self, parent=None):
dialog = WebConnectDialog(self, parent)
dialog.run()

@property
def is_login_in_progress(self) -> bool:
"""Set to true if the login process is underway; the credential files make be created at this
time, but that does not count as 'authenticated' until the login process is over. This is used
by WebConnectDialog since it creates its cookies before the login is actually complete.
This is recorded with a file in ~/.cache/lutris so it will persist across Lutris
restarted, just as the credentials themselves do. For this reason, we need to allow
the user to login again even when a login is in progress."""
return self._get_login_in_progress_path().exists()

@is_login_in_progress.setter
def is_login_in_progress(self, in_progress: bool) -> None:
path = self._get_login_in_progress_path()
if in_progress:
path.touch()
else:
path.unlink(missing_ok=True)

def _get_login_in_progress_path(self) -> Path:
return Path(os.path.join(settings.CACHE_DIR, f"{self.name}-login-in-progress"))

def is_authenticated(self):
"""Return whether the service is authenticated"""
return all(system.path_exists(path) for path in self.credential_files)
return not self.is_login_in_progress and all(system.path_exists(path) for path in self.credential_files)

def wipe_game_cache(self):
"""Wipe the game cache, allowing it to be reloaded"""
Expand Down
2 changes: 1 addition & 1 deletion lutris/services/humblebundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def login(self, parent=None):
if dialog.cookies_content:
with open(self.cookies_path, "w", encoding="utf-8") as cookies_file:
cookies_file.write(dialog.cookies_content)
self.login_callback(None)
SERVICE_LOGIN.fire(self)
else:
self.logout()
else:
Expand Down

0 comments on commit 6fc1684

Please sign in to comment.