[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/server/ Read the
username and password interactively.
Fred L. Drake, Jr.
fred at zope.com
Fri Jun 18 12:34:13 EDT 2004
Log message for revision 25910:
Read the username and password interactively.
(Merged revision 25908 from the ZopeX3-3.0 branch.)
-=-
Modified: Zope3/trunk/src/zope/app/server/mkzopeinstance.py
===================================================================
--- Zope3/trunk/src/zope/app/server/mkzopeinstance.py 2004-06-18 16:28:07 UTC (rev 25909)
+++ Zope3/trunk/src/zope/app/server/mkzopeinstance.py 2004-06-18 16:32:54 UTC (rev 25910)
@@ -44,18 +44,35 @@
else:
return 0
app = Application(options)
- return app.process()
+ try:
+ return app.process()
+ except KeyboardInterrupt:
+ return 1
+ except SystemExit, e:
+ return e.code
class Application:
def __init__(self, options):
self.options = options
+ self.need_blank_line = False
def read_input_line(self, prompt):
# The tests replace this to make sure the right things happen.
return raw_input(prompt)
+ def read_password(self, prompt):
+ # The tests replace this to make sure the right things happen.
+ import getpass
+ try:
+ return getpass.getpass(prompt)
+ except KeyboardInterrupt:
+ # The cursor was left on the same line as the prompt,
+ # which we don't like. Print a blank line.
+ print
+ raise
+
def process(self):
options = self.options
@@ -81,29 +98,58 @@
" non-directories)")
return 1
- # XXX for now, bail if the username/password hasn't been
- # provided from the command line; this should be improved
- # after the ZopeX3 alpha:
- if not (options.username and options.password):
- print >>sys.stderr, ("username and password must be"
- " provided using the --user option")
- return 2
+ if not options.username:
+ options.username = self.get_username()
+ if not options.password:
+ options.password = self.get_password()
# now create the instance!
self.copy_skeleton()
return 0
def get_skeltarget(self):
- print SKELTARGET_MESSAGE
+ self.print_message(SKELTARGET_MESSAGE)
+ self.need_blank_line = True
while 1:
skeltarget = self.read_input_line("Directory: ").strip()
if skeltarget == '':
print >>sys.stderr, 'You must specify a directory'
continue
- else:
- break
- return os.path.expanduser(skeltarget)
+ return os.path.expanduser(skeltarget)
+ def get_username(self):
+ self.print_message(USERNAME_MESSAGE)
+ self.need_blank_line = True
+ while 1:
+ username = self.read_input_line("Username: ").strip()
+ if not username:
+ print >>sys.stderr, "You must specify an administrative user"
+ continue
+ return username
+
+ def get_password(self):
+ self.print_message(PASSWORD_MESSAGE)
+ while 1:
+ password = self.read_password("Password: ")
+ if not password:
+ print >>sys.stderr, "Password may not be empty"
+ continue
+ if password != password.strip() or password.split() != [password]:
+ print >>sys.stderr, "Password may not contain spaces"
+ continue
+ break
+ again = self.read_password("Verify password: ")
+ if again != password:
+ print >>sys.stderr, "Password not verified!"
+ sys.exit(1)
+ return password
+
+ def print_message(self, message):
+ if self.need_blank_line:
+ print
+ self.need_blank_line = False
+ print message
+
def copy_skeleton(self):
options = self.options
# XXX we should be able to compute the script
@@ -127,6 +173,8 @@
# instead of shutil.copy2().
assert os.path.isdir(dst), dst
names = os.listdir(src)
+ if ".svn" in names:
+ names.remove(".svn")
for name in names:
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
@@ -159,7 +207,16 @@
etc.
"""
+USERNAME_MESSAGE = """\
+Please choose a username for the initial administrator account.
+This is required to allow Zope's management interface to be used.
+"""
+PASSWORD_MESSAGE = """\
+Please provide a password for the initial administrator account.
+"""
+
+
def parse_args(argv):
"""Parse the command line, returning an object representing the input."""
path, prog = os.path.split(os.path.realpath(argv[0]))
Modified: Zope3/trunk/src/zope/app/server/tests/test_mkzopeinstance.py
===================================================================
--- Zope3/trunk/src/zope/app/server/tests/test_mkzopeinstance.py 2004-06-18 16:28:07 UTC (rev 25909)
+++ Zope3/trunk/src/zope/app/server/tests/test_mkzopeinstance.py 2004-06-18 16:32:54 UTC (rev 25910)
@@ -161,6 +161,7 @@
self.assertEqual(skel, "foo")
self.assertEqual(input, [])
self.assert_(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
def test_process_creates_destination(self):
options = self.createOptions()
@@ -169,6 +170,7 @@
self.assertEqual(app.process(), 0)
self.assert_(os.path.isdir(self.instance))
self.assertEqual(input, [])
+ self.failUnless(app.all_input_consumed())
def test_process_aborts_on_file_destination(self):
options = self.createOptions()
@@ -185,7 +187,77 @@
self.assertEqual(app.process(), 1)
self.assert_(self.stderr.getvalue())
+ def test_get_username(self):
+ options = self.createOptions()
+ app = ControlledInputApplication(options, ["myuser"])
+ usr = app.get_username()
+ self.assertEqual(usr, "myuser")
+ self.failIf(self.stderr.getvalue())
+ self.failUnless(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
+ def test_get_username_strips_whitespace(self):
+ options = self.createOptions()
+ app = ControlledInputApplication(options, [" myuser\t"])
+ usr = app.get_username()
+ self.assertEqual(usr, "myuser")
+ self.failIf(self.stderr.getvalue())
+ self.failUnless(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
+
+ def test_get_username_ignores_empty_names(self):
+ options = self.createOptions()
+ app = ControlledInputApplication(options, ["", " ", "\t", "myuser"])
+ usr = app.get_username()
+ self.assertEqual(usr, "myuser")
+ self.failUnless(self.stderr.getvalue())
+ self.failUnless(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
+
+ def test_get_password(self):
+ options = self.createOptions()
+ app = ControlledInputApplication(options, ["foo", "foo"])
+ pw = app.get_password()
+ self.assertEqual(pw, "foo")
+ self.failIf(self.stderr.getvalue())
+ self.failUnless(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
+
+ def test_get_password_not_verified(self):
+ options = self.createOptions()
+ app = ControlledInputApplication(options, ["foo", "bar"])
+ try:
+ app.get_password()
+ except SystemExit, e:
+ self.assertEqual(e.code, 1)
+ else:
+ self.fail("expected SystemExit")
+ self.failUnless(self.stderr.getvalue())
+ self.failUnless(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
+
+ def test_get_password_empty(self):
+ # Make sure the empty password is ignored.
+ options = self.createOptions()
+ app = ControlledInputApplication(options, ["", "foo", "foo"])
+ pw = app.get_password()
+ self.assertEqual(pw, "foo")
+ self.failUnless(self.stderr.getvalue())
+ self.failUnless(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
+
+ def test_get_password_disallows_whitespace(self):
+ # Any password that contains spaces is disallowed.
+ options = self.createOptions()
+ app = ControlledInputApplication(options, [" ", "\t", "a b",
+ " a", "b ", "foo", "foo"])
+ pw = app.get_password()
+ self.assertEqual(pw, "foo")
+ self.failUnless(self.stderr.getvalue())
+ self.failUnless(self.stdout.getvalue())
+ self.failUnless(app.all_input_consumed())
+
+
class ControlledInputApplication(mkzopeinstance.Application):
def __init__(self, options, input_lines):
@@ -195,7 +267,12 @@
def read_input_line(self, prompt):
return self.__input.pop(0)
+ read_password = read_input_line
+ def all_input_consumed(self):
+ return not self.__input
+
+
class Options:
username = "[test-username]"
More information about the Zope3-Checkins
mailing list