Add login dialog and username/password command line options
This commit is contained in:
parent
1f9f08c3c5
commit
c048ebcfbb
@ -180,6 +180,8 @@ class ArgHandler:
|
|||||||
self.imports = []
|
self.imports = []
|
||||||
self.exports = []
|
self.exports = []
|
||||||
self.removes = parser.removes
|
self.removes = parser.removes
|
||||||
|
self.username = parser.username
|
||||||
|
self.password = parser.password
|
||||||
|
|
||||||
self.open = self.__handle_open_option(parser.open, parser.create)
|
self.open = self.__handle_open_option(parser.open, parser.create)
|
||||||
self.sanitize_args(parser.imports, parser.exports)
|
self.sanitize_args(parser.imports, parser.exports)
|
||||||
@ -505,7 +507,7 @@ class ArgHandler:
|
|||||||
newdb.write_version(self.imp_db_path)
|
newdb.write_version(self.imp_db_path)
|
||||||
|
|
||||||
try:
|
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")
|
msg = _("Created empty Family Tree successfully")
|
||||||
print(msg, file=sys.stderr)
|
print(msg, file=sys.stderr)
|
||||||
except:
|
except:
|
||||||
@ -532,7 +534,7 @@ class ArgHandler:
|
|||||||
|
|
||||||
# we load this file for use
|
# we load this file for use
|
||||||
try:
|
try:
|
||||||
self.smgr.open_activate(self.open)
|
self.smgr.open_activate(self.open, self.username, self.password)
|
||||||
print(_("Opened successfully!"), file=sys.stderr)
|
print(_("Opened successfully!"), file=sys.stderr)
|
||||||
except:
|
except:
|
||||||
print(_("Error opening the file."), file=sys.stderr)
|
print(_("Error opening the file."), file=sys.stderr)
|
||||||
|
@ -62,6 +62,8 @@ Help options
|
|||||||
|
|
||||||
Application options
|
Application options
|
||||||
-O, --open=FAMILY_TREE Open Family Tree
|
-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
|
-C, --create=FAMILY_TREE Create on open if new Family Tree
|
||||||
-i, --import=FILENAME Import file
|
-i, --import=FILENAME Import file
|
||||||
-e, --export=FILENAME Export file
|
-e, --export=FILENAME Export file
|
||||||
@ -138,6 +140,8 @@ class ArgParser:
|
|||||||
The valid options are:
|
The valid options are:
|
||||||
|
|
||||||
-O, --open=FAMILY_TREE Open Family Tree
|
-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
|
-C, --create=FAMILY_TREE Create on open if new Family Tree
|
||||||
-i, --import=FILENAME Import file
|
-i, --import=FILENAME Import file
|
||||||
-e, --export=FILENAME Export file
|
-e, --export=FILENAME Export file
|
||||||
@ -196,6 +200,8 @@ class ArgParser:
|
|||||||
|
|
||||||
self.open_gui = None
|
self.open_gui = None
|
||||||
self.open = None
|
self.open = None
|
||||||
|
self.username = None
|
||||||
|
self.password = None
|
||||||
self.exports = []
|
self.exports = []
|
||||||
self.actions = []
|
self.actions = []
|
||||||
self.imports = []
|
self.imports = []
|
||||||
@ -279,6 +285,10 @@ class ArgParser:
|
|||||||
self.open = value
|
self.open = value
|
||||||
elif option in ['-C', '--create']:
|
elif option in ['-C', '--create']:
|
||||||
self.create = value
|
self.create = value
|
||||||
|
elif option in ['-U', '--username']:
|
||||||
|
self.username = value
|
||||||
|
elif option in ['-P', '--password']:
|
||||||
|
self.password = value
|
||||||
elif option in ['-i', '--import']:
|
elif option in ['-i', '--import']:
|
||||||
family_tree_format = None
|
family_tree_format = None
|
||||||
if (opt_ix < len(options) - 1
|
if (opt_ix < len(options) - 1
|
||||||
|
@ -132,7 +132,7 @@ class CLIDbLoader:
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def read_file(self, filename):
|
def read_file(self, filename, username, password):
|
||||||
"""
|
"""
|
||||||
This method takes care of changing database, and loading the data.
|
This method takes care of changing database, and loading the data.
|
||||||
In 3.0 we only allow reading of real databases of filetype
|
In 3.0 we only allow reading of real databases of filetype
|
||||||
@ -173,7 +173,8 @@ class CLIDbLoader:
|
|||||||
self._begin_progress()
|
self._begin_progress()
|
||||||
|
|
||||||
try:
|
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:
|
except DbEnvironmentError as msg:
|
||||||
self.dbstate.no_database()
|
self.dbstate.no_database()
|
||||||
self._errordialog(_("Cannot open database"), str(msg))
|
self._errordialog(_("Cannot open database"), str(msg))
|
||||||
@ -240,11 +241,11 @@ class CLIManager:
|
|||||||
self._pmgr = BasePluginManager.get_instance()
|
self._pmgr = BasePluginManager.get_instance()
|
||||||
self.user = user
|
self.user = user
|
||||||
|
|
||||||
def open_activate(self, path):
|
def open_activate(self, path, username, password):
|
||||||
"""
|
"""
|
||||||
Open and make a family tree active
|
Open and make a family tree active
|
||||||
"""
|
"""
|
||||||
self._read_recent_file(path)
|
self._read_recent_file(path, username, password)
|
||||||
|
|
||||||
def _errordialog(self, title, errormessage):
|
def _errordialog(self, title, errormessage):
|
||||||
"""
|
"""
|
||||||
@ -253,7 +254,7 @@ class CLIManager:
|
|||||||
print(_('ERROR: %s') % errormessage, file=sys.stderr)
|
print(_('ERROR: %s') % errormessage, file=sys.stderr)
|
||||||
sys.exit(1)
|
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
|
Called when a file needs to be loaded
|
||||||
"""
|
"""
|
||||||
@ -274,7 +275,7 @@ class CLIManager:
|
|||||||
"that the database is not in use."))
|
"that the database is not in use."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.db_loader.read_file(filename):
|
if self.db_loader.read_file(filename, username, password):
|
||||||
# Attempt to figure out the database title
|
# Attempt to figure out the database title
|
||||||
path = os.path.join(filename, "name.txt")
|
path = os.path.join(filename, "name.txt")
|
||||||
try:
|
try:
|
||||||
|
@ -163,8 +163,6 @@ register('database.backup-path', USER_HOME)
|
|||||||
register('database.backup-on-exit', True)
|
register('database.backup-on-exit', True)
|
||||||
register('database.autobackup', 0)
|
register('database.autobackup', 0)
|
||||||
register('database.path', os.path.join(HOME_DIR, 'grampsdb'))
|
register('database.path', os.path.join(HOME_DIR, 'grampsdb'))
|
||||||
register('database.user', '')
|
|
||||||
register('database.password', '')
|
|
||||||
register('database.host', '')
|
register('database.host', '')
|
||||||
register('database.port', '')
|
register('database.port', '')
|
||||||
|
|
||||||
|
@ -288,6 +288,8 @@ LONGOPTS = [
|
|||||||
"oaf-ior-fd=",
|
"oaf-ior-fd=",
|
||||||
"oaf-private",
|
"oaf-private",
|
||||||
"open=",
|
"open=",
|
||||||
|
"username=",
|
||||||
|
"password=",
|
||||||
"create=",
|
"create=",
|
||||||
"options=",
|
"options=",
|
||||||
"screen=",
|
"screen=",
|
||||||
@ -303,7 +305,7 @@ LONGOPTS = [
|
|||||||
"quiet",
|
"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')
|
GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')
|
||||||
|
|
||||||
|
@ -1427,6 +1427,11 @@ class DbReadBase:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def requires_login(self):
|
||||||
|
"""
|
||||||
|
Returns True for backends that require a login dialog, else False.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
class DbWriteBase(DbReadBase):
|
class DbWriteBase(DbReadBase):
|
||||||
"""
|
"""
|
||||||
|
@ -575,7 +575,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
|
|||||||
if directory:
|
if directory:
|
||||||
self.load(directory)
|
self.load(directory)
|
||||||
|
|
||||||
def _initialize(self, directory):
|
def _initialize(self, directory, username, password):
|
||||||
"""
|
"""
|
||||||
Initialize database backend.
|
Initialize database backend.
|
||||||
"""
|
"""
|
||||||
@ -586,12 +586,14 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
|
|||||||
force_bsddb_upgrade=False,
|
force_bsddb_upgrade=False,
|
||||||
force_bsddb_downgrade=False,
|
force_bsddb_downgrade=False,
|
||||||
force_python_upgrade=False,
|
force_python_upgrade=False,
|
||||||
update=True):
|
update=True,
|
||||||
|
username=None,
|
||||||
|
password=None):
|
||||||
"""
|
"""
|
||||||
If update is False: then don't update any files
|
If update is False: then don't update any files
|
||||||
"""
|
"""
|
||||||
# run backend-specific code:
|
# 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
|
# We use the existence of the person table as a proxy for the database
|
||||||
# being new
|
# being new
|
||||||
|
@ -1471,14 +1471,6 @@ class GrampsPreferences(ConfigureDialog):
|
|||||||
current_line += 1
|
current_line += 1
|
||||||
|
|
||||||
self.connection_widgets = []
|
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,
|
entry = self.add_entry(grid, _('Host'), current_line,
|
||||||
'database.host', col_attach=1)
|
'database.host', col_attach=1)
|
||||||
self.connection_widgets.append(entry)
|
self.connection_widgets.append(entry)
|
||||||
|
@ -144,7 +144,7 @@ class DbLoader(CLIDbLoader):
|
|||||||
return ""
|
return ""
|
||||||
return self.import_info.info_text()
|
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.
|
This method takes care of changing database, and loading the data.
|
||||||
In 3.0 we only allow reading of real databases of filetype
|
In 3.0 we only allow reading of real databases of filetype
|
||||||
@ -181,6 +181,13 @@ class DbLoader(CLIDbLoader):
|
|||||||
db.disable_signals()
|
db.disable_signals()
|
||||||
self.dbstate.no_database()
|
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()
|
self._begin_progress()
|
||||||
|
|
||||||
force_schema_upgrade = False
|
force_schema_upgrade = False
|
||||||
@ -194,7 +201,9 @@ class DbLoader(CLIDbLoader):
|
|||||||
mode, force_schema_upgrade,
|
mode, force_schema_upgrade,
|
||||||
force_bsddb_upgrade,
|
force_bsddb_upgrade,
|
||||||
force_bsddb_downgrade,
|
force_bsddb_downgrade,
|
||||||
force_python_upgrade)
|
force_python_upgrade,
|
||||||
|
username=username,
|
||||||
|
password=password)
|
||||||
if self.dbstate.is_open():
|
if self.dbstate.is_open():
|
||||||
self.dbstate.db.close(
|
self.dbstate.db.close(
|
||||||
user=User(callback=self._pulse_progress,
|
user=User(callback=self._pulse_progress,
|
||||||
@ -383,6 +392,49 @@ def format_maker():
|
|||||||
box.show_all()
|
box.show_all()
|
||||||
return (box, type_selector)
|
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):
|
class GrampsImportFileDialog(ManagedWindow):
|
||||||
|
|
||||||
def __init__(self, dbstate, uistate, callback=None):
|
def __init__(self, dbstate, uistate, callback=None):
|
||||||
|
@ -536,7 +536,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
|||||||
@catch_db_error
|
@catch_db_error
|
||||||
def load(self, name, callback=None, mode=DBMODE_W, force_schema_upgrade=False,
|
def load(self, name, callback=None, mode=DBMODE_W, force_schema_upgrade=False,
|
||||||
force_bsddb_upgrade=False, force_bsddb_downgrade=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
|
If update is False: then don't update any files; open read-only
|
||||||
"""
|
"""
|
||||||
|
@ -65,7 +65,7 @@ class DBAPI(DbGeneric):
|
|||||||
with open(versionpath, "w") as version_file:
|
with open(versionpath, "w") as version_file:
|
||||||
version_file.write(self.__class__.__name__.lower())
|
version_file.write(self.__class__.__name__.lower())
|
||||||
|
|
||||||
def _initialize(self, directory):
|
def _initialize(self, directory, username, password):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _create_schema(self):
|
def _create_schema(self):
|
||||||
|
@ -66,13 +66,14 @@ class PostgreSQL(DBAPI):
|
|||||||
})
|
})
|
||||||
return summary
|
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_file = os.path.join(directory, 'settings.ini')
|
||||||
config_mgr = ConfigManager(config_file)
|
config_mgr = ConfigManager(config_file)
|
||||||
config_mgr.register('database.dbname', '')
|
config_mgr.register('database.dbname', '')
|
||||||
config_mgr.register('database.host', '')
|
config_mgr.register('database.host', '')
|
||||||
config_mgr.register('database.user', '')
|
|
||||||
config_mgr.register('database.password', '')
|
|
||||||
config_mgr.register('database.port', '')
|
config_mgr.register('database.port', '')
|
||||||
|
|
||||||
if not os.path.exists(config_file):
|
if not os.path.exists(config_file):
|
||||||
@ -81,8 +82,6 @@ class PostgreSQL(DBAPI):
|
|||||||
dbname = file.readline().strip()
|
dbname = file.readline().strip()
|
||||||
config_mgr.set('database.dbname', dbname)
|
config_mgr.set('database.dbname', dbname)
|
||||||
config_mgr.set('database.host', config.get('database.host'))
|
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.set('database.port', config.get('database.port'))
|
||||||
config_mgr.save()
|
config_mgr.save()
|
||||||
|
|
||||||
@ -93,6 +92,10 @@ class PostgreSQL(DBAPI):
|
|||||||
value = config_mgr.get('database.' + key)
|
value = config_mgr.get('database.' + key)
|
||||||
if value:
|
if value:
|
||||||
dbkwargs[key] = value
|
dbkwargs[key] = value
|
||||||
|
if username:
|
||||||
|
dbkwargs['user'] = username
|
||||||
|
if password:
|
||||||
|
dbkwargs['password'] = password
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.dbapi = Connection(**dbkwargs)
|
self.dbapi = Connection(**dbkwargs)
|
||||||
|
@ -64,7 +64,7 @@ class SQLite(DBAPI):
|
|||||||
})
|
})
|
||||||
return summary
|
return summary
|
||||||
|
|
||||||
def _initialize(self, directory):
|
def _initialize(self, directory, username, password):
|
||||||
if directory == ':memory:':
|
if directory == ':memory:':
|
||||||
path_to_db = ':memory:'
|
path_to_db = ':memory:'
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user