diff --git a/crates/bitwarden-json/src/client.rs b/crates/bitwarden-json/src/client.rs index bd40f50ec0..6db9f37fc2 100644 --- a/crates/bitwarden-json/src/client.rs +++ b/crates/bitwarden-json/src/client.rs @@ -1,4 +1,4 @@ -use bitwarden::ClientSettings; +use bitwarden::{ClientSettings, OrganizationId}; #[cfg(feature = "secrets")] use bitwarden::{ generators::GeneratorClientsExt, @@ -20,6 +20,11 @@ impl Client { Self(bitwarden::Client::new(settings)) } + pub fn get_access_token_organization(&self) -> Option { + let client = &self.0; + client.internal.get_access_token_organization() + } + pub async fn run_command(&self, input_str: &str) -> String { const SUBCOMMANDS_TO_CLEAN: &[&str] = &["Secrets"]; let mut cmd_value: serde_json::Value = match serde_json::from_str(input_str) { diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index a82cc9e00a..6bed138956 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -15,6 +15,7 @@ name = "bitwarden_py" crate-type = ["cdylib"] [dependencies] +bitwarden = { workspace = true } bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } pyo3 = { version = "0.27.0", features = ["extension-module", "abi3"] } pyo3-log = "0.13.2" diff --git a/crates/bitwarden-py/src/client.rs b/crates/bitwarden-py/src/client.rs index 9c12a624d9..9d794697c5 100644 --- a/crates/bitwarden-py/src/client.rs +++ b/crates/bitwarden-py/src/client.rs @@ -25,4 +25,13 @@ impl BitwardenClient { fn run_command(&self, command_input: String) -> String { self.0.block_on(self.1.run_command(&command_input)) } + + #[pyo3(text_signature = "($self")] + fn get_access_token_organization(&self) -> String { + if let Some(organization_id) = self.1.get_access_token_organization() { + organization_id.to_string() + } else { + "".to_string() + } + } } diff --git a/languages/python/bitwarden_sdk/bitwarden_client.py b/languages/python/bitwarden_sdk/bitwarden_client.py index 4ba5fc2400..098458f20c 100644 --- a/languages/python/bitwarden_sdk/bitwarden_client.py +++ b/languages/python/bitwarden_sdk/bitwarden_client.py @@ -100,12 +100,15 @@ def get_by_ids(self, ids: List[UUID]) -> ResponseForSecretsResponse: def create( self, - organization_id: UUID, + organization_id: Optional[UUID], key: str, value: str, note: Optional[str], project_ids: Optional[List[UUID]] = None, ) -> ResponseForSecretResponse: + if organization_id is None: + organization_id = self.client.inner.get_access_token_organization() + if note is None: # secrets api does not accept empty notes note = "" @@ -120,7 +123,12 @@ def create( ) return ResponseForSecretResponse.from_dict(result) - def list(self, organization_id: str) -> ResponseForSecretIdentifiersResponse: + def list( + self, organization_id: Optional[UUID] + ) -> ResponseForSecretIdentifiersResponse: + if organization_id is None: + organization_id = self.client.inner.get_access_token_organization() + result = self.client._run_command( Command( secrets=SecretsCommand(list=SecretIdentifiersRequest(organization_id)) @@ -130,13 +138,16 @@ def list(self, organization_id: str) -> ResponseForSecretIdentifiersResponse: def update( self, - organization_id: str, + organization_id: Optional[UUID], id: str, key: str, value: str, note: Optional[str], project_ids: Optional[List[UUID]] = None, ) -> ResponseForSecretResponse: + if organization_id is None: + organization_id = self.client.inner.get_access_token_organization() + if note is None: # secrets api does not accept empty notes note = "" @@ -158,8 +169,11 @@ def delete(self, ids: List[str]) -> ResponseForSecretsDeleteResponse: return ResponseForSecretsDeleteResponse.from_dict(result) def sync( - self, organization_id: str, last_synced_date: Optional[str] + self, organization_id: Optional[UUID], last_synced_date: Optional[str] ) -> ResponseForSecretsSyncResponse: + if organization_id is None: + organization_id = self.client.inner.get_access_token_organization() + result = self.client._run_command( Command( secrets=SecretsCommand( @@ -182,9 +196,12 @@ def get(self, id: str) -> ResponseForProjectResponse: def create( self, - organization_id: str, + organization_id: Optional[UUID], name: str, ) -> ResponseForProjectResponse: + if organization_id is None: + organization_id = self.client.inner.get_access_token_organization() + result = self.client._run_command( Command( projects=ProjectsCommand( @@ -194,7 +211,10 @@ def create( ) return ResponseForProjectResponse.from_dict(result) - def list(self, organization_id: str) -> ResponseForProjectsResponse: + def list(self, organization_id: Optional[UUID]) -> ResponseForProjectsResponse: + if organization_id is None: + organization_id = self.client.inner.get_access_token_organization() + result = self.client._run_command( Command(projects=ProjectsCommand(list=ProjectsListRequest(organization_id))) ) @@ -202,10 +222,13 @@ def list(self, organization_id: str) -> ResponseForProjectsResponse: def update( self, - organization_id: str, + organization_id: Optional[UUID], id: str, name: str, ) -> ResponseForProjectResponse: + if organization_id is None: + organization_id = self.client.inner.get_access_token_organization() + result = self.client._run_command( Command( projects=ProjectsCommand( diff --git a/languages/python/example.py b/languages/python/example.py index 2ff9af1265..3010ef0fb7 100755 --- a/languages/python/example.py +++ b/languages/python/example.py @@ -19,7 +19,6 @@ # Add some logging & set the org id logging.basicConfig(level=logging.DEBUG) -organization_id = os.getenv("ORGANIZATION_ID") # -- Example Generator Commands -- # Note: using the generator does not require authentication with a server @@ -49,44 +48,44 @@ # -- Example Project Commands -- -project = client.projects().create(organization_id, "ProjectName") -project2 = client.projects().create(organization_id, "AnotherProject") +project = client.projects().create(None, "ProjectName") +project2 = client.projects().create(None, "AnotherProject") updated_project = client.projects().update( - organization_id, project.data.id, "Cool New Project Name" + None, project.data.id, "Cool New Project Name" ) get_that_project = client.projects().get(project.data.id) input("Press Enter to delete the project...") client.projects().delete([project.data.id]) -print(client.projects().list(organization_id)) +print(client.projects().list(None)) # -- Example Secret Commands -- -if client.secrets().sync(organization_id, None).data.has_changes is True: +if client.secrets().sync(None, None).data.has_changes is True: print("There are changes to sync") else: print("No changes to sync") last_synced_date = datetime.now(tz=timezone.utc) -print(client.secrets().sync(organization_id, last_synced_date)) +print(client.secrets().sync(None, last_synced_date)) secret = client.secrets().create( - organization_id, + None, "TEST_SECRET", "This is a test secret", "Secret1234!", [project2.data.id], ) secret2 = client.secrets().create( - organization_id, + None, "ANOTHER_SECRET", "Secret1234!", None, [project2.data.id], ) secret_updated = client.secrets().update( - organization_id, + None, secret.data.id, "TEST_SECRET_UPDATED", "This as an updated test secret",