From 3632df4758bcd34a0e95bc816283f5f00723d9cc Mon Sep 17 00:00:00 2001 From: Nemirtingas <9432037+Nemirtingas@users.noreply.github.com> Date: Fri, 29 May 2026 13:51:55 +0000 Subject: [PATCH 1/2] Modify Bitwarden client to handle missing email Remove email parameter requirement and fetch email if not provided. --- src/vaultwarden/clients/bitwarden.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/vaultwarden/clients/bitwarden.py b/src/vaultwarden/clients/bitwarden.py index d6b8c99..3650b11 100644 --- a/src/vaultwarden/clients/bitwarden.py +++ b/src/vaultwarden/clients/bitwarden.py @@ -21,9 +21,7 @@ def __init__( timeout: int = 30, ): # if one of the parameters is None, raise an exception - if not all( - [url, email, password, client_id, client_secret, device_id] - ): + if not all([url, password, client_id, client_secret, device_id]): raise BitwardenError("All parameters are required") self.email = email self.password = password @@ -96,6 +94,18 @@ def _set_connect_token(self): "identity/connect/token", headers=headers, data=payload ) self._connect_token = ConnectToken.model_validate_json(resp.text) + + if self.email is None: + headers = { + "Authorization": f"Bearer {self._connect_token.access_token}", + "content-type": "application/json; charset=utf-8", + "Accept": "*/*", + } + resp = self._http_client.get( + "api/accounts/profile", headers=headers + ) + self.email = resp.json()["email"] + import vaultwarden.models.bitwarden self._connect_token.master_key = make_master_key( From 96fc7f29ff8da0071a8a123c1a2e8fd962e7a52a Mon Sep 17 00:00:00 2001 From: Nemirtingas Date: Tue, 2 Jun 2026 10:28:23 +0200 Subject: [PATCH 2/2] Try to add test without mail --- tests/e2e/test_bitwarden.py | 39 +++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/tests/e2e/test_bitwarden.py b/tests/e2e/test_bitwarden.py index ff59ad5..2a566a0 100644 --- a/tests/e2e/test_bitwarden.py +++ b/tests/e2e/test_bitwarden.py @@ -11,17 +11,32 @@ client_id = os.environ.get("BITWARDEN_CLIENT_ID", None) client_secret = os.environ.get("BITWARDEN_CLIENT_SECRET", None) device_id = os.environ.get("BITWARDEN_DEVICE_ID", None) -bitwarden = BitwardenAPIClient( - url, email, password, client_id, client_secret, device_id -) # Get test organization id from environment variables test_organization = os.environ.get("BITWARDEN_TEST_ORGANIZATION", None) +client_with_mail = BitwardenAPIClient( + url, + email, + password, + client_id, + client_secret, + device_id, +) + +client_without_mail = BitwardenAPIClient( + url, + None, + password, + client_id, + client_secret, + device_id, +) + -class BitwardenBasic(unittest.TestCase): - def setUp(self) -> None: - self.organization = get_organization(bitwarden, test_organization) +class BitwardenBaseTests: + def setup_base(self): + self.organization = get_organization(self.bitwarden, test_organization) self.test_colls_names = self.organization.collections(as_dict=True) self.test_colls_ids = self.organization.collections() self.test_users = self.organization.users() @@ -128,5 +143,17 @@ def test_deduplicate(self): return +class BitwardenWithEmailTests(unittest.TestCase, BitwardenBaseTests): + def setUp(self): + self.bitwarden = client_with_mail + self.setup_base() + + +class BitwardenWithoutEmailTests(unittest.TestCase, BitwardenBaseTests): + def setUp(self): + self.bitwarden = client_without_mail + self.setup_base() + + if __name__ == "__main__": unittest.main()