From 97e80e30ab12992109beea571c0d587ca9d2a526 Mon Sep 17 00:00:00 2001 From: Peter Jiang <2892084432j@gmail.com> Date: Fri, 8 Nov 2024 15:32:11 -0500 Subject: [PATCH 1/3] Add tests with env vars --- tests/README.md | 6 +++ tests/test.py | 137 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 tests/README.md create mode 100644 tests/test.py diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..3dcb67dc --- /dev/null +++ b/tests/README.md @@ -0,0 +1,6 @@ +To test, make sure the following env vars are defined: + +```sh +export CORE_SDK_TEST_SECRET_REF='op://vault/item/field' +export CORE_SDK_TEST_VAULT_ID='' +``` diff --git a/tests/test.py b/tests/test.py new file mode 100644 index 00000000..e234c01e --- /dev/null +++ b/tests/test.py @@ -0,0 +1,137 @@ +import asyncio +import os + +# [developer-docs.sdk.python.sdk-import]-start +from onepassword import * +# [developer-docs.sdk.python.sdk-import]-end + + +async def main(): + # [developer-docs.sdk.python.client-initialization]-start + # Gets your service account token from the OP_SERVICE_ACCOUNT_TOKEN environment variable. + token = os.getenv("OP_SERVICE_ACCOUNT_TOKEN") + test_vault_id = os.getenv("CORE_SDK_TEST_VAULT_ID") + test_secret_ref = os.getenv("CORE_SDK_TEST_SECRET_REF") + + if not token or not test_vault_id or not test_secret_ref: + raise ValueError("OP_SERVICE_ACCOUNT_TOKEN, CORE_SDK_TEST_VAULT_ID, and CORE_SDK_TEST_SECRET_REF must be set.") + + # Connects to 1Password. + client = await Client.authenticate( + auth=token, + # Set the following to your own integration name and version. + integration_name="My 1Password Integration", + integration_version="v1.0.0", + ) + # [developer-docs.sdk.python.client-initialization]-end + + # [developer-docs.sdk.python.list-vaults]-start + vaults = await client.vaults.list_all() + async for vault in vaults: + print(vault.title) + # [developer-docs.sdk.python.list-vaults]-end + + # [developer-docs.sdk.python.list-items]-start + items = await client.items.list_all(vault.id) + async for item in items: + print(item.title) + # [developer-docs.sdk.python.list-items]-end + + # [developer-docs.sdk.python.resolve-secret]-start + # Retrieves a secret from 1Password. Takes a secret reference as input and returns the secret to which it points. + value = await client.secrets.resolve(test_secret_ref) + print(value) + # [developer-docs.sdk.python.resolve-secret]-end + + # [developer-docs.sdk.python.create-item]-start + # Create an Item and add it to your vault. + to_create = ItemCreateParams( + title="MyName", + category="Login", + vaultId = test_vault_id, + fields=[ + ItemField( + id="username", + title="username", + field_type="Text", + value="mynameisjeff", + ), + ItemField( + id="password", + title="password", + field_type="Concealed", + value="jeff", + ), + ItemField( + id="onetimepassword", + title="one-time-password", + field_type="Totp", + section_id="totpsection", + value="otpauth://totp/my-example-otp?secret=jncrjgbdjnrncbjsr&issuer=1Password", + ), + ], + sections=[ + ItemSection(id="", title=""), + ItemSection(id="totpsection", title=""), + ], + tags=["test tag 1", "test tag 2"], + websites=[ + Website( + label="my custom website", + url="https://example.com", + autofill_behavior="AnywhereOnWebsite", + ) + ], + ) + created_item = await client.items.create(to_create) + # [developer-docs.sdk.python.create-item]-end + + print(dict(created_item)) + + # [developer-docs.sdk.python.resolve-totp-code]-start + # Retrieves a secret from 1Password. Takes a secret reference as input and returns the secret to which it points. + code = await client.secrets.resolve( + f"op://{created_item.vault_id}/{created_item.id}/TOTP_onetimepassword?attribute=totp" + ) + print(code) + # [developer-docs.sdk.python.resolve-totp-code]-end + + # [developer-docs.sdk.python.get-totp-item-crud]-start + # Fetch a totp code from the item + for f in created_item.fields: + if f.field_type == "Totp": + if f.details.content.error_message is not None: + print(f.details.content.error_message) + else: + print(f.details.content.code) + # [developer-docs.sdk.python.get-totp-item-crud]-end + + # [developer-docs.sdk.python.get-item]-start + # Retrieve an item from your vault. + item = await client.items.get(created_item.vault_id, created_item.id) + # [developer-docs.sdk.python.get-item]-end + + print(dict(item)) + + # [developer-docs.sdk.python.update-item]-start + # Update a field in your item + item.fields[0].value = "new_value" + item.websites.append( + Website( + label="my custom website 2", + url="https://example2.com", + autofill_behavior="Never", + ), + ) + updated_item = await client.items.put(item) + # [developer-docs.sdk.python.update-item]-end + + print(dict(updated_item)) + # [developer-docs.sdk.python.delete-item]-start + # Delete a item from your vault. + await client.items.delete(created_item.vault_id, updated_item.id) + # [developer-docs.sdk.python.delete-item]-end + + +if __name__ == "__main__": + asyncio.run(main()) From 9ac0e61589919aa2c8ca1ff9eefea40806b0acbb Mon Sep 17 00:00:00 2001 From: Peter Jiang <2892084432j@gmail.com> Date: Mon, 11 Nov 2024 11:26:23 -0500 Subject: [PATCH 2/3] add comment --- tests/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/README.md b/tests/README.md index 3dcb67dc..68cef0bc 100644 --- a/tests/README.md +++ b/tests/README.md @@ -2,5 +2,5 @@ To test, make sure the following env vars are defined: ```sh export CORE_SDK_TEST_SECRET_REF='op://vault/item/field' -export CORE_SDK_TEST_VAULT_ID='' +export CORE_SDK_TEST_VAULT_ID='' # can get from `op list vaults` ``` From 4a0159faaf111228c02a4b0a35a693e0f5e22b16 Mon Sep 17 00:00:00 2001 From: Peter Jiang <2892084432j@gmail.com> Date: Thu, 28 Nov 2024 23:39:58 -0500 Subject: [PATCH 3/3] split examples and tests into smaller units --- .../test.py => example/item_crud_operation.py | 62 ++++++------------- example/list_items_in_vaults.py | 24 +++++++ example/list_vaults.py | 22 +++++++ example/resolve_secret_reference.py | 15 +++++ example/validate_secret_reference.py | 13 ++++ tests/run_all_tests.sh | 9 +++ tests/test_list_items_in_vaults.py | 26 ++++++++ tests/test_list_vaults.py | 24 +++++++ tests/test_resolve_secret_reference.py | 13 ++++ tests/test_validate_secret_reference.py | 10 +++ 10 files changed, 174 insertions(+), 44 deletions(-) rename tests/test.py => example/item_crud_operation.py (63%) create mode 100644 example/list_items_in_vaults.py create mode 100644 example/list_vaults.py create mode 100644 example/resolve_secret_reference.py create mode 100644 example/validate_secret_reference.py create mode 100755 tests/run_all_tests.sh create mode 100644 tests/test_list_items_in_vaults.py create mode 100644 tests/test_list_vaults.py create mode 100644 tests/test_resolve_secret_reference.py create mode 100644 tests/test_validate_secret_reference.py diff --git a/tests/test.py b/example/item_crud_operation.py similarity index 63% rename from tests/test.py rename to example/item_crud_operation.py index e234c01e..521007cf 100644 --- a/tests/test.py +++ b/example/item_crud_operation.py @@ -1,71 +1,45 @@ import asyncio import os -# [developer-docs.sdk.python.sdk-import]-start -from onepassword import * -# [developer-docs.sdk.python.sdk-import]-end +from onepassword.client import Client +from onepassword.types import AutofillBehavior, ItemCategory, ItemCreateParams, ItemField, ItemFieldType, ItemSection, Website - -async def main(): - # [developer-docs.sdk.python.client-initialization]-start - # Gets your service account token from the OP_SERVICE_ACCOUNT_TOKEN environment variable. +# Perform CRUD operations on an item +async def item_crud_operation(): token = os.getenv("OP_SERVICE_ACCOUNT_TOKEN") - test_vault_id = os.getenv("CORE_SDK_TEST_VAULT_ID") - test_secret_ref = os.getenv("CORE_SDK_TEST_SECRET_REF") - - if not token or not test_vault_id or not test_secret_ref: - raise ValueError("OP_SERVICE_ACCOUNT_TOKEN, CORE_SDK_TEST_VAULT_ID, and CORE_SDK_TEST_SECRET_REF must be set.") - - # Connects to 1Password. + if not token: + raise ValueError("OP_SERVICE_ACCOUNT_TOKEN must be set.") client = await Client.authenticate( auth=token, # Set the following to your own integration name and version. integration_name="My 1Password Integration", integration_version="v1.0.0", ) - # [developer-docs.sdk.python.client-initialization]-end - - # [developer-docs.sdk.python.list-vaults]-start - vaults = await client.vaults.list_all() - async for vault in vaults: - print(vault.title) - # [developer-docs.sdk.python.list-vaults]-end - - # [developer-docs.sdk.python.list-items]-start - items = await client.items.list_all(vault.id) - async for item in items: - print(item.title) - # [developer-docs.sdk.python.list-items]-end - - # [developer-docs.sdk.python.resolve-secret]-start - # Retrieves a secret from 1Password. Takes a secret reference as input and returns the secret to which it points. - value = await client.secrets.resolve(test_secret_ref) - print(value) - # [developer-docs.sdk.python.resolve-secret]-end - - # [developer-docs.sdk.python.create-item]-start - # Create an Item and add it to your vault. + # Fill in a real vault ID below + # You can find this by using the list_vaults.py example + # Or using `op vault list` + vault_id = "xxxxxxxxxxxxxxxxxxxxxxxxxx" to_create = ItemCreateParams( title="MyName", - category="Login", - vaultId = test_vault_id, + category=ItemCategory.LOGIN, + vault_id=vault_id, fields=[ ItemField( id="username", title="username", - field_type="Text", + field_type=ItemFieldType.TEXT, value="mynameisjeff", ), ItemField( id="password", title="password", - field_type="Concealed", + field_type=ItemFieldType.CONCEALED, value="jeff", ), ItemField( id="onetimepassword", title="one-time-password", - field_type="Totp", + field_type=ItemFieldType.TOTP, section_id="totpsection", value="otpauth://totp/my-example-otp?secret=jncrjgbdjnrncbjsr&issuer=1Password", ), @@ -79,7 +53,7 @@ async def main(): Website( label="my custom website", url="https://example.com", - autofill_behavior="AnywhereOnWebsite", + autofill_behavior=AutofillBehavior.NEVER, ) ], ) @@ -120,7 +94,7 @@ async def main(): Website( label="my custom website 2", url="https://example2.com", - autofill_behavior="Never", + autofill_behavior=AutofillBehavior.NEVER, ), ) updated_item = await client.items.put(item) @@ -134,4 +108,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + asyncio.run(item_crud_operation()) \ No newline at end of file diff --git a/example/list_items_in_vaults.py b/example/list_items_in_vaults.py new file mode 100644 index 00000000..a965c375 --- /dev/null +++ b/example/list_items_in_vaults.py @@ -0,0 +1,24 @@ +import asyncio +import os + +from onepassword.client import Client + +# list all items in all vaults +async def list_items_in_vaults(): + token = os.getenv("OP_SERVICE_ACCOUNT_TOKEN") + if not token: + raise ValueError("OP_SERVICE_ACCOUNT_TOKEN must be set.") + client = await Client.authenticate( + auth=token, + # Set the following to your own integration name and version. + integration_name="My 1Password Integration", + integration_version="v1.0.0", + ) + vaults = await client.vaults.list_all() + async for vault in vaults: + items = await client.items.list_all(vault.id) + async for item in items: + print(item.title) + +if __name__ == "__main__": + asyncio.run(list_items_in_vaults()) \ No newline at end of file diff --git a/example/list_vaults.py b/example/list_vaults.py new file mode 100644 index 00000000..782cb75e --- /dev/null +++ b/example/list_vaults.py @@ -0,0 +1,22 @@ +import asyncio +import os + +from onepassword.client import Client + +# list all vaults +async def list_vaults(): + token = os.getenv("OP_SERVICE_ACCOUNT_TOKEN") + if not token: + raise ValueError("OP_SERVICE_ACCOUNT_TOKEN must be set.") + client = await Client.authenticate( + auth=token, + # Set the following to your own integration name and version. + integration_name="My 1Password Integration", + integration_version="v1.0.0", + ) + vaults = await client.vaults.list_all() + async for vault in vaults: + print(vault.title) + +if __name__ == "__main__": + asyncio.run(list_vaults()) \ No newline at end of file diff --git a/example/resolve_secret_reference.py b/example/resolve_secret_reference.py new file mode 100644 index 00000000..58b4443e --- /dev/null +++ b/example/resolve_secret_reference.py @@ -0,0 +1,15 @@ + +from onepassword.secrets import Secrets + +# Retrieves a secret from 1Password. Takes a secret reference as input and returns the secret to which it points. +def resolve_secret_reference(): + # Replace this with a real secret reference + secret_reference = "op://vault/item/field" + try: + Secrets.validate_secret_reference(secret_reference) + print("Secret reference resolved successfully") + except Exception as error: + print(error) + +if __name__ == "__main__": + resolve_secret_reference() \ No newline at end of file diff --git a/example/validate_secret_reference.py b/example/validate_secret_reference.py new file mode 100644 index 00000000..0a3ee1d0 --- /dev/null +++ b/example/validate_secret_reference.py @@ -0,0 +1,13 @@ + +from onepassword.secrets import Secrets + +# Validate secret reference to ensure no syntax errors +def validate_secret_reference(): + try: + Secrets.validate_secret_reference("op://vault/item/field") + print("Secret reference is of valid syntax") + except Exception as error: + print(error) + +if __name__ == "__main__": + validate_secret_reference() \ No newline at end of file diff --git a/tests/run_all_tests.sh b/tests/run_all_tests.sh new file mode 100755 index 00000000..bc247dee --- /dev/null +++ b/tests/run_all_tests.sh @@ -0,0 +1,9 @@ +# change working directory to the directory of the script + +cd "$(dirname "$0")" + +# Run all python files in the tests directory +for file in *.py +do + python3 $file +done \ No newline at end of file diff --git a/tests/test_list_items_in_vaults.py b/tests/test_list_items_in_vaults.py new file mode 100644 index 00000000..2b4cf9e5 --- /dev/null +++ b/tests/test_list_items_in_vaults.py @@ -0,0 +1,26 @@ +import asyncio +import os + +from onepassword.client import Client + +async def test_list_items_in_vaults(): + print("Starting list_items_in_vaults test") + token = os.getenv("OP_SERVICE_ACCOUNT_TOKEN") + if not token: + raise ValueError("OP_SERVICE_ACCOUNT_TOKEN must be set.") + client = await Client.authenticate( + auth=token, + # Set the following to your own integration name and version. + integration_name="My 1Password Integration", + integration_version="v1.0.0", + ) + vaults = await client.vaults.list_all() + async for vault in vaults: + items = await client.items.list_all(vault.id) + async for item in items: + print(item.title) + + print("list_items_in_vaults test completed successfully") + +if __name__ == "__main__": + asyncio.run(test_list_items_in_vaults()) \ No newline at end of file diff --git a/tests/test_list_vaults.py b/tests/test_list_vaults.py new file mode 100644 index 00000000..776c94d6 --- /dev/null +++ b/tests/test_list_vaults.py @@ -0,0 +1,24 @@ +import asyncio +import os + +from onepassword.client import Client + +async def test_list_vaults(): + print("Starting list_vaults test") + token = os.getenv("OP_SERVICE_ACCOUNT_TOKEN") + if not token: + raise ValueError("OP_SERVICE_ACCOUNT_TOKEN must be set.") + client = await Client.authenticate( + auth=token, + # Set the following to your own integration name and version. + integration_name="My 1Password Integration", + integration_version="v1.0.0", + ) + vaults = await client.vaults.list_all() + async for vault in vaults: + print(vault.title) + + print("Finished list_vaults test successfully") + +if __name__ == "__main__": + asyncio.run(test_list_vaults()) \ No newline at end of file diff --git a/tests/test_resolve_secret_reference.py b/tests/test_resolve_secret_reference.py new file mode 100644 index 00000000..79503706 --- /dev/null +++ b/tests/test_resolve_secret_reference.py @@ -0,0 +1,13 @@ +from onepassword.secrets import Secrets +import os + +def test_resolve_secret_reference(): + print("Starting resolve_secret_reference test") + test_secret_ref = os.getenv("CORE_SDK_TEST_SECRET_REF") + if not test_secret_ref: + raise ValueError("CORE_SDK_TEST_SECRET_REF must be set.") + Secrets.validate_secret_reference(test_secret_ref) + print("Finished resolve_secret_reference test successfully") + +if __name__ == "__main__": + test_resolve_secret_reference() diff --git a/tests/test_validate_secret_reference.py b/tests/test_validate_secret_reference.py new file mode 100644 index 00000000..4756919b --- /dev/null +++ b/tests/test_validate_secret_reference.py @@ -0,0 +1,10 @@ +from onepassword.secrets import Secrets + +# Validate secret reference to ensure no syntax errors +def test_validate_secret_reference(): + print("Starting validate_secret_reference test") + Secrets.validate_secret_reference("op://vault/item/field") + print("Finished validate_secret_reference test successfully") + +if __name__ == "__main__": + test_validate_secret_reference()