implement a very simple, wxpython based, config wizard

This implements a very small app using a wx ui to log a user in.

it takes a username and password, and submits them to a backend on the web site
(currently the allmydata test net webserver) to authenticate them.  It returns
the 'root_cap' uri of the user's virtual drive. Also the introducer.furl is
retrieved.  These are then written into the default noderoot basedir in their
usual files (private/root_dir.cap and introducer.furl)

a button is provided which will direct the user to the web site in the event
that they need to register in order to have an account to use.

once the user is successfully authenticated and the files are written, then
on win32 the tahoe service will be started.
This commit is contained in:
robk-tahoe 2008-01-11 19:53:15 -07:00
parent d87a80dca6
commit dba59050a9
2 changed files with 241 additions and 5 deletions

69
windows/amdicon.py Normal file
View File

@ -0,0 +1,69 @@
#----------------------------------------------------------------------
# This file was generated by encode_icons.py
#
from wx import ImageFromStream, BitmapFromImage
from wx import EmptyIcon
import cStringIO
def getData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x04\
\x1aIDATX\x85\xad\x97MLTW\x14\xc7\xff\xef\xbd\x997|\x8c\x86\xb1\x888\x0c\x06\
\x17\x80\x03\xa1\x8a\t\xa9\x8d5a\xd3t\xd3\xa4\xed\xae+\xe3\xa6\xe9\x02v\x8d\
\xdd\xb8\xd2%D\xb1\x06\x02]\xd9.\xba\xd0\xa4iBqaHHM\xcbnbGZeH\x8d\x16\xad\
\xed\x14\x91\xe1c\x98\xb9\xf7\xbdw\xcf\xe9\x02\x9c\xf2\xf1\xde\x9b7\xc8\x99L\
2\x99{\xce\xb9\xbfs\xee\xb9\xe7\xde\xabi\xba\x81\xa0\x12\x1eN2\xd9!\x90\x1d\
\xc2\xdb\x87\x92\xa8\xab\x8abY\xe41\xb34\x0b=\xec\xc00mX}\x19-\xb0C\x00\xd0t\
#\xd0\xd7\xb8\xde\xcd-\xa3\x1f\xf3\xcd\x99\t\xce\x895\xde*9\xb1\xc67g&\xb8e\
\xec#\x0e}u\x8a\x83\xfa\xd4t#\x18\x80q\xed4_\xb8s\x85\xcbIN\xac\xf1\x85;W\
\xd8\xb8v:0D\xf9\xc9\x87\xba\xf9\xfc\xc4eV;>S\xf3)\x9e\x9aO\xf1\xfdlf\xd7\
\xd8\xf9\x89\xcbl\\\xef\x0e\x06\xe1W\x03\xa1\x1b\x1d|&\xf6.\xee~:T\xfao\xe2\
\x8fi\\\xfci\x04\x7f\x15\x9e\x03:\x03\xa4!Q\xd3\x8c\xc1\xde>|\xd8z\xb6\xa4w\
\xe6\xdb\xcf\x90\x113\xb0\xfbg\xfdk\xa2\\\xea\xc7\x9fL\xf1\x92\xbd\xc8K\xf6"\
\x8f\xa4o\xb16\xd8\xc3\x91\xd1\xcem\xd1EF;Y\x1b\xec\xe1\x91\xf4\xad\x92\xee\
\xf8\x93\xa9@K\xa1\xfb\xc1\xc5\xab\xe2\xe8ij\x83$\x81\x97\xc5W\xb8to\x0cf\
\xb4\xb0\xab\xd2\xad\xbe\x8cfF\x0b\xb8to\x0c/\x8b\xaf I\xa0\xa7\xa9\r\xf1\
\xea\xb8\xff\x0e\x00\xbc\x01B7:\xf8\x9dD\x12\x92\x05$\x0b|\xf7p\x12y\xe4<\
\xb7\x99\xd5\x97\xd1\xf2\xc8\xe1\xc7\xc7\xd3%\x9bd\xfd1\x84\x87\x93\xbc\'\
\x00\x008z \x06I\x02\x92\x04rb\x15\x9a\xa1|\xa3\xd1\x0c\x85\xf9\x95l\xc9\xa6\
\xbd>\x01&\xff\x12\x08\xf9\r:\xec@\x92(\xfd\x0e"\x95\xda\x94\x01\xb0\xb78\
\xb3\x03\x02Tf\xe3\t\xa0\xa4\t\x87\x1d\x08*\x02\x00\xea\xa3Qt\x1e\xec\x00\
\xbe\xe9\xf0]\xd3\xfah\xb4d\xe3\xb0\x03%M_\x00\xd7>\xa0\r\x9e\xe2/\xce~\x82\
\x0f\xdaO\x96\x8d\xa0\x9c\xdc\x9d{\x80\xab\xd3?\x80/\xa6]\x8b\xc15\x03-\x07\
\xe3\xe8mm/\xa5\xf2M\xa4\xb7\xb5\x1d\xdf\xff\x16\xc7S\xa4]\xc7]\x01\xaa\xcd\
\xf0\xbeL\xbe\xd5\x9f\x97\xb8\x020\x13\xc4>\x020Se\x00\x04\x82do\x80\xb9\xec\
\x02&\x1feP\xb0,\xd4\x98&\xde\xef8\x81\xf6\xc6\x06O}B\xa5\x00L\xa5J\xde)\x0f\
\x9e\xfd\x83\xaf\x7f\xfe\x05\xe1\xda"\xec\xfeY-<\x9c\xe4\xfb\x93\x7f\xe2\xf3\
s\xef\xe1\xe4\xb1\xa3\xee\x00{\xca\x80\xcb\x12,;K\xb8\x9dJo;\x0f\xec\xfeY\
\xcd\x1c9\xc1\xb7S\xbf\xe2\xad\x06\x0bu\xa1\x18\xc2\xba\xb9\xcb\xdf\x1e\x00$\
\x14;X\xb0\xb3\xf8\xd7z\x81U\xb5\x02b\x85e\xa1\x83\xbf\xdc}\x18\xd9\x03\xd5<\
\x99\x1b\x07\x81P\xa5W\xe3p\xf8\x08\x8eW\xb5\xe1\x88\x19\xaf\x1c\x80\x99\xf0\
B>\xc3\xbc|\x0c\x8b,\x10\x14\x14\x13\x88\x15\x98j\\\x1d1i\x90,A\xacP\xa0u,\
\xda\x0bx\xb8\x9e\xc6a\xb3\x11k\x8ew}\xb8\x1eFy\xb5\x86\xb9\xe2\xef(\xa8\xf5\
\xcd\x83E\xc2\xa2\x8d\x13\xae\xb1Y\xc0\x18\xea\xda\xd6\r\x8d\xa1.\x8e5\xadl\
\xeaHX$7\xecX\xe2\xb9x\x8aU\xb5R\x19\xc0\xeb~.Y\xc2\xe2\xff\x9dY$\xd1p|\t\
\xb5Q\xa7\x04a\x0cuq\xa4V\xa2\xae\xe5\xefM\x1d\x01\x8b$\x1c\xb672\x06\xdf\
\xce\xed]\x03\x16I((\x10+\x106\xd2\xafX\x81\x0cB]3!\xff\xa8\x11\x00\xc0\xac\
\xe1@"\x0bG/\x80\xc9\x7f\xb2\xe0\x00\xbc\xd1\x07\x88is\xfd\xb7C\xd8\xac\xef\
\xd2/\x17iE\x00\xbc3\x03L\xdb\xb2\xe1\x90wk\xdd\x17\x00\x02C\x92\x00\x816\
\xa3W`\xe6=GY9\x00\x13,\x96\xbe\xa9%+\x04m\xa0\x9b\xc9\xaa\xec%\x16\x08\x80\
\xc1P\xec}\xff\x8b\xd4\xad"q.\xf5F\x13\xbf\x16\xd7mHN\xf0\x07k\x10\xf1\xf3\
\xe7\n\xa0\xa4\x89\xe2bl_&/.\xc6\xa0D\xc4s\xdc\xf3i\xa6\rt\xb3Q%\xa1\x87\xfc\
\xaf\xe2~B\x8e\x01%M\xcf\xeb\x18\x00\xfc\x07\x9aY\xdf_&\xed\xfd\xe8\x00\x00\
\x00\x00IEND\xaeB`\x82'
def getBitmap():
return BitmapFromImage(getImage())
def getImage():
stream = cStringIO.StringIO(getData())
return ImageFromStream(stream)
def getIcon():
icon = EmptyIcon()
icon.CopyFromBitmap(getBitmap())
return icon

View File

@ -1,10 +1,22 @@
BACKEND_URL = 'https://www-test.allmydata.com/native_client2.php'
REGISTER_PAGE = 'https://www-test.allmydata.com/register'
WINSVC_NAME = 'Tahoe'
import os
import sys
import traceback
import urllib2
from urllib import urlencode
import webbrowser
import wx
from allmydata.util.assertutil import precondition
from allmydata import uri
import amdicon
class AuthError(Exception):
pass
@ -12,6 +24,7 @@ def unicode_to_utf8(uobj):
assert precondition(isinstance(uobj, unicode))
return uobj.encode('utf-8')
def post(url, args):
argstr = urlencode(args)
conn = urllib2.urlopen(url, argstr)
@ -34,12 +47,166 @@ def get_root_cap(url, user, passwd):
def get_introducer_furl(url):
return post(url, { 'action': 'getintroducerfurl' })
def write_config_file(filename, contents):
if sys.platform == 'win32':
from allmydata.windows import registry
basedir = registry.get_base_dir_path()
else:
basedir = os.path.expanduser('~/.tahoe')
path = os.path.join(basedir, filename)
dirname = os.path.dirname(path)
if not os.path.exists(dirname):
os.makedirs(dirname)
iff = file(path, 'wb')
iff.write(contents)
iff.close()
def DisplayTraceback(message):
xc = traceback.format_exception(*sys.exc_info())
wx.MessageBox(u"%s\n (%s)"%(message,''.join(xc)), 'Error')
class ConfWizApp(wx.App):
def __init__(self):
wx.App.__init__(self, 0)
def OnInit(self):
try:
wx.InitAllImageHandlers()
self.frame = ConfWizFrame(self)
self.frame.CenterOnScreen()
self.SetTopWindow(self.frame)
self.SetExitOnFrameDelete(True)
self.frame.Show(True)
return True
except:
DisplayTraceback('config wizard init threw an exception')
class ConfWizFrame(wx.Frame):
def __init__(self, app):
title = 'Allmydata Tahoe Config Wizard'
wx.Frame.__init__(self, None, -1, title)
self.app = app
self.SetSizeHints(100, 100, 600, 800)
self.SetIcon(amdicon.getIcon())
self.Bind(wx.EVT_CLOSE, self.close)
background = wx.Panel(self, -1)
background.parent = self
self.login_panel = LoginPanel(background)
self.register_panel = RegisterPanel(background)
sizer = wx.BoxSizer(wx.VERTICAL)
background_sizer = wx.BoxSizer(wx.VERTICAL)
background_sizer.Add(self.login_panel, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 26)
background_sizer.Add(self.register_panel, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 26)
background.SetSizer(background_sizer)
sizer.Add(background, 0, wx.EXPAND | wx.ALL, 0)
self.SetSizer(sizer)
self.SetAutoLayout(True)
self.Fit()
self.Layout()
def close(self, event):
sys.exit()
class LoginPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
self.parent = parent
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.user_label = wx.StaticText(self, -1, 'Email')
self.pass_label = wx.StaticText(self, -1, 'Password')
self.user_field = wx.TextCtrl(self, -1, u'', size=(260,-1))
self.pass_field = wx.TextCtrl(self, -1, u'', size=(260,-1), style=wx.TE_PASSWORD)
self.login_button = wx.Button(self, -1, 'Sign In')
self.warning_label = wx.StaticText(self, -1, '')
self.warning_label.SetOwnForegroundColour(wx.RED)
wx.EVT_CHAR(self.user_field, self.on_user_entry)
wx.EVT_CHAR(self.pass_field, self.on_pass_entry)
self.Bind(wx.EVT_BUTTON, self.on_login, self.login_button)
login_sizer = wx.FlexGridSizer(3, 2, 5, 4)
login_sizer.Add(self.user_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
login_sizer.Add(self.user_field, 0, wx.EXPAND | wx.ALL, 2)
login_sizer.Add(self.pass_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
login_sizer.Add(self.pass_field, 0, wx.EXPAND | wx.ALL, 2)
login_sizer.Add(wx.Size(2,2), 0, wx.ALIGN_RIGHT | wx.ALL, 2)
login_sizer.Add(self.login_button, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
self.sizer.Add(login_sizer, 1, wx.EXPAND | wx.ALL, 2)
#self.sizer.Add(self.warning_label, 0, wx.EXPAND | wx.ALL, 2)
self.sizer.Add(self.warning_label, 0, wx.CENTER | wx.ALL, 2)
self.SetSizer(self.sizer)
self.SetAutoLayout(True)
def on_user_entry(self, event):
if event.GetKeyCode() == wx.WXK_RETURN:
self.pass_field.SetFocus()
else:
event.Skip()
def on_pass_entry(self, event):
if event.GetKeyCode() == wx.WXK_RETURN:
self.on_login(event)
else:
event.Skip()
def on_login(self, event):
user = self.user_field.GetValue()
passwd = self.pass_field.GetValue()
self.warning_label.SetLabel('')
try:
root_cap = get_root_cap(BACKEND_URL, user, passwd)
write_config_file('private/root_dir.cap', root_cap+'\n')
except AuthError:
self.warning_label.SetLabel('Your email and/or password is incorrect')
self.user_field.SetFocus()
self.Layout()
return
# fetch the introducer furl
ifurl = get_introducer_furl(BACKEND_URL)
write_config_file('introducer.furl', ifurl+'\n')
# start service etc.
if sys.platform == 'win32':
try:
import win32service
import win32serviceutil as wsu
if wsu.QueryServiceStatus(WINSVC_NAME)[1] != win32service.SERVICE_RUNNING:
wsu.StartService(WINSVC_NAME)
except:
DisplayTraceback('Failed to start windows service')
# exit
self.parent.parent.Close()
class RegisterPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
self.parent = parent
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.reg_label = wx.StaticText(self, -1, "Don't have an account?")
self.reg_button = wx.Button(self, -1, 'Create Account')
self.Bind(wx.EVT_BUTTON, self.on_reg_button, self.reg_button)
reg_sizer = wx.FlexGridSizer(1, 2, 5, 4)
reg_sizer.Add(self.reg_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
reg_sizer.Add(self.reg_button, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
self.sizer.Add(reg_sizer, 1, wx.EXPAND | wx.ALL, 2)
self.SetSizer(self.sizer)
self.SetAutoLayout(True)
def on_reg_button(self, event):
webbrowser.open(REGISTER_PAGE)
def main():
URL = 'https://www-test.allmydata.com/native_client2.php'
print get_introducer_furl(URL)
print get_root_cap(URL, u'user', u'pass')
app = ConfWizApp()
app.MainLoop()
if __name__ == '__main__':