diff --git a/README.md b/README.md index 263d6f1..693b4f8 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ encrypted file. There is no account and no service behind it: it works entirely offline, and if you want two PCs in step you run the sync server yourself, on your own hardware. -**Version 0.3.0 — early.** It installs from a `.deb` on Ubuntu 22.04 or +**Version 0.6.0 — early.** It installs from a `.deb` on Ubuntu 22.04 or newer, or runs from source. It has so far been tested in CI only, on a virtual display, not yet on a real desktop. @@ -19,7 +19,8 @@ virtual display, not yet on a real desktop. | [PassMan-Server-Linux](https://github.com/usermaneGermane/PassMan-Server-Linux) | the sync server for Linux, run by systemd | **Same vaults as on Windows.** The vault file, the sync protocol and the -features are those of PassMan for Windows 2.4.0, which this was ported from. +features match PassMan for Windows 2.8.0, except the 2.7.0 redesign, which is +not ported yet (see *What is different from Windows*). A vault moves between a Windows PC and a Linux PC unchanged, and both sync with either server. @@ -107,6 +108,7 @@ screen if you sync. - **Clipboard.** PassMan uses Tk's own clipboard, so nothing like `xclip` needs installing. It works on X11 and, through XWayland, on Wayland. On X11 what PassMan copied disappears when PassMan closes. As on Windows, + locking leaves a copied password pasteable, closing clears it at once, and copied passwords are cleared after 30 seconds — but a clipboard manager (GNOME or KDE clipboard history, CopyQ, …) may keep its own copy, which no application can reach. @@ -130,6 +132,8 @@ Where that README names a Windows version, read the Linux one beside it: | 2.4.0 | 0.3.0 | deleting archived entries after N days | | 2.5.0 | 0.4.0 | switching servers no longer removes entries silently | | 2.6.0 | 0.5.0 | a copy that is not installed says LAB in its title | +| 2.7.0 | not yet | the redesigned window | +| 2.8.0 | 0.6.0 | locking no longer clears a copied password | (0.2.0 added the `.deb` package, which has no Windows counterpart.) diff --git a/sourceFiles/gui.py b/sourceFiles/gui.py index 914e652..37f76ff 100644 --- a/sourceFiles/gui.py +++ b/sourceFiles/gui.py @@ -846,10 +846,8 @@ def lock_vault(self, auto=False): self._cancel_idle_timer() if self.master_password and self.current_user: self._save() - if self._clip_text is not None: - if self._clip_job: - self.root.after_cancel(self._clip_job) - self._clear_clipboard(self._clip_text, quiet=True) + # A copied password outlives the lock: the usual auto-clear timer + # keeps running, so it can still be pasted until that fires. self.vault = self.master_password = self.current_user = None self._history_open.clear() self.search_query = "" diff --git a/sourceFiles/tests/test_clipboard_lock.py b/sourceFiles/tests/test_clipboard_lock.py new file mode 100644 index 0000000..1a9b706 --- /dev/null +++ b/sourceFiles/tests/test_clipboard_lock.py @@ -0,0 +1,58 @@ +""" +Locking the vault leaves a copied password on the clipboard. + +The auto-clear timer started by the copy keeps running, so the password can +still be pasted after a lock until that timer fires. +""" + +import pytest + +gui = pytest.importorskip("gui", reason="needs tkinter (bundled with Python)") + + +class FakeRoot: + def __init__(self): + self.cancelled = [] + + def after_cancel(self, job): + self.cancelled.append(job) + + +class FakeApp: + """Just enough of PasswordManagerGUI for lock_vault to run.""" + + lock_vault = gui.PasswordManagerGUI.lock_vault + + def __init__(self): + self.root = FakeRoot() + self.master_password = None # nothing unlocked → no save + self.current_user = None + self.vault = {} + self._clip_text = "s3cret" + self._clip_job = "clear-job" + self.cleared = [] + self._history_open = set() + + def _cancel_idle_timer(self): + pass + + def show_login_screen(self): + pass + + def toast(self, message, kind="info"): + pass + + def _clear_clipboard(self, expected, quiet=False): + self.cleared.append(expected) + + +@pytest.mark.parametrize("auto", [False, True]) +def test_lock_keeps_the_copied_password_and_its_timer(auto): + app = FakeApp() + + app.lock_vault(auto=auto) + + assert app.cleared == [] + assert app.root.cancelled == [] + assert app._clip_job == "clear-job" + assert app._clip_text == "s3cret" diff --git a/sourceFiles/version.py b/sourceFiles/version.py index 7affa5b..e8e8c7c 100644 --- a/sourceFiles/version.py +++ b/sourceFiles/version.py @@ -6,7 +6,7 @@ format changes. """ -__version__ = "0.5.0" +__version__ = "0.6.0" #: Container version PassMan writes today (see crypto_utils.MAGIC). VAULT_FORMAT = "PMV2"