Implement a setting for manual vs server login method

This commit is contained in:
Ryan Holmes
2018-03-18 00:46:53 -04:00
parent 49181dce2b
commit 53451dfaf6
7 changed files with 187 additions and 179 deletions

View File

@@ -6,5 +6,6 @@ __all__ = [
"pyfaDatabasePreferences",
"pyfaLoggingPreferences",
"pyfaEnginePreferences",
"pyfaEsiPreferences",
"pyfaStatViewPreferences"]

View File

@@ -1,148 +0,0 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
from gui.bitmap_loader import BitmapLoader
import gui.mainFrame
from service.settings import CRESTSettings
# noinspection PyPackageRequirements
from wx.lib.intctrl import IntCtrl
from service.esi import Esi
class PFCrestPref(PreferenceView):
title = "CREST"
def populatePanel(self, panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.settings = CRESTSettings.getInstance()
self.dirtySettings = False
dlgWidth = panel.GetParent().GetParent().ClientSize.width
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add(self.stTitle, 0, wx.ALL, 5)
self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.stInfo = wx.StaticText(panel, wx.ID_ANY,
"Please see the pyfa wiki on GitHub for information regarding these options.",
wx.DefaultPosition, wx.DefaultSize, 0)
self.stInfo.Wrap(dlgWidth - 50)
mainSizer.Add(self.stInfo, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
rbSizer = wx.BoxSizer(wx.HORIZONTAL)
self.rbMode = wx.RadioBox(panel, -1, "Mode", wx.DefaultPosition, wx.DefaultSize,
['Implicit', 'User-supplied details'], 1, wx.RA_SPECIFY_COLS)
self.rbServer = wx.RadioBox(panel, -1, "Server", wx.DefaultPosition, wx.DefaultSize,
['Tranquility', 'Singularity'], 1, wx.RA_SPECIFY_COLS)
self.rbMode.SetSelection(self.settings.get('mode'))
self.rbServer.SetSelection(self.settings.get('server'))
rbSizer.Add(self.rbMode, 1, wx.TOP | wx.RIGHT, 5)
rbSizer.Add(self.rbServer, 1, wx.ALL, 5)
self.rbMode.Bind(wx.EVT_RADIOBOX, self.OnModeChange)
self.rbServer.Bind(wx.EVT_RADIOBOX, self.OnServerChange)
mainSizer.Add(rbSizer, 1, wx.ALL | wx.EXPAND, 0)
timeoutSizer = wx.BoxSizer(wx.HORIZONTAL)
self.stTimout = wx.StaticText(panel, wx.ID_ANY, "Timeout (seconds):", wx.DefaultPosition, wx.DefaultSize, 0)
self.stTimout.Wrap(-1)
timeoutSizer.Add(self.stTimout, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.intTimeout = IntCtrl(panel, max=300000, limited=True, value=self.settings.get('timeout'))
timeoutSizer.Add(self.intTimeout, 0, wx.ALL, 5)
self.intTimeout.Bind(wx.lib.intctrl.EVT_INT, self.OnTimeoutChange)
mainSizer.Add(timeoutSizer, 0, wx.ALL | wx.EXPAND, 0)
detailsTitle = wx.StaticText(panel, wx.ID_ANY, "CREST client details", wx.DefaultPosition, wx.DefaultSize, 0)
detailsTitle.Wrap(-1)
detailsTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add(detailsTitle, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND, 5)
fgAddrSizer = wx.FlexGridSizer(2, 2, 0, 0)
fgAddrSizer.AddGrowableCol(1)
fgAddrSizer.SetFlexibleDirection(wx.BOTH)
fgAddrSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
self.stSetID = wx.StaticText(panel, wx.ID_ANY, "Client ID:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stSetID.Wrap(-1)
fgAddrSizer.Add(self.stSetID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.inputClientID = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientID'), wx.DefaultPosition,
wx.DefaultSize, 0)
fgAddrSizer.Add(self.inputClientID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.stSetSecret = wx.StaticText(panel, wx.ID_ANY, "Client Secret:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stSetSecret.Wrap(-1)
fgAddrSizer.Add(self.stSetSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.inputClientSecret = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientSecret'), wx.DefaultPosition,
wx.DefaultSize, 0)
fgAddrSizer.Add(self.inputClientSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.btnApply = wx.Button(panel, wx.ID_ANY, "Save Client Settings", wx.DefaultPosition, wx.DefaultSize, 0)
self.btnApply.Bind(wx.EVT_BUTTON, self.OnBtnApply)
mainSizer.Add(fgAddrSizer, 0, wx.EXPAND, 5)
mainSizer.Add(self.btnApply, 0, wx.ALIGN_RIGHT, 5)
self.ToggleProxySettings(self.settings.get('mode'))
panel.SetSizer(mainSizer)
panel.Layout()
def OnTimeoutChange(self, event):
self.settings.set('timeout', event.GetEventObject().GetValue())
def OnModeChange(self, event):
self.settings.set('mode', event.GetInt())
self.ToggleProxySettings(self.settings.get('mode'))
def OnServerChange(self, event):
self.settings.set('server', event.GetInt())
def OnBtnApply(self, event):
self.settings.set('clientID', self.inputClientID.GetValue().strip())
self.settings.set('clientSecret', self.inputClientSecret.GetValue().strip())
sEsi = Esi.getInstance()
sEsi.delAllCharacters()
def ToggleProxySettings(self, mode):
if mode:
self.stSetID.Enable()
self.inputClientID.Enable()
self.stSetSecret.Enable()
self.inputClientSecret.Enable()
else:
self.stSetID.Disable()
self.inputClientID.Disable()
self.stSetSecret.Disable()
self.inputClientSecret.Disable()
def getImage(self):
return BitmapLoader.getBitmap("eve", "gui")
PFCrestPref.register()

View File

@@ -0,0 +1,137 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
from gui.bitmap_loader import BitmapLoader
import gui.mainFrame
from service.settings import EsiSettings
# noinspection PyPackageRequirements
from wx.lib.intctrl import IntCtrl
from service.esi import Esi
class PFEsiPref(PreferenceView):
title = "EVE SSO"
def populatePanel(self, panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.settings = EsiSettings.getInstance()
self.dirtySettings = False
dlgWidth = panel.GetParent().GetParent().ClientSize.width
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add(self.stTitle, 0, wx.ALL, 5)
self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.stInfo = wx.StaticText(panel, wx.ID_ANY,
"Please see the pyfa wiki on GitHub for information regarding these options.",
wx.DefaultPosition, wx.DefaultSize, 0)
self.stInfo.Wrap(dlgWidth - 50)
mainSizer.Add(self.stInfo, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
rbSizer = wx.BoxSizer(wx.HORIZONTAL)
self.rbMode = wx.RadioBox(panel, -1, "Login Authentication Method", wx.DefaultPosition, wx.DefaultSize,
['Local Server', 'Manual'], 1, wx.RA_SPECIFY_COLS)
self.rbMode.SetItemToolTip(0, "This options starts a local webserver that the web application will call back to with information about the character login.")
self.rbMode.SetItemToolTip(1, "This option prompts users to copy and paste information from the web application to allow for character login. Use this if having issues with the local server.")
# self.rbServer = wx.RadioBox(panel, -1, "Server", wx.DefaultPosition, wx.DefaultSize,
# ['Tranquility', 'Singularity'], 1, wx.RA_SPECIFY_COLS)
self.rbMode.SetSelection(self.settings.get('loginMode'))
# self.rbServer.SetSelection(self.settings.get('server'))
rbSizer.Add(self.rbMode, 1, wx.TOP | wx.RIGHT, 5)
# rbSizer.Add(self.rbServer, 1, wx.ALL, 5)
self.rbMode.Bind(wx.EVT_RADIOBOX, self.OnModeChange)
# self.rbServer.Bind(wx.EVT_RADIOBOX, self.OnServerChange)
mainSizer.Add(rbSizer, 1, wx.ALL | wx.EXPAND, 0)
timeoutSizer = wx.BoxSizer(wx.HORIZONTAL)
# self.stTimout = wx.StaticText(panel, wx.ID_ANY, "Timeout (seconds):", wx.DefaultPosition, wx.DefaultSize, 0)
# self.stTimout.Wrap(-1)
#
# timeoutSizer.Add(self.stTimout, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
# self.intTimeout = IntCtrl(panel, max=300000, limited=True, value=self.settings.get('timeout'))
# timeoutSizer.Add(self.intTimeout, 0, wx.ALL, 5)
# self.intTimeout.Bind(wx.lib.intctrl.EVT_INT, self.OnTimeoutChange)
#
# mainSizer.Add(timeoutSizer, 0, wx.ALL | wx.EXPAND, 0)
# detailsTitle = wx.StaticText(panel, wx.ID_ANY, "CREST client details", wx.DefaultPosition, wx.DefaultSize, 0)
# detailsTitle.Wrap(-1)
# detailsTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
#
# mainSizer.Add(detailsTitle, 0, wx.ALL, 5)
# mainSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
# wx.EXPAND, 5)
# fgAddrSizer = wx.FlexGridSizer(2, 2, 0, 0)
# fgAddrSizer.AddGrowableCol(1)
# fgAddrSizer.SetFlexibleDirection(wx.BOTH)
# fgAddrSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
#
# self.stSetID = wx.StaticText(panel, wx.ID_ANY, "Client ID:", wx.DefaultPosition, wx.DefaultSize, 0)
# self.stSetID.Wrap(-1)
# fgAddrSizer.Add(self.stSetID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
#
# self.inputClientID = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientID'), wx.DefaultPosition,
# wx.DefaultSize, 0)
#
# fgAddrSizer.Add(self.inputClientID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
#
# self.stSetSecret = wx.StaticText(panel, wx.ID_ANY, "Client Secret:", wx.DefaultPosition, wx.DefaultSize, 0)
# self.stSetSecret.Wrap(-1)
#
# fgAddrSizer.Add(self.stSetSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
#
# self.inputClientSecret = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientSecret'), wx.DefaultPosition,
# wx.DefaultSize, 0)
#
# fgAddrSizer.Add(self.inputClientSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
#
# self.btnApply = wx.Button(panel, wx.ID_ANY, "Save Client Settings", wx.DefaultPosition, wx.DefaultSize, 0)
# self.btnApply.Bind(wx.EVT_BUTTON, self.OnBtnApply)
#
# mainSizer.Add(fgAddrSizer, 0, wx.EXPAND, 5)
# mainSizer.Add(self.btnApply, 0, wx.ALIGN_RIGHT, 5)
# self.ToggleProxySettings(self.settings.get('loginMode'))
panel.SetSizer(mainSizer)
panel.Layout()
def OnTimeoutChange(self, event):
self.settings.set('timeout', event.GetEventObject().GetValue())
def OnModeChange(self, event):
self.settings.set('loginMode', event.GetInt())
def OnServerChange(self, event):
self.settings.set('server', event.GetInt())
def OnBtnApply(self, event):
self.settings.set('clientID', self.inputClientID.GetValue().strip())
self.settings.set('clientSecret', self.inputClientSecret.GetValue().strip())
sEsi = Esi.getInstance()
sEsi.delAllCharacters()
def getImage(self):
return BitmapLoader.getBitmap("eve", "gui")
PFEsiPref.register()

View File

@@ -83,7 +83,7 @@ import threading
import webbrowser
import wx.adv
from service.esi import Esi
from service.esi import Esi, LoginMethod
from gui.esiFittings import EveFittings, ExportToEve, SsoCharacterMgmt
disableOverrideEditor = False
@@ -241,12 +241,12 @@ class MainFrame(wx.Frame):
self.Bind(GE.EVT_SSO_LOGGING_IN, self.ShowSsoLogin)
def ShowSsoLogin(self, event):
dlg = SsoLogin(self)
if dlg.ShowModal() == wx.ID_OK:
sEsi = Esi.getInstance()
# todo: verify that this is a correct SSO Info block
sEsi.handleLogin(dlg.ssoInfoCtrl.Value.strip())
if getattr(event, "login_mode", LoginMethod.SERVER) == LoginMethod.MANUAL:
dlg = SsoLogin(self)
if dlg.ShowModal() == wx.ID_OK:
sEsi = Esi.getInstance()
# todo: verify that this is a correct SSO Info block
sEsi.handleLogin(dlg.ssoInfoCtrl.Value.strip())
def ShowUpdateBox(self, release, version):
dlg = UpdateDialog(self, release, version)

View File

@@ -43,7 +43,7 @@ from gui.builtinPreferenceViews import ( # noqa: E402, F401
pyfaGeneralPreferences,
pyfaNetworkPreferences,
pyfaHTMLExportPreferences,
# pyfaCrestPreferences,
pyfaEsiPreferences,
pyfaContextMenuPreferences,
pyfaStatViewPreferences,
pyfaUpdatePreferences,

View File

@@ -17,6 +17,7 @@ from eos.enum import Enum
from eos.saveddata.ssocharacter import SsoCharacter
import gui.globalEvents as GE
from service.server import StoppableHTTPServer, AuthHandler
from service.settings import EsiSettings
from .esi_security_proxy import EsiSecurityProxy
from esipy import EsiClient, EsiApp
@@ -39,6 +40,11 @@ class Servers(Enum):
SISI = 1
class LoginMethod(Enum):
SERVER = 0
MANUAL = 1
class Esi(object):
esiapp = None
esi_v1 = None
@@ -75,6 +81,8 @@ class Esi(object):
def __init__(self):
Esi.initEsiApp()
self.settings = EsiSettings.getInstance()
AFTER_TOKEN_REFRESH.add_receiver(self.tokenUpdate)
# these will be set when needed
@@ -119,7 +127,7 @@ class Esi(object):
if char is not None and char.esi_client is None:
char.esi_client = Esi.genEsiClient()
Esi.update_token(char, Esi.get_sso_data(char)) # don't use update_token on security directly, se still need to apply the values here
print(repr(char))
eos.db.commit()
return char
@@ -181,17 +189,33 @@ class Esi(object):
char.esi_client.security.update_token(tokenResponse)
def login(self):
# Switch off how we do things here depending on the mode of authentication
uri = self.startServer()
serverAddr = None
if self.settings.get('loginMode') == LoginMethod.SERVER:
serverAddr = self.startServer()
uri = self.getLoginURI(serverAddr)
webbrowser.open(uri)
wx.PostEvent(self.mainFrame, GE.SsoLoggingIn())
wx.PostEvent(self.mainFrame, GE.SsoLoggingIn(login_mode=self.settings.get('loginMode')))
def stopServer(self):
pyfalog.debug("Stopping Server")
self.httpd.stop()
self.httpd = None
def startServer(self):
def getLoginURI(self, redirect=None):
self.state = str(uuid.uuid4())
esisecurity = EsiSecurityProxy(sso_url=config.ESI_AUTH_PROXY)
args = {
'state': self.state,
'pyfa_version': config.version,
}
if redirect is not None:
args['redirect'] = redirect
return esisecurity.get_auth_uri(**args)
def startServer(self): # todo: break this out into two functions: starting the server, and getting the URI
pyfalog.debug("Starting server")
# we need this to ensure that the previous get_request finishes, and then the socket will close
@@ -199,20 +223,14 @@ class Esi(object):
self.stopServer()
time.sleep(1)
self.state = str(uuid.uuid4())
self.httpd = StoppableHTTPServer(('localhost', 0), AuthHandler)
port = self.httpd.socket.getsockname()[1]
esisecurity = EsiSecurityProxy(sso_url=config.ESI_AUTH_PROXY)
uri = esisecurity.get_auth_uri(state=self.state, redirect='http://localhost:{}'.format(port), pyfa_version=config.version)
self.serverThread = threading.Thread(target=self.httpd.serve, args=(self.handleServerLogin,))
self.serverThread.name = "SsoCallbackServer"
self.serverThread.daemon = True
self.serverThread.start()
return uri
return 'http://localhost:{}'.format(port)
def handleLogin(self, ssoInfo):
auth_response = json.loads(base64.b64decode(ssoInfo))

View File

@@ -352,32 +352,32 @@ class UpdateSettings(object):
self.serviceUpdateSettings[type] = value
class CRESTSettings(object):
class EsiSettings(object):
_instance = None
@classmethod
def getInstance(cls):
if cls._instance is None:
cls._instance = CRESTSettings()
cls._instance = EsiSettings()
return cls._instance
def __init__(self):
# mode
# 0 - Implicit authentication
# 1 - User-supplied client details
serviceCRESTDefaultSettings = {"mode": 0, "server": 0, "clientID": "", "clientSecret": "", "timeout": 60}
# LoginMode:
# 0 - Server Start Up
# 1 - User copy and paste data from website to pyfa
defaults = {"loginMode": 0, "clientID": "", "clientSecret": "", "timeout": 60}
self.serviceCRESTSettings = SettingsProvider.getInstance().getSettings(
"pyfaServiceCRESTSettings",
serviceCRESTDefaultSettings
self.settings = SettingsProvider.getInstance().getSettings(
"pyfaServiceEsiSettings",
defaults
)
def get(self, type):
return self.serviceCRESTSettings[type]
return self.settings[type]
def set(self, type, value):
self.serviceCRESTSettings[type] = value
self.settings[type] = value
class StatViewSettings(object):