Make backup of config when upgrading

Fixes #307
This commit is contained in:
Manuel Ebert 2015-04-04 18:36:34 +11:00
parent 2615070df0
commit c0ec95679b
4 changed files with 39 additions and 20 deletions

View file

@ -26,7 +26,12 @@ class EncryptedJournal(Journal.Journal):
super(EncryptedJournal, self).__init__(name, **kwargs)
self.config['encrypt'] = True
def _load(self, filename):
def _load(self, filename, password=None):
"""Loads an encrypted journal from a file and tries to decrypt it.
If password is not provided, will look for password in the keychain
and otherwise ask the user to enter a password up to three times.
If the password is provided but wrong (or corrupt), this will simply
return None."""
with open(filename) as f:
journal_encrypted = f.read()
@ -36,7 +41,8 @@ class EncryptedJournal(Journal.Journal):
return Fernet(key).decrypt(journal_encrypted).decode('utf-8')
except (InvalidToken, IndexError):
return None
if password:
return validate_password(password)
return util.get_password(keychain=self.name, validator=validate_password)
def _store(self, filename, text):

View file

@ -153,7 +153,7 @@ def run(manual_args=None):
util.prnt(u"Journals defined in {}".format(install.CONFIG_FILE_PATH))
ml = min(max(len(k) for k in config['journals']), 20)
for journal, cfg in config['journals'].items():
print " * {:{}} -> {}".format(journal, ml, cfg['journal'] if isinstance(cfg, dict) else cfg)
print(" * {:{}} -> {}".format(journal, ml, cfg['journal'] if isinstance(cfg, dict) else cfg))
sys.exit(0)
log.debug('Using configuration "%s"', config)

View file

@ -63,7 +63,7 @@ def upgrade_config(config):
for key in missing_keys:
config[key] = default_config[key]
save_config(config)
print("[.jrnl_conf updated to newest version]")
print("[.jrnl_conf updated to newest version at {}]".format(CONFIG_FILE_PATH))
def save_config(config):

View file

@ -12,8 +12,6 @@ from cryptography.fernet import Fernet
def upgrade_encrypted_journal(filename, key_plain):
"""Decrypts a journal in memory using the jrnl 1.x encryption scheme
and returns it in plain text."""
util.prompt("UPGRADING JOURNAL")
print "UPGRADING SHIT", filename, key_plain
with open(filename) as f:
iv_cipher = f.read()
iv, cipher = iv_cipher[:16], iv_cipher[16:]
@ -27,10 +25,8 @@ def upgrade_encrypted_journal(filename, key_plain):
else:
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
plain = unpadder.update(plain_padded) + unpadder.finalize()
except IndexError:
print "UH NO"
except ValueError:
return None
print "PLain", plain
key = EncryptedJournal.make_key(key_plain)
journal = Fernet(key).encrypt(plain)
with open(filename, 'w') as f:
@ -40,17 +36,27 @@ def upgrade_encrypted_journal(filename, key_plain):
def upgrade_jrnl_if_necessary(config_path):
with open(config_path) as f:
config = f.read()
if not config.strip().startswith("{"):
config_file = f.read()
if not config_file.strip().startswith("{"):
return
config = util.load_config(config_path)
util.prompt("""Welcome to jrnl {}
jrnl will now upgrade your configuration and journal files.
Please note that jrnl 1.x is NOT forward compatible with this version of jrnl.
If you choose to proceed, you will not be able to use your journals with
older versions of jrnl anymore.""".format(__version__))
util.prompt("""Welcome to jrnl {}.
It looks like you've been using an older version of jrnl until now. That's
okay - jrnl will now upgrade your configuration and journal files. Afterwards
you can enjoy all of the great new features that come with jrnl 2:
- Support for storing your journal in multiple files
- Faster reading and writing for large journals
- New encryption back-end that makes installing jrnl much easier
- Tons of bug fixes
Please note that jrnl 1.x is NOT forward compatible with this version of jrnl.
If you choose to proceed, you will not be able to use your journals with
older versions of jrnl anymore.
""".format(__version__))
encrypted_journals = {}
plain_journals = {}
@ -66,13 +72,14 @@ def upgrade_jrnl_if_necessary(config_path):
else:
plain_journals[journal] = journal_conf
if encrypted_journals:
util.prompt("Following encrypted journals will be upgraded to jrnl {}:".format(__version__))
longest_journal_name = max([len(journal) for journal in config['journals']])
util.prompt("\nFollowing encrypted journals will be upgraded to jrnl {}:".format(__version__))
for journal, path in encrypted_journals.items():
util.prompt(" {:20} -> {}".format(journal, path))
util.prompt(" {:{pad}} -> {}".format(journal, path, pad=longest_journal_name))
if plain_journals:
util.prompt("Following plain text journals will be not be touched:")
util.prompt("\nFollowing plain text journals will be not be touched:")
for journal, path in plain_journals.items():
util.prompt(" {:20} -> {}".format(journal, path))
util.prompt(" {:{pad}} -> {}".format(journal, path, pad=longest_journal_name))
cont = util.yesno("Continue upgrading jrnl?", default=False)
if not cont:
@ -82,3 +89,9 @@ def upgrade_jrnl_if_necessary(config_path):
for journal, path in encrypted_journals.items():
util.prompt("Enter password for {} journal (stored in {}).".format(journal, path))
util.get_password(keychain=journal, validator=lambda pwd: upgrade_encrypted_journal(path, pwd))
with open(config_path + ".backup", 'w') as config_backup:
config_backup.write(config_file)
util.prompt("""\n\nYour old config has been backed up to {}.backup.
We're all done here and you can start enjoying jrnl 2.""".format(config_path))