diff options
Diffstat (limited to 'modules/installed/first_boot.py')
-rw-r--r-- | modules/installed/first_boot.py | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/modules/installed/first_boot.py b/modules/installed/first_boot.py new file mode 100644 index 0000000..9cf7474 --- /dev/null +++ b/modules/installed/first_boot.py @@ -0,0 +1,120 @@ +from urlparse import urlparse +import os, cherrypy, re +from gettext import gettext as _ +from plugin_mount import PagePlugin, PluginMount, FormPlugin +from modules.auth import require +from forms import Form +import util as u +from vendor.withsqlite.withsqlite import sqlite_db +import cfg + +class FirstBoot(PagePlugin): + def __init__(self, *args, **kwargs): + PagePlugin.__init__(self, *args, **kwargs) + self.register_page("firstboot") # this is the url this page will hang off of (/firstboot) + + @cherrypy.expose + def index(self, *args, **kwargs): + return self.state0(*args, **kwargs) + + ## TODO: flesh out these tests values + def valid_box_name_p(self, name): + name = name.strip() + if re.search("\W", name): + return False + return True + def valid_box_key_p(self, key): + return True + def generate_box_key(self): + return "fake key" + + @cherrypy.expose + def state0(self, message="", box_name="", box_key="", submitted=False): + """ + In this state, we do time config over HTTP, name the box and + server key selection. + + All the parameters are form inputs. They get passed in when + the form is submitted. This method checks the inputs and if + they validate, uses them to take action. If they do not + validate, it displays the form to give the user a chance to + input correct values. It might display an error message (in + the message parameter). + + message is an optional string that we can display to the + user. It's a good place to put error messages. + """ + + ## Until LDAP is in place, we'll put the box name and key in the cfg.store_file + ## Must resist the sick temptation to write an LDAP interface to the sqlite file + with sqlite_db(cfg.store_file, table="thisbox", autocommit=True) as db: + db['about'] = "This table is for information about this FreedomBox" + if box_name: + if self.valid_box_name_p(box_name): + db['box_name'] = box_name + else: + message += _("Invalid box name.") + elif 'box_name' in db and db['box_name']: + box_name = db['box_name'] + #TODO: set /etc/hostname to box name via ex machina + + if box_key: + if self.valid_box_key_p(box_key): + db['box_key'] = box_key + else: + message += _("Invalid key!") + elif 'box_key' in db and db['box_key']: + box_key = _("We already have a key for this box on file.") #TODO: Think this through and handle more gracefully + elif submitted and not box_key: + box_key = self.generate_box_key() + db['box_key'] = box_key + + + if box_name and box_key and self.valid_box_name_p(box_name) and self.valid_box_key_p(box_key): + ## Update state to 1 and head there + with sqlite_db(cfg.store_file, table="firstboot", autocommit=True) as db: + db['state']=1 + raise cherrypy.InternalRedirect('/firstboot/state1') + + main = "<p>Welcome. It looks like this FreedomBox isn't set up yet. We'll need to ask you a just few questions to get started.</p>" + form = Form(title="Welcome to Your FreedomBox!", + action="/firstboot", + name="whats_my_name", + message=message) + if not box_name: + box_name = cfg.box_name + form.html("<p>For convenience, your FreedomBox needs a name. It should be something short that doesn't contain spaces or punctuation. 'Willard' would be a good name. 'Freestyle McFreedomBox!!!' would not.</p>") + form.text_input('Name your FreedomBox', id="box_name", value=box_name) + form.html("<p>%(box_name)s uses cryptographic keys so it can prove its identity when talking to you. %(box_name)s can make a key for itself, but if one already exists (from a prior FreedomBox, for example), you can paste it below. This key should not be the same as your key because you are not your FreedomBox!</p>" % {'box_name':cfg.box_name}) + form.text_box("If you want, paste your box's key here.", id="box_key", value=box_key) + form.hidden(name="submitted", value="True") + form.submit("Box it up!") + + main += form.render() + return self.fill_template(template="base", title=_("First Boot!"), main=main, + sidebar_right=_("""<strong>Getting Help</strong><p>We've done our best to make your FreedomBox easy to use. If you have questions during setup, there are a few places to turn for help. TODO: add links to such help.</p>""")) + + @cherrypy.expose + def state1(self, message=None): + """ + State 1 is when we have a box name and key. In this state, + our task is to provide a certificate and maybe to guide the + user through installing it. We automatically move to State 2, + which is an HTTPS connection. + + TODO: HTTPS failure in State 2 should returns to state 1. + """ + main = """<p>Here's a certificate. +TODO: explain all this cert stuff to the user.</p> +<p>TODO: add instrux for installing certificate.</p> +<p>After you have installed +""" + if False: + ## Update state to 2 and head there + with sqlite_db(cfg.store_file, table="firstboot", autocommit=True) as db: + db['state']=1 + #TODO: switch to HTTPS + raise cherrypy.InternalRedirect('/firstboot/state1') + + return self.fill_template(template="base", title=_("Installing the Certificate"), main=main, + sidebar_right=_("""<strong>Getting Help</strong><p>We've done our best to make your FreedomBox easy to use. If you have questions during setup, there are a few places to turn for help. TODO: add links to such help.</p>""")) |