basic-password-manager 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (16) hide show
  1. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/PKG-INFO +3 -1
  2. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/README.md +2 -0
  3. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/basic_password_manager.egg-info/PKG-INFO +3 -1
  4. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/pw_manager/tui.py +51 -1
  5. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/pyproject.toml +1 -1
  6. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/LICENSE +0 -0
  7. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/basic_password_manager.egg-info/SOURCES.txt +0 -0
  8. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/basic_password_manager.egg-info/dependency_links.txt +0 -0
  9. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/basic_password_manager.egg-info/entry_points.txt +0 -0
  10. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/basic_password_manager.egg-info/requires.txt +0 -0
  11. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/basic_password_manager.egg-info/top_level.txt +0 -0
  12. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/pw_manager/__init__.py +0 -0
  13. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/pw_manager/cli.py +0 -0
  14. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/pw_manager/crypto.py +0 -0
  15. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/pw_manager/vault.py +0 -0
  16. {basic_password_manager-0.2.0 → basic_password_manager-0.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-password-manager
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Local encrypted password manager that lives in your terminal
5
5
  License-Expression: MIT
6
6
  Project-URL: Repository, https://github.com/Daisentaur/password-manager
@@ -48,6 +48,8 @@ For development: `python3 -m venv venv && ./venv/bin/pip install -e .`
48
48
  Run `pw` with no arguments for the interactive TUI: unlock, then `/` to
49
49
  filter, Enter to copy the selected password, `n` to add, `e` to edit,
50
50
  `d` to delete, `t` to switch themes (persisted across runs), `q` to quit.
51
+ Rarer operations live in the command palette (`ctrl+p`), e.g. changing the
52
+ master password.
51
53
  The bundled themes — muted-slate (default), dawn, matrix — are borrowed with
52
54
  admiration from [tuxedo](https://github.com/webstonehq/tuxedo); Textual's
53
55
  built-in themes are in the picker too.
@@ -34,6 +34,8 @@ For development: `python3 -m venv venv && ./venv/bin/pip install -e .`
34
34
  Run `pw` with no arguments for the interactive TUI: unlock, then `/` to
35
35
  filter, Enter to copy the selected password, `n` to add, `e` to edit,
36
36
  `d` to delete, `t` to switch themes (persisted across runs), `q` to quit.
37
+ Rarer operations live in the command palette (`ctrl+p`), e.g. changing the
38
+ master password.
37
39
  The bundled themes — muted-slate (default), dawn, matrix — are borrowed with
38
40
  admiration from [tuxedo](https://github.com/webstonehq/tuxedo); Textual's
39
41
  built-in themes are in the picker too.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-password-manager
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Local encrypted password manager that lives in your terminal
5
5
  License-Expression: MIT
6
6
  Project-URL: Repository, https://github.com/Daisentaur/password-manager
@@ -48,6 +48,8 @@ For development: `python3 -m venv venv && ./venv/bin/pip install -e .`
48
48
  Run `pw` with no arguments for the interactive TUI: unlock, then `/` to
49
49
  filter, Enter to copy the selected password, `n` to add, `e` to edit,
50
50
  `d` to delete, `t` to switch themes (persisted across runs), `q` to quit.
51
+ Rarer operations live in the command palette (`ctrl+p`), e.g. changing the
52
+ master password.
51
53
  The bundled themes — muted-slate (default), dawn, matrix — are borrowed with
52
54
  admiration from [tuxedo](https://github.com/webstonehq/tuxedo); Textual's
53
55
  built-in themes are in the picker too.
@@ -6,8 +6,9 @@ and Textual's own built-in themes are available there too.
6
6
  """
7
7
 
8
8
  import os
9
+ from typing import Iterable
9
10
 
10
- from textual.app import App, ComposeResult
11
+ from textual.app import App, ComposeResult, SystemCommand
11
12
  from textual.binding import Binding
12
13
  from textual.containers import Vertical
13
14
  from textual.screen import ModalScreen, Screen
@@ -125,6 +126,37 @@ class EntryModal(ModalScreen):
125
126
  )
126
127
 
127
128
 
129
+ class PasswdModal(ModalScreen):
130
+ """Change the master password. Asks for the current one again so a
131
+ walked-up-to unlocked session can't lock the real owner out."""
132
+
133
+ BINDINGS = [Binding("escape", "dismiss", "cancel")]
134
+
135
+ def compose(self) -> ComposeResult:
136
+ with Vertical(classes="modal-box"):
137
+ yield Label("change master password", classes="modal-title")
138
+ yield Input(password=True, placeholder="current master password", id="p-current")
139
+ yield Input(password=True, placeholder="new master password (8+ chars)", id="p-new")
140
+ yield Input(password=True, placeholder="confirm new master password", id="p-confirm")
141
+ yield Static("enter saves · esc cancels", classes="modal-hint")
142
+ yield Static("", id="p-error")
143
+
144
+ def on_input_submitted(self, event: Input.Submitted) -> None:
145
+ current = self.query_one("#p-current", Input).value
146
+ new = self.query_one("#p-new", Input).value
147
+ error = self.query_one("#p-error", Static)
148
+ if current != self.app.master:
149
+ error.update("current master password is wrong")
150
+ return
151
+ if len(new) < 8:
152
+ error.update("new master password must be at least 8 characters")
153
+ return
154
+ if new != self.query_one("#p-confirm", Input).value:
155
+ error.update("new passwords do not match")
156
+ return
157
+ self.dismiss(new)
158
+
159
+
128
160
  class ConfirmModal(ModalScreen):
129
161
  """y/n confirmation."""
130
162
 
@@ -340,6 +372,24 @@ class PwApp(App):
340
372
  with open(THEME_FILE, "w") as f:
341
373
  f.write(theme.name)
342
374
 
375
+ def get_system_commands(self, screen: Screen) -> Iterable[SystemCommand]:
376
+ yield from super().get_system_commands(screen)
377
+ if isinstance(screen, MainScreen):
378
+ yield SystemCommand(
379
+ "Change master password",
380
+ "re-encrypt the vault under a new master password",
381
+ self._change_master,
382
+ )
383
+
384
+ def _change_master(self) -> None:
385
+ def done(new: str | None) -> None:
386
+ if new:
387
+ self.master = new
388
+ vault.save(VAULT_PATH, self.master, self.entries)
389
+ self.notify("master password changed (old one is now useless)")
390
+
391
+ self.push_screen(PasswdModal(), done)
392
+
343
393
 
344
394
  def main() -> None:
345
395
  PwApp().run()
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "basic-password-manager"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Local encrypted password manager that lives in your terminal"
9
9
  readme = "README.md"
10
10
  license = "MIT"