-
Notifications
You must be signed in to change notification settings - Fork 222
feat: Added change passphrase dialog #1659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
jetchirag
wants to merge
14
commits into
borgbase:master
Choose a base branch
from
jetchirag:feat/change-borg-passphrase
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 9 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
d41aa5a
Added change passphrase feature
jetchirag b5c3772
Added tests for passphrase change
jetchirag 16d5c6b
Update src/vorta/assets/icons/lock.svg
jetchirag 40be85f
Update src/vorta/views/repo_tab.py
jetchirag 85ff480
Added change passphrase button tooltip for disabled state
jetchirag ddf3ecf
minor changes; edited validate function to use startwith instead of list
jetchirag 6c551c1
Merge branch 'master' into feat/change-borg-passphrase
jetchirag f96ca0f
Dynamically get version requirement in message for change-passphrase
jetchirag 9a14f3a
Merge branch 'feat/change-borg-passphrase'
jetchirag a58db2d
Changed Disabled Change Passphrase tooltip
jetchirag 8649f4d
Save password to keyring, remove old password field
jetchirag 6832b15
Use password input widget
jetchirag 8c3344e
Lint fix
jetchirag d9571d2
Set window title
jetchirag File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <ui version="4.0"> | ||
| <class>ChangeBorgPassphrase</class> | ||
| <widget class="QDialog" name="ChangeRepositoryPass"> | ||
| <property name="geometry"> | ||
| <rect> | ||
| <x>0</x> | ||
| <y>0</y> | ||
| <width>466</width> | ||
| <height>274</height> | ||
| </rect> | ||
| </property> | ||
| <property name="modal"> | ||
| <bool>true</bool> | ||
| </property> | ||
| <layout class="QGridLayout" name="gridLayout"> | ||
| <property name="verticalSpacing"> | ||
| <number>0</number> | ||
| </property> | ||
| <item row="0" column="0"> | ||
| <widget class="QLabel" name="title"> | ||
| <property name="font"> | ||
| <font> | ||
| <bold>true</bold> | ||
| </font> | ||
| </property> | ||
| <property name="text"> | ||
| <string>Change Borg Passphrase</string> | ||
| </property> | ||
| <!-- Center align horizontally --> | ||
| <property name="alignment"> | ||
| <set>Qt::AlignCenter</set> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="2" column="0"> | ||
| <!-- Single Box layout with three password inputs, current, new, confirm --> | ||
|
|
||
| <layout class="QFormLayout" name="repoDataFormLayout"> | ||
| <property name="fieldGrowthPolicy"> | ||
| <enum>QFormLayout::ExpandingFieldsGrow</enum> | ||
| </property> | ||
| <property name="leftMargin"> | ||
| <number>5</number> | ||
| </property> | ||
| <property name="topMargin"> | ||
| <number>5</number> | ||
| </property> | ||
| <property name="rightMargin"> | ||
| <number>5</number> | ||
| </property> | ||
| <property name="bottomMargin"> | ||
| <number>30</number> | ||
| </property> | ||
|
|
||
|
|
||
| <item row="1" column="0"> | ||
| <widget class="QLabel" name="oldPasswordLabel"> | ||
| <property name="text"> | ||
| <string>Old Passphrase:</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="1" column="1"> | ||
| <widget class="QLineEdit" name="oldPasswordLineEdit"> | ||
| <property name="enabled"> | ||
| <bool>true</bool> | ||
| </property> | ||
| <property name="echoMode"> | ||
| <enum>QLineEdit::Password</enum> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
|
|
||
| <item row="2" column="0"> | ||
| <widget class="QLabel" name="label_3"> | ||
| <property name="text"> | ||
| <string>New Passphrase:</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="2" column="1"> | ||
| <widget class="QLineEdit" name="passwordLineEdit"> | ||
| <property name="enabled"> | ||
| <bool>true</bool> | ||
| </property> | ||
| <property name="echoMode"> | ||
| <enum>QLineEdit::Password</enum> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="3" column="1"> | ||
| <widget class="QLineEdit" name="confirmLineEdit"> | ||
| <property name="enabled"> | ||
| <bool>true</bool> | ||
| </property> | ||
| <property name="echoMode"> | ||
| <enum>QLineEdit::Password</enum> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="3" column="0"> | ||
| <widget class="QLabel" name="confirmLabel"> | ||
| <property name="text"> | ||
| <string>Confirm Passphrase:</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="4" column="0" colspan="2"> | ||
| <widget class="QLabel" name="errorText"> | ||
| <property name="text"> | ||
| <string></string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
|
|
||
| </layout> | ||
|
|
||
|
|
||
| </item> | ||
| <item row="3" column="0"> | ||
| <widget class="QDialogButtonBox" name="buttonBox"> | ||
| <property name="standardButtons"> | ||
| <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| </layout> | ||
| </widget> | ||
| <resources /> | ||
| <connections /> | ||
| </ui> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| from typing import Any, Dict | ||
| from vorta.borg._compatibility import MIN_BORG_FOR_FEATURE | ||
| from vorta.config import LOG_DIR | ||
| from vorta.i18n import trans_late, translate | ||
| from vorta.utils import borg_compat | ||
| from .borg_job import BorgJob | ||
|
|
||
|
|
||
| class BorgChangePassJob(BorgJob): | ||
| def started_event(self): | ||
| self.app.backup_started_event.emit() | ||
| self.app.backup_progress_event.emit(self.tr('Changing Borg passphrase...')) | ||
|
|
||
| def finished_event(self, result: Dict[str, Any]): | ||
| """ | ||
| Process that the job terminated with the given results. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| result : Dict[str, Any] | ||
| The (json-like) dictionary containing the job results. | ||
| """ | ||
| self.app.backup_finished_event.emit(result) | ||
| self.result.emit(result) | ||
| if result['returncode'] != 0: | ||
| self.app.backup_progress_event.emit( | ||
| translate( | ||
| 'BorgChangePassJob', | ||
| 'Errors during changing passphrase. See the <a href="{0}">logs</a> for details.', | ||
| ).format(LOG_DIR.as_uri()) | ||
| ) | ||
| else: | ||
| self.app.backup_progress_event.emit(self.tr('Borg passphrase changed.')) | ||
|
|
||
| @classmethod | ||
| def prepare(cls, profile, oldPass, newPass): | ||
| ret = super().prepare(profile) | ||
| if not ret['ok']: | ||
| return ret | ||
| else: | ||
| ret['ok'] = False # Set back to false, so we can do our own checks here. | ||
|
|
||
| if not borg_compat.check('CHANGE_PASSPHRASE'): | ||
| ret['ok'] = False | ||
| ret['message'] = trans_late( | ||
| 'messages', 'This feature needs Borg {} or higher.'.format(MIN_BORG_FOR_FEATURE['CHANGE_PASSPHRASE']) | ||
| ) | ||
| return ret | ||
|
|
||
| cmd = ['borg', '--info', '--log-json', 'key', 'change-passphrase'] | ||
| cmd.append(f'{profile.repo.url}') | ||
|
|
||
| ret['password'] = oldPass | ||
|
real-yfprojects marked this conversation as resolved.
Outdated
|
||
| ret['additional_env'] = {'BORG_NEW_PASSPHRASE': newPass} | ||
|
|
||
| ret['ok'] = True | ||
| ret['cmd'] = cmd | ||
|
|
||
| return ret | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| from PyQt5 import QtCore, uic | ||
| from PyQt5.QtWidgets import QAction, QApplication, QDialogButtonBox, QLineEdit | ||
| from vorta.borg.change_passphrase import BorgChangePassJob | ||
| from vorta.i18n import translate | ||
| from vorta.utils import get_asset, validate_passwords | ||
| from vorta.views.utils import get_colored_icon | ||
|
|
||
| uifile = get_asset('UI/changeborgpass.ui') | ||
| ChangeBorgPassUI, ChangeBorgPassBase = uic.loadUiType(uifile) | ||
|
|
||
|
|
||
| class ChangeBorgPassphraseWindow(ChangeBorgPassBase, ChangeBorgPassUI): | ||
| change_borg_passphrase = QtCore.pyqtSignal(dict) | ||
|
|
||
| def __init__(self, profile): | ||
| super().__init__() | ||
| self.setupUi(self) | ||
| self.setAttribute(QtCore.Qt.WA_DeleteOnClose) | ||
| self.result = None | ||
| self.profile = profile | ||
|
|
||
| # dialogButtonBox | ||
| self.saveButton = self.buttonBox.button(QDialogButtonBox.StandardButton.Ok) | ||
| self.saveButton.setText(self.tr("Update")) | ||
|
|
||
| self.buttonBox.rejected.connect(self.close) | ||
| self.buttonBox.accepted.connect(self.run) | ||
| self.passwordLineEdit.textChanged.connect(self.password_listener) | ||
| self.confirmLineEdit.textChanged.connect(self.password_listener) | ||
|
|
||
| # Add clickable icon to toggle password visibility to end of box | ||
| self.showHideAction = QAction(self.tr("Show my passwords"), self) | ||
| self.showHideAction.setCheckable(True) | ||
| self.showHideAction.toggled.connect(self.set_visibility) | ||
|
|
||
| self.passwordLineEdit.addAction(self.showHideAction, QLineEdit.TrailingPosition) | ||
|
|
||
| self.set_icons() | ||
|
|
||
| def retranslateUi(self, dialog): | ||
| """Retranslate strings in ui.""" | ||
| super().retranslateUi(dialog) | ||
|
|
||
| # setupUi calls retranslateUi | ||
| if hasattr(self, 'saveButton'): | ||
| self.saveButton.setText(self.tr("Update")) | ||
|
|
||
| def set_icons(self): | ||
| self.showHideAction.setIcon(get_colored_icon("eye")) | ||
|
|
||
| def set_visibility(self, visible): | ||
| visibility = QLineEdit.Normal if visible else QLineEdit.Password | ||
| self.passwordLineEdit.setEchoMode(visibility) | ||
| self.confirmLineEdit.setEchoMode(visibility) | ||
|
|
||
| if visible: | ||
| self.showHideAction.setIcon(get_colored_icon("eye-slash")) | ||
| self.showHideAction.setText(self.tr("Hide my passwords")) | ||
| else: | ||
| self.showHideAction.setIcon(get_colored_icon("eye")) | ||
| self.showHideAction.setText(self.tr("Show my passwords")) | ||
|
|
||
| def run(self): | ||
| # if self.password_listener() and self.validate(): | ||
| if self.password_listener(): | ||
| oldPass = self.oldPasswordLineEdit.text() | ||
| newPass = self.passwordLineEdit.text() | ||
|
|
||
| params = BorgChangePassJob.prepare(self.profile, oldPass, newPass) | ||
| if params['ok']: | ||
| self.saveButton.setEnabled(False) | ||
| job = BorgChangePassJob(params['cmd'], params) | ||
| job.updated.connect(self._set_status) | ||
| job.result.connect(self.run_result) | ||
| QApplication.instance().jobs_manager.add_job(job) | ||
| else: | ||
| self._set_status(params['message']) | ||
|
|
||
| def _set_status(self, text): | ||
| self.errorText.setText(text) | ||
| self.errorText.repaint() | ||
|
|
||
| def run_result(self, result): | ||
| self.saveButton.setEnabled(True) | ||
| if result['returncode'] == 0: | ||
| self.change_borg_passphrase.emit(result) | ||
| self.accept() | ||
| else: | ||
| self._set_status(self.tr('Unable to change Borg passphrase.')) | ||
|
|
||
| def validate(self): | ||
| """Check encryption type""" | ||
| if self.profile.repo.encryption.startswith('repokey'): | ||
| return True | ||
| self.errorText.setText(translate('utils', 'Encryption type must be repokey.')) | ||
| return False | ||
|
|
||
| def password_listener(self): | ||
| '''Validates passwords only if its going to be used''' | ||
| oldPass = self.oldPasswordLineEdit.text() | ||
| firstPass = self.passwordLineEdit.text() | ||
| secondPass = self.confirmLineEdit.text() | ||
|
|
||
| # Since borg originally does not have minimum character requirement | ||
| if len(oldPass) < 1: | ||
| self.errorText.setText(translate('utils', 'Old password is required.')) | ||
| return False | ||
|
|
||
| msg = validate_passwords(firstPass, secondPass) | ||
| self.errorText.setText(translate('utils', msg)) | ||
| return not bool(msg) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| {"type": "log_message", "time": 1679134475.3384268, "message": "Key updated", "levelname": "INFO", "name": "borg.archiver"} | ||
| {"type": "log_message", "time": 1679134475.338515, "message": "Key location: /Users/chirag/Projects/vorta/repo2", "levelname": "INFO", "name": "borg.archiver"} |
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.