Add login dialog and username/password command line options

This commit is contained in:
Nick Hall 2017-09-25 22:44:47 +01:00
parent 1f9f08c3c5
commit c048ebcfbb
13 changed files with 100 additions and 32 deletions

View File

@ -180,6 +180,8 @@ class ArgHandler:
self.imports = []
self.exports = []
self.removes = parser.removes
self.username = parser.username
self.password = parser.password
self.open = self.__handle_open_option(parser.open, parser.create)
self.sanitize_args(parser.imports, parser.exports)
@ -505,7 +507,7 @@ class ArgHandler:
newdb.write_version(self.imp_db_path)
try:
self.smgr.open_activate(self.imp_db_path)
self.smgr.open_activate(self.imp_db_path, self.username, self.password)
msg = _("Created empty Family Tree successfully")
print(msg, file=sys.stderr)
except:
@ -532,7 +534,7 @@ class ArgHandler:
# we load this file for use
try:
self.smgr.open_activate(self.open)
self.smgr.open_activate(self.open, self.username, self.password)
print(_("Opened successfully!"), file=sys.stderr)
except:
print(_("Error opening the file."), file=sys.stderr)

View File

@ -62,6 +62,8 @@ Help options
Application options
-O, --open=FAMILY_TREE Open Family Tree
-U, --username=USERNAME Database username
-P, --password=PASSWORD Database password
-C, --create=FAMILY_TREE Create on open if new Family Tree
-i, --import=FILENAME Import file
-e, --export=FILENAME Export file
@ -138,6 +140,8 @@ class ArgParser:
The valid options are:
-O, --open=FAMILY_TREE Open Family Tree
-U, --username=USERNAME Database username
-P, --password=PASSWORD Database password
-C, --create=FAMILY_TREE Create on open if new Family Tree
-i, --import=FILENAME Import file
-e, --export=FILENAME Export file
@ -196,6 +200,8 @@ class ArgParser:
self.open_gui = None
self.open = None
self.username = None
self.password = None
self.exports = []
self.actions = []
self.imports = []
@ -279,6 +285,10 @@ class ArgParser:
self.open = value
elif option in ['-C', '--create']:
self.create = value
elif option in ['-U', '--username']:
self.username = value
elif option in ['-P', '--password']:
self.password = value
elif option in ['-i', '--import']:
family_tree_format = None
if (opt_ix < len(options) - 1

View File

@ -132,7 +132,7 @@ class CLIDbLoader:
"""
pass
def read_file(self, filename):
def read_file(self, filename, username, password):
"""
This method takes care of changing database, and loading the data.
In 3.0 we only allow reading of real databases of filetype
@ -173,7 +173,8 @@ class CLIDbLoader:
self._begin_progress()
try:
self.dbstate.db.load(filename, self._pulse_progress, mode)
self.dbstate.db.load(filename, self._pulse_progress, mode,
username=username, password=password)
except DbEnvironmentError as msg:
self.dbstate.no_database()
self._errordialog(_("Cannot open database"), str(msg))
@ -240,11 +241,11 @@ class CLIManager:
self._pmgr = BasePluginManager.get_instance()
self.user = user
def open_activate(self, path):
def open_activate(self, path, username, password):
"""
Open and make a family tree active
"""
self._read_recent_file(path)
self._read_recent_file(path, username, password)
def _errordialog(self, title, errormessage):
"""
@ -253,7 +254,7 @@ class CLIManager:
print(_('ERROR: %s') % errormessage, file=sys.stderr)
sys.exit(1)
def _read_recent_file(self, filename):
def _read_recent_file(self, filename, username, password):
"""
Called when a file needs to be loaded
"""
@ -274,7 +275,7 @@ class CLIManager:
"that the database is not in use."))
return
if self.db_loader.read_file(filename):
if self.db_loader.read_file(filename, username, password):
# Attempt to figure out the database title
path = os.path.join(filename, "name.txt")
try:

View File

@ -163,8 +163,6 @@ register('database.backup-path', USER_HOME)
register('database.backup-on-exit', True)
register('database.autobackup', 0)
register('database.path', os.path.join(HOME_DIR, 'grampsdb'))
register('database.user', '')
register('database.password', '')
register('database.host', '')
register('database.port', '')

View File

@ -288,6 +288,8 @@ LONGOPTS = [
"oaf-ior-fd=",
"oaf-private",
"open=",
"username=",
"password=",
"create=",
"options=",
"screen=",
@ -303,7 +305,7 @@ LONGOPTS = [
"quiet",
]
SHORTOPTS = "O:C:i:e:f:a:p:d:c:r:lLthuv?syq"
SHORTOPTS = "O:U:P:C:i:e:f:a:p:d:c:r:lLthuv?syq"
GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')

View File

@ -1427,6 +1427,11 @@ class DbReadBase:
"""
raise NotImplementedError
def requires_login(self):
"""
Returns True for backends that require a login dialog, else False.
"""
return False
class DbWriteBase(DbReadBase):
"""

View File

@ -575,7 +575,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
if directory:
self.load(directory)
def _initialize(self, directory):
def _initialize(self, directory, username, password):
"""
Initialize database backend.
"""
@ -586,12 +586,14 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
force_bsddb_upgrade=False,
force_bsddb_downgrade=False,
force_python_upgrade=False,
update=True):
update=True,
username=None,
password=None):
"""
If update is False: then don't update any files
"""
# run backend-specific code:
self._initialize(directory)
self._initialize(directory, username, password)
# We use the existence of the person table as a proxy for the database
# being new

View File

@ -1471,14 +1471,6 @@ class GrampsPreferences(ConfigureDialog):
current_line += 1
self.connection_widgets = []
entry = self.add_entry(grid, _('Username'), current_line,
'database.user', col_attach=1)
self.connection_widgets.append(entry)
current_line += 1
entry = self.add_entry(grid, _('Password'), current_line,
'database.password', col_attach=1)
self.connection_widgets.append(entry)
current_line += 1
entry = self.add_entry(grid, _('Host'), current_line,
'database.host', col_attach=1)
self.connection_widgets.append(entry)

View File

@ -144,7 +144,7 @@ class DbLoader(CLIDbLoader):
return ""
return self.import_info.info_text()
def read_file(self, filename):
def read_file(self, filename, username=None, password=None):
"""
This method takes care of changing database, and loading the data.
In 3.0 we only allow reading of real databases of filetype
@ -181,6 +181,13 @@ class DbLoader(CLIDbLoader):
db.disable_signals()
self.dbstate.no_database()
if db.requires_login() and username is None:
login = GrampsLoginDialog(self.uistate)
credentials = login.run()
if credentials is None:
return
username, password = credentials
self._begin_progress()
force_schema_upgrade = False
@ -194,7 +201,9 @@ class DbLoader(CLIDbLoader):
mode, force_schema_upgrade,
force_bsddb_upgrade,
force_bsddb_downgrade,
force_python_upgrade)
force_python_upgrade,
username=username,
password=password)
if self.dbstate.is_open():
self.dbstate.db.close(
user=User(callback=self._pulse_progress,
@ -383,6 +392,49 @@ def format_maker():
box.show_all()
return (box, type_selector)
class GrampsLoginDialog(ManagedWindow):
def __init__(self, uistate):
"""
A login dialog to obtain credentials to connect to a database
"""
self.title = _("Login")
ManagedWindow.__init__(self, uistate, [], self.__class__, modal=True)
dialog = Gtk.Dialog(parent=uistate.window)
grid = Gtk.Grid()
grid.set_border_width(6)
grid.set_row_spacing(6)
grid.set_column_spacing(6)
label = Gtk.Label(label=_('Username: '))
grid.attach(label, 0, 0, 1, 1)
self.username = Gtk.Entry()
self.username.set_hexpand(True)
grid.attach(self.username, 1, 0, 1, 1)
label = Gtk.Label(label=_('Password: '))
grid.attach(label, 0, 1, 1, 1)
self.password = Gtk.Entry()
self.password.set_hexpand(True)
self.password.set_visibility(False)
self.password.set_input_purpose(Gtk.InputPurpose.PASSWORD)
grid.attach(self.password, 1, 1, 1, 1)
dialog.vbox.pack_start(grid, True, True, 0)
dialog.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('Login'), Gtk.ResponseType.OK)
self.set_window(dialog, None, self.title)
def run(self):
self.show()
response = self.window.run()
username = self.username.get_text()
password = self.password.get_text()
if response == Gtk.ResponseType.CANCEL:
self.close()
return None
elif response == Gtk.ResponseType.OK:
self.close()
return (username, password)
class GrampsImportFileDialog(ManagedWindow):
def __init__(self, dbstate, uistate, callback=None):

View File

@ -536,7 +536,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
@catch_db_error
def load(self, name, callback=None, mode=DBMODE_W, force_schema_upgrade=False,
force_bsddb_upgrade=False, force_bsddb_downgrade=False,
force_python_upgrade=False, update=True):
force_python_upgrade=False, update=True,
username=None, password=None):
"""
If update is False: then don't update any files; open read-only
"""

View File

@ -65,7 +65,7 @@ class DBAPI(DbGeneric):
with open(versionpath, "w") as version_file:
version_file.write(self.__class__.__name__.lower())
def _initialize(self, directory):
def _initialize(self, directory, username, password):
raise NotImplementedError
def _create_schema(self):

View File

@ -66,13 +66,14 @@ class PostgreSQL(DBAPI):
})
return summary
def _initialize(self, directory):
def requires_login(self):
return True
def _initialize(self, directory, username, password):
config_file = os.path.join(directory, 'settings.ini')
config_mgr = ConfigManager(config_file)
config_mgr.register('database.dbname', '')
config_mgr.register('database.host', '')
config_mgr.register('database.user', '')
config_mgr.register('database.password', '')
config_mgr.register('database.port', '')
if not os.path.exists(config_file):
@ -81,8 +82,6 @@ class PostgreSQL(DBAPI):
dbname = file.readline().strip()
config_mgr.set('database.dbname', dbname)
config_mgr.set('database.host', config.get('database.host'))
config_mgr.set('database.user', config.get('database.user'))
config_mgr.set('database.password', config.get('database.password'))
config_mgr.set('database.port', config.get('database.port'))
config_mgr.save()
@ -93,6 +92,10 @@ class PostgreSQL(DBAPI):
value = config_mgr.get('database.' + key)
if value:
dbkwargs[key] = value
if username:
dbkwargs['user'] = username
if password:
dbkwargs['password'] = password
try:
self.dbapi = Connection(**dbkwargs)

View File

@ -64,7 +64,7 @@ class SQLite(DBAPI):
})
return summary
def _initialize(self, directory):
def _initialize(self, directory, username, password):
if directory == ':memory:':
path_to_db = ':memory:'
else: