diff --git a/bitwardenBackup.py b/bitwardenBackup.py index 664303a..cec3859 100644 --- a/bitwardenBackup.py +++ b/bitwardenBackup.py @@ -57,16 +57,16 @@ def build_logger(level): def write_config_file(array, config_file): logger.debug("Starting to write config file and encrypt contents") logger.debug("Using config file: {}".format(config_file)) - logger.debug("Converting array to json") + logger.debug("Converting config from array to json") array_json = json.dumps(array) - logger.debug("Encrypting json") + logger.debug("Encrypting config json") encrypted_array_json = encrypt(client, array_json) logger.debug("Attempting to write encrypted config to file") try: f = open(config_file, "w") f.write(encrypted_array_json) f.close() - logger.debug("Succesffully wrote encrypted config to file") + logger.debug("Successfully wrote encrypted config to file") except Exception as e: logger.error("Unable to write encrypted config to file. Error: {}".format(e)) sys.exit(-1) @@ -75,20 +75,35 @@ def write_config_file(array, config_file): def read_config_file(config_file): logger.debug("Starting to read config file and decrypt contents") logger.debug("Using config file: {}".format(config_file)) - logger.debug("Attempting to read encrypted config to file") + logger.debug("Attempting to read encrypted config from file") try: with open(config_file) as f: config = f.read() + logger.debug("Successfully read encrypted config from file") except Exception as e: - logger.error("Unable to read encrypted config to file. Error: {}".format(e)) + logger.error("Unable to read encrypted config from file. Error: {}".format(e)) sys.exit(-1) - logger.debug("Decrypting config file") + logger.debug("Decrypting config contents") decrypted_array_json = decrypt(client, config) - logger.debug("Convert json to array") + logger.debug("Convert config from json to array") array = json.loads(decrypted_array_json) logger.debug("Finished reading config file and decrypting contents") return array +def ask_for_confirmation(question): + logger.debug("Asking user for confirmation") + logger.debug("Question: {}".format(question)) + print(question) + confirmation = input("y/n> ") + while True: + logger.debug("User answered: {}".format(confirmation)) + if confirmation.casefold() == "y": + return True + elif confirmation.casefold() == "n": + return False + else: + print("This value must be one of the following characters: y, n.") + def create_encryption_key(client): # Create an encryption key. try: @@ -229,7 +244,7 @@ def does_file_exist(filepath): return os.path.exists(filepath) def ask_for_account_details(): - print("Requesting account details to build the ini file.") + print("Requesting account details to add to config.") account_email_address = input("Please enter Bitwarden account email address: ") account_api_client_id = input("Please enter Bitwarden account API client ID: ") while True: @@ -254,6 +269,47 @@ def ask_for_account_details(): array[account_email_address]["account_vault_password"] = account_vault_password return array +def edit_account_details(accounts, email): + if ask_for_confirmation("Would you like to edit the Bitwarden account email address?\nCurrent Value: {}".format(email)): + account_email_address = input("Please enter Bitwarden account email address: ") + else: + account_email_address = email + + if ask_for_confirmation("Would you like to edit the Bitwarden account API client ID?\nCurrent Value: {}".format(accounts[email]['account_api_client_id'])): + account_api_client_id = input("Please enter Bitwarden account API client ID: ") + else: + account_api_client_id = accounts[email]['account_api_client_id'] + + if ask_for_confirmation("Would you like to edit the Bitwarden account API secret?"): + while True: + account_api_secret = getpass.getpass("Please enter Bitwarden account API secret: ") + account_api_secret2 = getpass.getpass("Please confirm Bitwarden account API secret: ") + if account_api_secret == account_api_secret2: + break + else: + print("The Bitwarden account API secrets do not match, please try again.") + else: + account_api_secret = accounts[email]['account_api_secret'] + + if ask_for_confirmation("Would you like to edit the Bitwarden account vault password?"): + while True: + account_vault_password = getpass.getpass("Please enter Bitwarden account vault password: ") + account_vault_password2 = getpass.getpass("Please confirm Bitwarden account vault password: ") + if account_vault_password == account_vault_password2: + break + else: + print("The Bitwarden account vault passwords do not match, please try again.") + else: + account_vault_password = accounts[email]['account_vault_password'] + + array = dict() + array[account_email_address] = dict() + array[account_email_address]["account_api_client_id"] = account_api_client_id + array[account_email_address]["account_api_secret"] = account_api_secret + array[account_email_address]["account_vault_password"] = account_vault_password + return array + + def select_account(accounts, wording = "edit"): print("Which account would you like to {}:".format(wording)) emails = list(accounts) @@ -366,28 +422,35 @@ if __name__ == "__main__": print("q) Quit config") while True: user_input = input("e/n/d/q> ") + # Editing an account if user_input.casefold() == "e": - account_section_to_edit = select_account(accounts) - + account_to_edit = select_account(accounts) + account_details = edit_account_details(accounts, account_to_edit) + del accounts[account_to_edit] + accounts.update(account_details) + write_config_file(accounts, secrets_config_file) + break + # Createing a new account elif user_input.casefold() == "n": account_details = ask_for_account_details() accounts.update(account_details) write_config_file(accounts, secrets_config_file) break - + + # Deleting an account elif user_input.casefold() == "d": account_to_delete = select_account(accounts, "delete") - print("Are you sure you wish to delete {} account? ".format(account_to_delete)) - confirmation = input("y/n> ") - if not confirmation.casefold() in ["y","yes"]: + if not ask_for_confirmation("Are you sure you wish to delete {} account? ".format(account_to_delete)): break del accounts[account_to_delete] write_config_file(accounts, secrets_config_file) break + # Quit the config elif user_input.casefold() == "q": sys.exit(0) + # Catch all for non-valid characters else: print("This value must be one of the following characters: e, n, d, q.") client.close()