lockedpass-cli 0.1.0__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.
- lockedpass_cli-0.1.0/LICENSE +8 -0
- lockedpass_cli-0.1.0/PKG-INFO +107 -0
- lockedpass_cli-0.1.0/README.md +77 -0
- lockedpass_cli-0.1.0/lockedpass_cli.egg-info/PKG-INFO +107 -0
- lockedpass_cli-0.1.0/lockedpass_cli.egg-info/SOURCES.txt +15 -0
- lockedpass_cli-0.1.0/lockedpass_cli.egg-info/dependency_links.txt +1 -0
- lockedpass_cli-0.1.0/lockedpass_cli.egg-info/entry_points.txt +2 -0
- lockedpass_cli-0.1.0/lockedpass_cli.egg-info/requires.txt +6 -0
- lockedpass_cli-0.1.0/lockedpass_cli.egg-info/top_level.txt +1 -0
- lockedpass_cli-0.1.0/lp/__init__.py +2 -0
- lockedpass_cli-0.1.0/lp/__main__.py +4 -0
- lockedpass_cli-0.1.0/lp/api.py +140 -0
- lockedpass_cli-0.1.0/lp/cli.py +727 -0
- lockedpass_cli-0.1.0/lp/crypto.py +143 -0
- lockedpass_cli-0.1.0/lp/session.py +105 -0
- lockedpass_cli-0.1.0/pyproject.toml +46 -0
- lockedpass_cli-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Copyright (c) 2026 Nextcoders LLC. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
This software and its source code are proprietary and confidential.
|
|
4
|
+
Unauthorized copying, distribution, modification, or use of this software,
|
|
5
|
+
via any medium, is strictly prohibited without the express written permission
|
|
6
|
+
of Nextcoders LLC.
|
|
7
|
+
|
|
8
|
+
For licensing inquiries, contact: hello@lockedpass.com
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lockedpass-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official CLI for LockedPass — zero-knowledge password manager
|
|
5
|
+
Author-email: Nextcoders <hello@lockedpass.com>
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://lockedpass.com
|
|
8
|
+
Project-URL: Documentation, https://account.lockedpass.com/api-docs
|
|
9
|
+
Project-URL: Repository, https://github.com/nextcoders/lockedpass-cli
|
|
10
|
+
Keywords: password,manager,cli,zero-knowledge,vault,encryption
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Security :: Cryptography
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: click>=8.0
|
|
24
|
+
Requires-Dist: httpx>=0.28
|
|
25
|
+
Requires-Dist: pynacl>=1.5
|
|
26
|
+
Requires-Dist: argon2-cffi>=23.0
|
|
27
|
+
Requires-Dist: cryptography>=41.0
|
|
28
|
+
Requires-Dist: pyperclip>=1.8
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# LockedPass CLI
|
|
32
|
+
|
|
33
|
+
Official command-line interface for [LockedPass](https://lockedpass.com) — a zero-knowledge password manager for teams and AI agents.
|
|
34
|
+
|
|
35
|
+
All encryption and decryption happens **locally on your machine**. The server never sees your master password, private key, or any plaintext credential data.
|
|
36
|
+
|
|
37
|
+
## Requirements
|
|
38
|
+
|
|
39
|
+
- Python 3.11+
|
|
40
|
+
- A LockedPass account (Pro plan or higher)
|
|
41
|
+
- An active CLI token generated from **Settings → API & CLI**
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install lockedpass-cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Quick start
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
lp login you@example.com
|
|
53
|
+
# Master password: •••••••• (prompted once, then cached)
|
|
54
|
+
|
|
55
|
+
lp vault list
|
|
56
|
+
lp ls
|
|
57
|
+
lp get "GitHub"
|
|
58
|
+
lp get "GitHub" --field password
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Commands
|
|
62
|
+
|
|
63
|
+
| Command | Description |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `lp login <email>` | Authenticate — master password required once |
|
|
66
|
+
| `lp lock` | Wipe cached keys (re-prompt on next use) |
|
|
67
|
+
| `lp unlock` | Re-cache keys from master password after lock |
|
|
68
|
+
| `lp vault list` | List all vaults |
|
|
69
|
+
| `lp ls` | List credentials in default vault |
|
|
70
|
+
| `lp get <name>` | Show a credential |
|
|
71
|
+
| `lp get <name> --field password` | Print a single field (scriptable) |
|
|
72
|
+
| `lp add` | Create a credential interactively |
|
|
73
|
+
| `lp edit <name>` | Edit a credential |
|
|
74
|
+
| `lp rm <name>` | Delete a credential |
|
|
75
|
+
| `lp otp <name>` | Generate a live TOTP code |
|
|
76
|
+
| `lp generate` | Generate a random password |
|
|
77
|
+
| `lp copy <name>` | Copy password to clipboard (clears in 30s) |
|
|
78
|
+
| `lp status` | Show session status |
|
|
79
|
+
| `lp logout` | Clear saved session |
|
|
80
|
+
|
|
81
|
+
## Non-interactive / AI agent use
|
|
82
|
+
|
|
83
|
+
The master password can be passed as an argument or environment variable — useful for automation and AI agents:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Argument
|
|
87
|
+
lp login lp.aivault@example.com "$LP_AI_PASSWORD"
|
|
88
|
+
|
|
89
|
+
# Environment variable
|
|
90
|
+
LP_MASTER_PASSWORD="$LP_AI_PASSWORD" lp login lp.aivault@example.com
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
After login the session is cached — subsequent commands run without any password.
|
|
94
|
+
|
|
95
|
+
See [AGENT.md](AGENT.md) for the full AI agent setup guide.
|
|
96
|
+
|
|
97
|
+
## Security
|
|
98
|
+
|
|
99
|
+
- **Argon2id** key derivation — only a one-way hash (`auth_verifier`) is sent to the server
|
|
100
|
+
- **X25519 + XSalsa20-Poly1305** (NaCl) for vault key encryption
|
|
101
|
+
- **XSalsa20-Poly1305** for credential data encryption
|
|
102
|
+
- Private key and vault keys never leave your machine in plaintext
|
|
103
|
+
- Session cached with a random local key — wiped on `lp lock`
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
Copyright (c) 2026 Nextcoders LLC. All Rights Reserved. — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# LockedPass CLI
|
|
2
|
+
|
|
3
|
+
Official command-line interface for [LockedPass](https://lockedpass.com) — a zero-knowledge password manager for teams and AI agents.
|
|
4
|
+
|
|
5
|
+
All encryption and decryption happens **locally on your machine**. The server never sees your master password, private key, or any plaintext credential data.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Python 3.11+
|
|
10
|
+
- A LockedPass account (Pro plan or higher)
|
|
11
|
+
- An active CLI token generated from **Settings → API & CLI**
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install lockedpass-cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
lp login you@example.com
|
|
23
|
+
# Master password: •••••••• (prompted once, then cached)
|
|
24
|
+
|
|
25
|
+
lp vault list
|
|
26
|
+
lp ls
|
|
27
|
+
lp get "GitHub"
|
|
28
|
+
lp get "GitHub" --field password
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
| Command | Description |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `lp login <email>` | Authenticate — master password required once |
|
|
36
|
+
| `lp lock` | Wipe cached keys (re-prompt on next use) |
|
|
37
|
+
| `lp unlock` | Re-cache keys from master password after lock |
|
|
38
|
+
| `lp vault list` | List all vaults |
|
|
39
|
+
| `lp ls` | List credentials in default vault |
|
|
40
|
+
| `lp get <name>` | Show a credential |
|
|
41
|
+
| `lp get <name> --field password` | Print a single field (scriptable) |
|
|
42
|
+
| `lp add` | Create a credential interactively |
|
|
43
|
+
| `lp edit <name>` | Edit a credential |
|
|
44
|
+
| `lp rm <name>` | Delete a credential |
|
|
45
|
+
| `lp otp <name>` | Generate a live TOTP code |
|
|
46
|
+
| `lp generate` | Generate a random password |
|
|
47
|
+
| `lp copy <name>` | Copy password to clipboard (clears in 30s) |
|
|
48
|
+
| `lp status` | Show session status |
|
|
49
|
+
| `lp logout` | Clear saved session |
|
|
50
|
+
|
|
51
|
+
## Non-interactive / AI agent use
|
|
52
|
+
|
|
53
|
+
The master password can be passed as an argument or environment variable — useful for automation and AI agents:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Argument
|
|
57
|
+
lp login lp.aivault@example.com "$LP_AI_PASSWORD"
|
|
58
|
+
|
|
59
|
+
# Environment variable
|
|
60
|
+
LP_MASTER_PASSWORD="$LP_AI_PASSWORD" lp login lp.aivault@example.com
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
After login the session is cached — subsequent commands run without any password.
|
|
64
|
+
|
|
65
|
+
See [AGENT.md](AGENT.md) for the full AI agent setup guide.
|
|
66
|
+
|
|
67
|
+
## Security
|
|
68
|
+
|
|
69
|
+
- **Argon2id** key derivation — only a one-way hash (`auth_verifier`) is sent to the server
|
|
70
|
+
- **X25519 + XSalsa20-Poly1305** (NaCl) for vault key encryption
|
|
71
|
+
- **XSalsa20-Poly1305** for credential data encryption
|
|
72
|
+
- Private key and vault keys never leave your machine in plaintext
|
|
73
|
+
- Session cached with a random local key — wiped on `lp lock`
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
Copyright (c) 2026 Nextcoders LLC. All Rights Reserved. — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lockedpass-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official CLI for LockedPass — zero-knowledge password manager
|
|
5
|
+
Author-email: Nextcoders <hello@lockedpass.com>
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://lockedpass.com
|
|
8
|
+
Project-URL: Documentation, https://account.lockedpass.com/api-docs
|
|
9
|
+
Project-URL: Repository, https://github.com/nextcoders/lockedpass-cli
|
|
10
|
+
Keywords: password,manager,cli,zero-knowledge,vault,encryption
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Security :: Cryptography
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: click>=8.0
|
|
24
|
+
Requires-Dist: httpx>=0.28
|
|
25
|
+
Requires-Dist: pynacl>=1.5
|
|
26
|
+
Requires-Dist: argon2-cffi>=23.0
|
|
27
|
+
Requires-Dist: cryptography>=41.0
|
|
28
|
+
Requires-Dist: pyperclip>=1.8
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# LockedPass CLI
|
|
32
|
+
|
|
33
|
+
Official command-line interface for [LockedPass](https://lockedpass.com) — a zero-knowledge password manager for teams and AI agents.
|
|
34
|
+
|
|
35
|
+
All encryption and decryption happens **locally on your machine**. The server never sees your master password, private key, or any plaintext credential data.
|
|
36
|
+
|
|
37
|
+
## Requirements
|
|
38
|
+
|
|
39
|
+
- Python 3.11+
|
|
40
|
+
- A LockedPass account (Pro plan or higher)
|
|
41
|
+
- An active CLI token generated from **Settings → API & CLI**
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install lockedpass-cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Quick start
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
lp login you@example.com
|
|
53
|
+
# Master password: •••••••• (prompted once, then cached)
|
|
54
|
+
|
|
55
|
+
lp vault list
|
|
56
|
+
lp ls
|
|
57
|
+
lp get "GitHub"
|
|
58
|
+
lp get "GitHub" --field password
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Commands
|
|
62
|
+
|
|
63
|
+
| Command | Description |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `lp login <email>` | Authenticate — master password required once |
|
|
66
|
+
| `lp lock` | Wipe cached keys (re-prompt on next use) |
|
|
67
|
+
| `lp unlock` | Re-cache keys from master password after lock |
|
|
68
|
+
| `lp vault list` | List all vaults |
|
|
69
|
+
| `lp ls` | List credentials in default vault |
|
|
70
|
+
| `lp get <name>` | Show a credential |
|
|
71
|
+
| `lp get <name> --field password` | Print a single field (scriptable) |
|
|
72
|
+
| `lp add` | Create a credential interactively |
|
|
73
|
+
| `lp edit <name>` | Edit a credential |
|
|
74
|
+
| `lp rm <name>` | Delete a credential |
|
|
75
|
+
| `lp otp <name>` | Generate a live TOTP code |
|
|
76
|
+
| `lp generate` | Generate a random password |
|
|
77
|
+
| `lp copy <name>` | Copy password to clipboard (clears in 30s) |
|
|
78
|
+
| `lp status` | Show session status |
|
|
79
|
+
| `lp logout` | Clear saved session |
|
|
80
|
+
|
|
81
|
+
## Non-interactive / AI agent use
|
|
82
|
+
|
|
83
|
+
The master password can be passed as an argument or environment variable — useful for automation and AI agents:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Argument
|
|
87
|
+
lp login lp.aivault@example.com "$LP_AI_PASSWORD"
|
|
88
|
+
|
|
89
|
+
# Environment variable
|
|
90
|
+
LP_MASTER_PASSWORD="$LP_AI_PASSWORD" lp login lp.aivault@example.com
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
After login the session is cached — subsequent commands run without any password.
|
|
94
|
+
|
|
95
|
+
See [AGENT.md](AGENT.md) for the full AI agent setup guide.
|
|
96
|
+
|
|
97
|
+
## Security
|
|
98
|
+
|
|
99
|
+
- **Argon2id** key derivation — only a one-way hash (`auth_verifier`) is sent to the server
|
|
100
|
+
- **X25519 + XSalsa20-Poly1305** (NaCl) for vault key encryption
|
|
101
|
+
- **XSalsa20-Poly1305** for credential data encryption
|
|
102
|
+
- Private key and vault keys never leave your machine in plaintext
|
|
103
|
+
- Session cached with a random local key — wiped on `lp lock`
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
Copyright (c) 2026 Nextcoders LLC. All Rights Reserved. — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
lockedpass_cli.egg-info/PKG-INFO
|
|
5
|
+
lockedpass_cli.egg-info/SOURCES.txt
|
|
6
|
+
lockedpass_cli.egg-info/dependency_links.txt
|
|
7
|
+
lockedpass_cli.egg-info/entry_points.txt
|
|
8
|
+
lockedpass_cli.egg-info/requires.txt
|
|
9
|
+
lockedpass_cli.egg-info/top_level.txt
|
|
10
|
+
lp/__init__.py
|
|
11
|
+
lp/__main__.py
|
|
12
|
+
lp/api.py
|
|
13
|
+
lp/cli.py
|
|
14
|
+
lp/crypto.py
|
|
15
|
+
lp/session.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lp
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""HTTP client for the LockedPass API."""
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
_DEFAULT_TIMEOUT = 15
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class APIError(Exception):
|
|
9
|
+
def __init__(self, status: int, detail: str):
|
|
10
|
+
super().__init__(detail)
|
|
11
|
+
self.status = status
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def from_response(cls, r: httpx.Response) -> "APIError":
|
|
15
|
+
try:
|
|
16
|
+
d = r.json()
|
|
17
|
+
detail = d.get("detail", f"HTTP {r.status_code}")
|
|
18
|
+
if isinstance(detail, list):
|
|
19
|
+
detail = "; ".join(e.get("msg", str(e)) for e in detail)
|
|
20
|
+
except Exception:
|
|
21
|
+
detail = f"HTTP {r.status_code}"
|
|
22
|
+
return cls(r.status_code, str(detail))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Client:
|
|
26
|
+
def __init__(self, base_url: str, token: str | None = None):
|
|
27
|
+
self.base_url = base_url.rstrip("/")
|
|
28
|
+
self.token = token
|
|
29
|
+
|
|
30
|
+
def _headers(self) -> dict:
|
|
31
|
+
h = {"Content-Type": "application/json"}
|
|
32
|
+
if self.token:
|
|
33
|
+
h["Authorization"] = f"Bearer {self.token}"
|
|
34
|
+
return h
|
|
35
|
+
|
|
36
|
+
def _check(self, r: httpx.Response) -> httpx.Response:
|
|
37
|
+
if not r.is_success:
|
|
38
|
+
raise APIError.from_response(r)
|
|
39
|
+
return r
|
|
40
|
+
|
|
41
|
+
def get(self, path: str) -> dict:
|
|
42
|
+
r = httpx.get(f"{self.base_url}{path}", headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
|
|
43
|
+
return self._check(r).json()
|
|
44
|
+
|
|
45
|
+
def post(self, path: str, body: dict) -> dict | None:
|
|
46
|
+
r = httpx.post(f"{self.base_url}{path}", json=body, headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
|
|
47
|
+
self._check(r)
|
|
48
|
+
return r.json() if r.status_code != 204 else None
|
|
49
|
+
|
|
50
|
+
def patch(self, path: str, body: dict) -> dict:
|
|
51
|
+
r = httpx.patch(f"{self.base_url}{path}", json=body, headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
|
|
52
|
+
return self._check(r).json()
|
|
53
|
+
|
|
54
|
+
def delete(self, path: str) -> None:
|
|
55
|
+
r = httpx.delete(f"{self.base_url}{path}", headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
|
|
56
|
+
self._check(r)
|
|
57
|
+
|
|
58
|
+
# ── Auth ─────────────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
def login_init(self, email: str) -> dict:
|
|
61
|
+
return self.post("/api/v1/auth/login/init", {"email": email})
|
|
62
|
+
|
|
63
|
+
def cli_login(self, email: str, auth_verifier: str) -> dict:
|
|
64
|
+
"""Authenticate and get a 30-day CLI token."""
|
|
65
|
+
return self.post("/api/v1/auth/cli/token", {"email": email, "auth_verifier": auth_verifier})
|
|
66
|
+
|
|
67
|
+
def me(self) -> dict:
|
|
68
|
+
return self.get("/api/v1/cli/me")
|
|
69
|
+
|
|
70
|
+
# ── Vaults ───────────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
def list_vaults(self) -> list:
|
|
73
|
+
"""Returns vaults with embedded members (no extra request needed)."""
|
|
74
|
+
return self.get("/api/v1/cli/vaults")
|
|
75
|
+
|
|
76
|
+
def create_vault(self, name_encrypted: str, vault_type: str, encrypted_vault_key: str) -> dict:
|
|
77
|
+
return self.post("/api/v1/vaults", {
|
|
78
|
+
"name_encrypted": name_encrypted,
|
|
79
|
+
"type": vault_type,
|
|
80
|
+
"encrypted_vault_key": encrypted_vault_key,
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
# ── Credentials ──────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
def list_credentials(self, vault_id: str, limit: int = 2000) -> list:
|
|
86
|
+
return self.get(f"/api/v1/cli/vaults/{vault_id}/credentials?limit={limit}")
|
|
87
|
+
|
|
88
|
+
def list_all_credentials(self, vault_id: str) -> list:
|
|
89
|
+
PAGE, skip, all_creds = 2000, 0, []
|
|
90
|
+
while True:
|
|
91
|
+
page = self.get(f"/api/v1/cli/vaults/{vault_id}/credentials?skip={skip}&limit={PAGE}")
|
|
92
|
+
all_creds.extend(page)
|
|
93
|
+
if len(page) < PAGE:
|
|
94
|
+
break
|
|
95
|
+
skip += PAGE
|
|
96
|
+
return all_creds
|
|
97
|
+
|
|
98
|
+
def get_credential_with_key(self, cred_id: str) -> dict:
|
|
99
|
+
"""Single request — returns credential + vault_key_encrypted."""
|
|
100
|
+
return self.get(f"/api/v1/cli/credentials/{cred_id}")
|
|
101
|
+
|
|
102
|
+
def create_credential(self, vault_id: str, cred_type: str, name_enc: str, data_enc: str) -> dict:
|
|
103
|
+
return self.post("/api/v1/cli/credentials", {
|
|
104
|
+
"vault_id": vault_id,
|
|
105
|
+
"type": cred_type,
|
|
106
|
+
"name_encrypted": name_enc,
|
|
107
|
+
"encrypted_data": data_enc,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
def update_credential(self, vault_id: str, cred_id: str, name_enc: str, data_enc: str) -> dict:
|
|
111
|
+
return self.patch(f"/api/v1/vaults/{vault_id}/credentials/{cred_id}", {
|
|
112
|
+
"name_encrypted": name_enc,
|
|
113
|
+
"encrypted_data": data_enc,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
def delete_credential(self, vault_id: str, cred_id: str) -> None:
|
|
117
|
+
self.delete(f"/api/v1/vaults/{vault_id}/credentials/{cred_id}")
|
|
118
|
+
|
|
119
|
+
def get_otp_secret(self, cred_id: str) -> dict:
|
|
120
|
+
return self.get(f"/api/v1/cli/otps/{cred_id}/secret")
|
|
121
|
+
|
|
122
|
+
def generate_password(self, length: int = 20, upper: bool = True, lower: bool = True,
|
|
123
|
+
numbers: bool = True, symbols: bool = True) -> str:
|
|
124
|
+
r = self.get(
|
|
125
|
+
f"/api/v1/cli/generate-password?length={length}"
|
|
126
|
+
f"&upper={str(upper).lower()}&lower={str(lower).lower()}"
|
|
127
|
+
f"&numbers={str(numbers).lower()}&symbols={str(symbols).lower()}"
|
|
128
|
+
)
|
|
129
|
+
return r["password"]
|
|
130
|
+
|
|
131
|
+
def log_action(self, vault_id: str, cred_id: str, action: str) -> None:
|
|
132
|
+
try:
|
|
133
|
+
self.post(f"/api/v1/vaults/{vault_id}/credentials/{cred_id}/log", {"action": action})
|
|
134
|
+
except Exception:
|
|
135
|
+
pass # non-critical
|
|
136
|
+
|
|
137
|
+
# ── Users ────────────────────────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
def lookup_user(self, email: str) -> dict:
|
|
140
|
+
return self.get(f"/api/v1/users/lookup?email={email}")
|