From 67cd747ae4ea466bef70a3c9d92d1f433628a351 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Fri, 5 Jul 2024 15:54:03 +0200 Subject: [PATCH 01/36] SM-1266: Compose case sensitive imports --- languages/php/src/BitwardenClient.php | 2 +- .../php/src/{schemas => Schemas}/AccessTokenLoginRequest.php | 0 .../php/src/{schemas => Schemas}/BitwardenClassStructure.php | 0 .../src/{schemas => Schemas}/BitwardenClassStructureTrait.php | 0 languages/php/src/{schemas => Schemas}/ClientSettings.php | 0 languages/php/src/{schemas => Schemas}/Command.php | 0 languages/php/src/{schemas => Schemas}/ProjectCreateRequest.php | 0 languages/php/src/{schemas => Schemas}/ProjectGetRequest.php | 0 languages/php/src/{schemas => Schemas}/ProjectPutRequest.php | 0 languages/php/src/{schemas => Schemas}/ProjectsCommand.php | 0 .../php/src/{schemas => Schemas}/ProjectsDeleteRequest.php | 0 languages/php/src/{schemas => Schemas}/ProjectsListRequest.php | 0 languages/php/src/{schemas => Schemas}/SecretCreateRequest.php | 0 languages/php/src/{schemas => Schemas}/SecretGetRequest.php | 0 .../php/src/{schemas => Schemas}/SecretIdentifiersRequest.php | 0 languages/php/src/{schemas => Schemas}/SecretPutRequest.php | 0 .../php/src/{schemas => Schemas}/SecretVerificationRequest.php | 0 languages/php/src/{schemas => Schemas}/SecretsCommand.php | 0 languages/php/src/{schemas => Schemas}/SecretsDeleteRequest.php | 0 languages/php/src/{schemas => Schemas}/SecretsGetRequest.php | 0 20 files changed, 1 insertion(+), 1 deletion(-) rename languages/php/src/{schemas => Schemas}/AccessTokenLoginRequest.php (100%) rename languages/php/src/{schemas => Schemas}/BitwardenClassStructure.php (100%) rename languages/php/src/{schemas => Schemas}/BitwardenClassStructureTrait.php (100%) rename languages/php/src/{schemas => Schemas}/ClientSettings.php (100%) rename languages/php/src/{schemas => Schemas}/Command.php (100%) rename languages/php/src/{schemas => Schemas}/ProjectCreateRequest.php (100%) rename languages/php/src/{schemas => Schemas}/ProjectGetRequest.php (100%) rename languages/php/src/{schemas => Schemas}/ProjectPutRequest.php (100%) rename languages/php/src/{schemas => Schemas}/ProjectsCommand.php (100%) rename languages/php/src/{schemas => Schemas}/ProjectsDeleteRequest.php (100%) rename languages/php/src/{schemas => Schemas}/ProjectsListRequest.php (100%) rename languages/php/src/{schemas => Schemas}/SecretCreateRequest.php (100%) rename languages/php/src/{schemas => Schemas}/SecretGetRequest.php (100%) rename languages/php/src/{schemas => Schemas}/SecretIdentifiersRequest.php (100%) rename languages/php/src/{schemas => Schemas}/SecretPutRequest.php (100%) rename languages/php/src/{schemas => Schemas}/SecretVerificationRequest.php (100%) rename languages/php/src/{schemas => Schemas}/SecretsCommand.php (100%) rename languages/php/src/{schemas => Schemas}/SecretsDeleteRequest.php (100%) rename languages/php/src/{schemas => Schemas}/SecretsGetRequest.php (100%) diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index 79fccdf9c..f1059c766 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -3,7 +3,7 @@ namespace Bitwarden\Sdk; use Bitwarden\Sdk\Schemas\AccessTokenLoginRequest; -use Bitwarden\Sdk\schemas\ClientSettings; +use Bitwarden\Sdk\Schemas\ClientSettings; use Bitwarden\Sdk\Schemas\Command; use FFI; use Swaggest\JsonDiff\Exception; diff --git a/languages/php/src/schemas/AccessTokenLoginRequest.php b/languages/php/src/Schemas/AccessTokenLoginRequest.php similarity index 100% rename from languages/php/src/schemas/AccessTokenLoginRequest.php rename to languages/php/src/Schemas/AccessTokenLoginRequest.php diff --git a/languages/php/src/schemas/BitwardenClassStructure.php b/languages/php/src/Schemas/BitwardenClassStructure.php similarity index 100% rename from languages/php/src/schemas/BitwardenClassStructure.php rename to languages/php/src/Schemas/BitwardenClassStructure.php diff --git a/languages/php/src/schemas/BitwardenClassStructureTrait.php b/languages/php/src/Schemas/BitwardenClassStructureTrait.php similarity index 100% rename from languages/php/src/schemas/BitwardenClassStructureTrait.php rename to languages/php/src/Schemas/BitwardenClassStructureTrait.php diff --git a/languages/php/src/schemas/ClientSettings.php b/languages/php/src/Schemas/ClientSettings.php similarity index 100% rename from languages/php/src/schemas/ClientSettings.php rename to languages/php/src/Schemas/ClientSettings.php diff --git a/languages/php/src/schemas/Command.php b/languages/php/src/Schemas/Command.php similarity index 100% rename from languages/php/src/schemas/Command.php rename to languages/php/src/Schemas/Command.php diff --git a/languages/php/src/schemas/ProjectCreateRequest.php b/languages/php/src/Schemas/ProjectCreateRequest.php similarity index 100% rename from languages/php/src/schemas/ProjectCreateRequest.php rename to languages/php/src/Schemas/ProjectCreateRequest.php diff --git a/languages/php/src/schemas/ProjectGetRequest.php b/languages/php/src/Schemas/ProjectGetRequest.php similarity index 100% rename from languages/php/src/schemas/ProjectGetRequest.php rename to languages/php/src/Schemas/ProjectGetRequest.php diff --git a/languages/php/src/schemas/ProjectPutRequest.php b/languages/php/src/Schemas/ProjectPutRequest.php similarity index 100% rename from languages/php/src/schemas/ProjectPutRequest.php rename to languages/php/src/Schemas/ProjectPutRequest.php diff --git a/languages/php/src/schemas/ProjectsCommand.php b/languages/php/src/Schemas/ProjectsCommand.php similarity index 100% rename from languages/php/src/schemas/ProjectsCommand.php rename to languages/php/src/Schemas/ProjectsCommand.php diff --git a/languages/php/src/schemas/ProjectsDeleteRequest.php b/languages/php/src/Schemas/ProjectsDeleteRequest.php similarity index 100% rename from languages/php/src/schemas/ProjectsDeleteRequest.php rename to languages/php/src/Schemas/ProjectsDeleteRequest.php diff --git a/languages/php/src/schemas/ProjectsListRequest.php b/languages/php/src/Schemas/ProjectsListRequest.php similarity index 100% rename from languages/php/src/schemas/ProjectsListRequest.php rename to languages/php/src/Schemas/ProjectsListRequest.php diff --git a/languages/php/src/schemas/SecretCreateRequest.php b/languages/php/src/Schemas/SecretCreateRequest.php similarity index 100% rename from languages/php/src/schemas/SecretCreateRequest.php rename to languages/php/src/Schemas/SecretCreateRequest.php diff --git a/languages/php/src/schemas/SecretGetRequest.php b/languages/php/src/Schemas/SecretGetRequest.php similarity index 100% rename from languages/php/src/schemas/SecretGetRequest.php rename to languages/php/src/Schemas/SecretGetRequest.php diff --git a/languages/php/src/schemas/SecretIdentifiersRequest.php b/languages/php/src/Schemas/SecretIdentifiersRequest.php similarity index 100% rename from languages/php/src/schemas/SecretIdentifiersRequest.php rename to languages/php/src/Schemas/SecretIdentifiersRequest.php diff --git a/languages/php/src/schemas/SecretPutRequest.php b/languages/php/src/Schemas/SecretPutRequest.php similarity index 100% rename from languages/php/src/schemas/SecretPutRequest.php rename to languages/php/src/Schemas/SecretPutRequest.php diff --git a/languages/php/src/schemas/SecretVerificationRequest.php b/languages/php/src/Schemas/SecretVerificationRequest.php similarity index 100% rename from languages/php/src/schemas/SecretVerificationRequest.php rename to languages/php/src/Schemas/SecretVerificationRequest.php diff --git a/languages/php/src/schemas/SecretsCommand.php b/languages/php/src/Schemas/SecretsCommand.php similarity index 100% rename from languages/php/src/schemas/SecretsCommand.php rename to languages/php/src/Schemas/SecretsCommand.php diff --git a/languages/php/src/schemas/SecretsDeleteRequest.php b/languages/php/src/Schemas/SecretsDeleteRequest.php similarity index 100% rename from languages/php/src/schemas/SecretsDeleteRequest.php rename to languages/php/src/Schemas/SecretsDeleteRequest.php diff --git a/languages/php/src/schemas/SecretsGetRequest.php b/languages/php/src/Schemas/SecretsGetRequest.php similarity index 100% rename from languages/php/src/schemas/SecretsGetRequest.php rename to languages/php/src/Schemas/SecretsGetRequest.php From d124c3716d439a4720ac486f06270392c865d246 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Fri, 5 Jul 2024 15:56:20 +0200 Subject: [PATCH 02/36] SM-1266: Consistent FFI library directories --- languages/php/src/BitwardenLib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/php/src/BitwardenLib.php b/languages/php/src/BitwardenLib.php index 351728986..46d19c798 100644 --- a/languages/php/src/BitwardenLib.php +++ b/languages/php/src/BitwardenLib.php @@ -34,9 +34,9 @@ public function __construct() } elseif (PHP_OS === 'Darwin') { $architecture = trim(exec('uname -m')); if ($architecture === 'x86_64' || $architecture === 'amd64') { - $lib_file = __DIR__.'/lib/macos-x64/libbitwarden_c.dylib'; + $lib_file = '/lib/macos-x64/libbitwarden_c.dylib'; } elseif ($architecture === 'arm64') { - $lib_file = __DIR__.'/lib/macos-arm64/libbitwarden_c.dylib'; + $lib_file = '/lib/macos-arm64/libbitwarden_c.dylib'; } if (file_exists($lib_file) == false) { $lib_file = __DIR__.'/../../../target/debug/libbitwarden_c.dylib'; From 1c4839adde64313088b966c84563afcde2a5fbb3 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Fri, 5 Jul 2024 15:59:27 +0200 Subject: [PATCH 03/36] SM-1266: Fix outdated secret get by ids command --- languages/php/src/SecretsClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/src/SecretsClient.php b/languages/php/src/SecretsClient.php index d5c0b0cef..89e8e980f 100644 --- a/languages/php/src/SecretsClient.php +++ b/languages/php/src/SecretsClient.php @@ -36,7 +36,7 @@ public function get_by_ids(array $secret_ids): \stdClass $project_get_by_ids_request->ids = $secret_ids; $project_get_by_ids_request->validate(); $secrets_command = new SecretsCommand(); - $secrets_command->get_by_ids = $project_get_by_ids_request->jsonSerialize(); + $secrets_command->getByIds = $project_get_by_ids_request->jsonSerialize(); return $this->run_secret_command($secrets_command); } From 54f4bdf6ee689244514a121262bb3d4cfd4a3ddf Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Fri, 5 Jul 2024 15:59:55 +0200 Subject: [PATCH 04/36] SM-1266: More verbose example --- languages/php/example.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/languages/php/example.php b/languages/php/example.php index 7eafcb96a..154133e44 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -17,12 +17,15 @@ // create project $res = $bitwarden_client->projects->create('php project', $organization_id); $project_id = $res->id; +echo "Project: $project_id\n"; // get project $res = $bitwarden_client->projects->get($project_id); // list projects $res = $bitwarden_client->projects->list($organization_id); +$project_count = count($res->data); +echo "Projects count: $project_count\n"; // update project $res = $bitwarden_client->projects->put($project_id, 'php test awesome', $organization_id); @@ -30,12 +33,18 @@ // create secret $res = $bitwarden_client->secrets->create("New Key", "hello world", $organization_id, [$project_id], "123"); $secret_id = $res->id; +echo "Secret: $secret_id\n"; // get secret $res = $bitwarden_client->secrets->get($secret_id); +// get secrets +$res = $bitwarden_client->secrets->get_by_ids([$secret_id]); + // list secrets $res = $bitwarden_client->secrets->list($organization_id); +$secret_count = count($res->data); +echo "Secrets count: $secret_count\n"; // update secret $res = $bitwarden_client->secrets->update($secret_id, "hello world 2", "hello", $organization_id, [$project_id], "123"); From 2beea1e40ebf1bc88dff3cd10c660e6ace334098 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Fri, 5 Jul 2024 16:00:19 +0200 Subject: [PATCH 05/36] SM-1266: Composer lock update (excluding dependencies) --- languages/php/composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/composer.lock b/languages/php/composer.lock index fc6b42c4f..8856663d8 100644 --- a/languages/php/composer.lock +++ b/languages/php/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7081b1bfe099982a63ad06d5ab9fa66d", + "content-hash": "c4bbd1e56c4c6ddbdb68e0015ccad231", "packages": [ { "name": "phplang/scope-exit", From d147f3baa9e92f28d27fc5cfd2731a65a23dfb8f Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Fri, 5 Jul 2024 16:30:59 +0200 Subject: [PATCH 06/36] SM-1266: PHP documentation update --- languages/php/INSTALL.md | 53 +++++++++++++++++ languages/php/README.md | 124 ++++++++++++++++++++++----------------- 2 files changed, 122 insertions(+), 55 deletions(-) create mode 100644 languages/php/INSTALL.md diff --git a/languages/php/INSTALL.md b/languages/php/INSTALL.md new file mode 100644 index 000000000..f9be34251 --- /dev/null +++ b/languages/php/INSTALL.md @@ -0,0 +1,53 @@ +# PHP Installation + +## Introduction + +Composer is used to build PHP Bitwarden client library. + +## Prerequisites + +- PHP >= 8.0 +- FFI extension enabled in PHP configuration +- Composer +- Bitwarden SDK native library, which is expected in one of below locations, depending on the OS and architecture. + If you prefer to build SDK yourself, see [SDK README.md](../../README.md) for instructions. + - Windows x86_64: `/lib/windows-x64/bitwarden_c.dll` + - Linux x86_64: `/lib/linux-x64/libbitwarden_c.so` + - macOS x86_64: `/lib/macos-x64/libbitwarden_c.dylib` + - macOS aarch64: `/lib/macos-arm64/libbitwarden_c.dylib` + +## Build Commands + +```shell +composer install +``` + +## Example + +### macOS + +#### Install Prerequisites + +Use brew Composer and PHP + +```shell +brew install php +brew install composer +``` + +#### Build Commands + +```shell +composer install +``` + +## Example SDK Usage Project + +```shell +export ACCESS_TOKEN="" +export ORGANIZATION_ID="" +export API_URL="https://api.bitwarden.com" +export IDENTITY_URL="https://identity.bitwarden.com" + +php example.php +``` diff --git a/languages/php/README.md b/languages/php/README.md index 9e4a9385d..ead059cbb 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -1,100 +1,114 @@ # Bitwarden Secrets Manager SDK wrapper for PHP -PHP bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some functionality. -Supported are CRUD operations on project and secret entities. +PHP bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some +functionality. ## Installation -Requirements: -- PHP >= 8.0 -- Composer -- Bitwarden C libraries which you can generate using BitwardenSDK and following instructions in its readme (requires Rust). https://github.com/bitwarden/sdk -If you are not using the standalone version of this library, file will be placed in `target/debug` folder if you are using from BitwardenSDK repository. -- Access token for the Bitwarden account - +See the [installation instructions](./INSTALL.md) ## Usage -To interact with the client first you need to obtain the access token from Bitwarden. -You can then initialize BitwardenSettings passing $api_url and $identity_url if needed. These parameteres are -optional and if they are not defined, BitwardenSettings instance will try to get these values from ENV, and -if they are not defined there as well, it will use defaults: `https://api.bitwarden.com` as api_url and -`https://identity.bitwarden.com` as identity_url. You can also pass device type as argument but that is entirely -optional. +### Create access token -Passing BitwardenSettings instance to BitwardenClient will initialize it. Before using the client you must -be authorized by calling the access_token_login method passing your Bitwarden access token to it. +To interact with the client first you need to obtain the access token from Bitwarden. +Review the help documentation on [Access Tokens]. +### Create new Bitwarden client ```php -$access_token = ''; -$api_url = ""; -$identity_url = ""; +require_once 'vendor/autoload.php'; + +$access_token = ''; +$organization_id = ""; +$api_url = "https://api.bitwarden.com"; +$identity_url = "https://identity.bitwarden.com"; + $bitwarden_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($bitwarden_settings); $bitwarden_client->access_token_login($access_token); ``` -After successful authorization you can interact with client to manage your projects and secrets. -```php -$organization_id = ""; +Initialize `BitwardenSettings` by passing `$api_url` and `$identity_url` or set to null to use the defaults. +The default for `api_url` is `https://api.bitwarden.com` and for `identity_url` is `https://identity.bitwarden.com`. -$bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($bitwarden_settings); -$res = $bitwarden_client->access_token_login($access_token); +### Create new project -// create project -$name = "PHP project" +```php +$name = "PHP project"; $res = $bitwarden_client->projects->create($name, $organization_id); $project_id = $res->id; +``` + +### Get project -// get project +```php $res = $bitwarden_client->projects->get($project_id); +``` + +### List all projects -// list projects +```php $res = $bitwarden_client->projects->list($organization_id); +``` -// update project -$name = "Updated PHP project" -$res = $bitwarden_client->projects->put($project_id, $name, $organization_id); +### Update project -// get secret -$res = $bitwarden_client->secrets->get($secret_id); +```php +$name = "Updated PHP project"; +$res = $bitwarden_client->projects->put($project_id, $name, $organization_id); +``` -// list secrets -$res = $bitwarden_client->secrets->list($organization_id); +### Delete project -// delete project +```php $res = $bitwarden_client->projects->delete([$project_id]); +``` +### Create new secret + +```php +$key = "Secret key"; +$note = "Secret note"; +$value = "Secret value"; +$res = $bitwarden_client->secrets->create($key, $note, $organization_id, [$project_id], $value); +$secret_id = $res->id; ``` -Similarly, you interact with secrets: +### Get secret + ```php -$organization_id = ""; +$res = $bitwarden_client->secrets->get($secret_id); +``` -// create secret -$key = "AWS secret key"; -$note = "Private account"; -$secret = "76asaj,Is_)" -$res = $bitwarden_client->secrets->create($key, $note, $organization_id, [$project_id], $secret); -$secret_id = $res->id; +### Get multiple secrets -// get secret -$res = $bitwarden_sdk->secrets->get($secret_id); +```php +$res = $bitwarden_client->secrets->get_by_ids([$secret_id]); +``` + +### List all secrets -// list secrets +```php $res = $bitwarden_client->secrets->list($organization_id); +``` -// update secret -$note = "Updated account"; -$key = "AWS private updated" -$secret = "7uYTE,:Aer" -$res = $bitwarden_client->secrets->update($secret_id, $key, $note, $organization_id, [$project_id], $secret); +### Update secret -// delete secret -$res = $bitwarden_sdk->secrets->delete([$secret_id]); +```php +$key = "Updated key"; +$note = "Updated note"; +$value = "Updated value"; +$res = $bitwarden_client->secrets->update($secret_id, $key, $note, $organization_id, [$project_id], $value); +``` + +### Delete secret + +```php +$res = $bitwarden_client->secrets->delete([$secret_id]); ``` +[Access Tokens]: https://bitwarden.com/help/access-tokens/ [Bitwarden Secrets Manager]: https://bitwarden.com/products/secrets-manager/ From cb87747d315acbc0795faf05339247fe7b1d1926 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Thu, 11 Jul 2024 11:10:16 +0200 Subject: [PATCH 07/36] Revert "SM-1266: Consistent FFI library directories" This reverts commit d124c3716d439a4720ac486f06270392c865d246. --- languages/php/src/BitwardenLib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/php/src/BitwardenLib.php b/languages/php/src/BitwardenLib.php index 46d19c798..351728986 100644 --- a/languages/php/src/BitwardenLib.php +++ b/languages/php/src/BitwardenLib.php @@ -34,9 +34,9 @@ public function __construct() } elseif (PHP_OS === 'Darwin') { $architecture = trim(exec('uname -m')); if ($architecture === 'x86_64' || $architecture === 'amd64') { - $lib_file = '/lib/macos-x64/libbitwarden_c.dylib'; + $lib_file = __DIR__.'/lib/macos-x64/libbitwarden_c.dylib'; } elseif ($architecture === 'arm64') { - $lib_file = '/lib/macos-arm64/libbitwarden_c.dylib'; + $lib_file = __DIR__.'/lib/macos-arm64/libbitwarden_c.dylib'; } if (file_exists($lib_file) == false) { $lib_file = __DIR__.'/../../../target/debug/libbitwarden_c.dylib'; From e58a8a94739e2b77fa49fe0612f3ec043a4d1bb5 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Thu, 11 Jul 2024 11:55:06 +0200 Subject: [PATCH 08/36] SM-1266: Native library locations docs update --- languages/php/INSTALL.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/languages/php/INSTALL.md b/languages/php/INSTALL.md index f9be34251..e4c13a12e 100644 --- a/languages/php/INSTALL.md +++ b/languages/php/INSTALL.md @@ -11,10 +11,15 @@ Composer is used to build PHP Bitwarden client library. - Composer - Bitwarden SDK native library, which is expected in one of below locations, depending on the OS and architecture. If you prefer to build SDK yourself, see [SDK README.md](../../README.md) for instructions. - - Windows x86_64: `/lib/windows-x64/bitwarden_c.dll` - - Linux x86_64: `/lib/linux-x64/libbitwarden_c.so` - - macOS x86_64: `/lib/macos-x64/libbitwarden_c.dylib` - - macOS aarch64: `/lib/macos-arm64/libbitwarden_c.dylib` + - Windows: + - x86_64: `C:\lib\windows-x64\bitwarden_c.dll`. + - The drive letter is determined by the workdir of the PHP process, usually `C:` + - Linux: + - x86_64: `/lib/linux-x64/libbitwarden_c.so` + - macOS: + - x86_64: `./src/lib/macos-x64/libbitwarden_c.dylib` + - aarch64: `./src/lib/macos-arm64/libbitwarden_c.dylib` + - Where the `./src` is relative path to the [src](./src) directory. ## Build Commands From 510ebb0a82f85e63ac0f7936fa2aab476b43ceb0 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Fri, 12 Jul 2024 11:56:36 +0200 Subject: [PATCH 09/36] SM-1266: Native library locations relative to src --- languages/php/INSTALL.md | 19 ++++++++----------- languages/php/src/BitwardenLib.php | 4 ++-- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/languages/php/INSTALL.md b/languages/php/INSTALL.md index e4c13a12e..efa609630 100644 --- a/languages/php/INSTALL.md +++ b/languages/php/INSTALL.md @@ -9,17 +9,14 @@ Composer is used to build PHP Bitwarden client library. - PHP >= 8.0 - FFI extension enabled in PHP configuration - Composer -- Bitwarden SDK native library, which is expected in one of below locations, depending on the OS and architecture. - If you prefer to build SDK yourself, see [SDK README.md](../../README.md) for instructions. - - Windows: - - x86_64: `C:\lib\windows-x64\bitwarden_c.dll`. - - The drive letter is determined by the workdir of the PHP process, usually `C:` - - Linux: - - x86_64: `/lib/linux-x64/libbitwarden_c.so` - - macOS: - - x86_64: `./src/lib/macos-x64/libbitwarden_c.dylib` - - aarch64: `./src/lib/macos-arm64/libbitwarden_c.dylib` - - Where the `./src` is relative path to the [src](./src) directory. +- Bitwarden SDK native library. + - Expected in one of below locations, depending on the OS and architecture. + The `src` is relative path to the [src](./src) directory. + - Windows x86_64: `src\lib\windows-x64\bitwarden_c.dll` + - Linux x86_64: `src/lib/linux-x64/libbitwarden_c.so` + - macOS x86_64: `src/lib/macos-x64/libbitwarden_c.dylib` + - macOS aarch64: `src/lib/macos-arm64/libbitwarden_c.dylib` + - If you prefer to build SDK yourself, see [SDK README.md](../../README.md) for instructions. ## Build Commands diff --git a/languages/php/src/BitwardenLib.php b/languages/php/src/BitwardenLib.php index 351728986..399aba6e8 100644 --- a/languages/php/src/BitwardenLib.php +++ b/languages/php/src/BitwardenLib.php @@ -22,12 +22,12 @@ public function __construct() $lib_file = null; if (PHP_OS === 'WINNT') { - $lib_file = '/lib/windows-x64/bitwarden_c.dll'; + $lib_file = __DIR__.'/lib/windows-x64/bitwarden_c.dll'; if (file_exists($lib_file) == false) { $lib_file = __DIR__.'/../../../target/debug/bitwarden_c.dll'; } } elseif (PHP_OS === 'Linux') { - $lib_file = '/lib/linux-x64/libbitwarden_c.so'; + $lib_file = __DIR__.'/lib/linux-x64/libbitwarden_c.so'; if (file_exists($lib_file) == false) { $lib_file = __DIR__.'/../../../target/debug/libbitwarden_c.so'; } From 7f03f3e68d484e0692640cdb2f97e3395778b490 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:28:20 -0700 Subject: [PATCH 10/36] feat: `login_access_token` with state_file; update examples --- languages/php/README.md | 13 ++++++----- languages/php/example.php | 33 ++++++++++++++++++++++++++- languages/php/src/BitwardenClient.php | 5 ++-- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/languages/php/README.md b/languages/php/README.md index 9e4a9385d..87169edd8 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -16,24 +16,25 @@ If you are not using the standalone version of this library, file will be placed ## Usage To interact with the client first you need to obtain the access token from Bitwarden. -You can then initialize BitwardenSettings passing $api_url and $identity_url if needed. These parameteres are -optional and if they are not defined, BitwardenSettings instance will try to get these values from ENV, and +You can then initialize BitwardenSettings passing `$api_url` and `$identity_url` if needed. These parameters are +optional and if they are not defined, the `BitwardenSettings` instance will try to get these values from ENV, and if they are not defined there as well, it will use defaults: `https://api.bitwarden.com` as api_url and `https://identity.bitwarden.com` as identity_url. You can also pass device type as argument but that is entirely optional. -Passing BitwardenSettings instance to BitwardenClient will initialize it. Before using the client you must -be authorized by calling the access_token_login method passing your Bitwarden access token to it. +Passing a `BitwardenSettings` instance to `BitwardenClient` will initialize it. Before using the client you must +be authorized by calling the `login_access_token` method passing your Bitwarden access token to it. ```php $access_token = ''; +$state_file = ''; $api_url = ""; $identity_url = ""; $bitwarden_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($bitwarden_settings); -$bitwarden_client->access_token_login($access_token); +$bitwarden_client->login_access_token($access_token, $state_file); ``` After successful authorization you can interact with client to manage your projects and secrets. @@ -41,7 +42,7 @@ After successful authorization you can interact with client to manage your proje $organization_id = ""; $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($bitwarden_settings); -$res = $bitwarden_client->access_token_login($access_token); +$res = $bitwarden_client->login_access_token($access_token, $state_file); // create project $name = "PHP project" diff --git a/languages/php/example.php b/languages/php/example.php index 7eafcb96a..fb250623b 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -3,6 +3,7 @@ require_once 'vendor/autoload.php'; $access_token = getenv('ACCESS_TOKEN'); +$state_file = getenv('STATE_FILE'); $organization_id = getenv('ORGANIZATION_ID'); // Configuring the URLS is optional, set them to null to use the default values @@ -12,36 +13,66 @@ $client_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); -$bitwarden_client->access_token_login($access_token); +try { + $bitwarden_client->login_access_token($access_token, $state_file); +} catch (Exception $e) { + print("Error: " . $e->getMessage() . "\n"); + exit(1); +} // create project +print("Projects:\n"); $res = $bitwarden_client->projects->create('php project', $organization_id); $project_id = $res->id; +print("\tcreate: '" . $project_id . "'\n"); // get project $res = $bitwarden_client->projects->get($project_id); +print("\tget: '" . $res->name . "'\n"); // list projects $res = $bitwarden_client->projects->list($organization_id); +print("\tlist:\n"); +foreach ($res->data as $project) { + print("\t\tID: '" . $project->id . "', Name: '" . $project->name . "'\n"); +} // update project $res = $bitwarden_client->projects->put($project_id, 'php test awesome', $organization_id); +print("\tupdate: '" . $res->name . "'\n\n"); // create secret +print("Secrets:\n"); $res = $bitwarden_client->secrets->create("New Key", "hello world", $organization_id, [$project_id], "123"); $secret_id = $res->id; +print("\tcreate: '" . $secret_id . "'\n"); // get secret $res = $bitwarden_client->secrets->get($secret_id); +print("\tget: '" . $res->key . "'\n"); // list secrets $res = $bitwarden_client->secrets->list($organization_id); +print("\tlist:\n"); +foreach ($res->data as $secret) { + print("\t\tID: '" . $secret->id . "', Name: '" . $secret->key . "'\n"); +} // update secret $res = $bitwarden_client->secrets->update($secret_id, "hello world 2", "hello", $organization_id, [$project_id], "123"); +print("\tupdate: '" . $res->key . "'\n\n"); // delete secret +print("Cleaning up secrets and projects:\n"); $res = $bitwarden_client->secrets->delete([$secret_id]); +print("\tdelete:\n"); +foreach ($res->data as $secret) { + print("\t\tdeleted secret: '" . $secret->id . "'\n\n"); +} // delete project $res = $bitwarden_client->projects->delete([$project_id]); +print("\tdelete:\n"); +foreach ($res->data as $project) { + print("\t\tdeleted project: '" . $project->id . "'\n\n"); +} diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index 79fccdf9c..bddd3fbeb 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -41,12 +41,13 @@ public function __construct(BitwardenSettings $bitwardenSettings) /** * @throws \Exception */ - public function access_token_login(string $access_token) + public function login_access_token(string $access_token, string $state_file): void { $access_token_request = new AccessTokenLoginRequest(); $access_token_request->accessToken = $access_token; + $access_token_request->stateFile = $state_file; $command = new Command(); - $command->accessTokenLogin = $access_token_request->jsonSerialize(); + $command->loginAccessToken = $access_token_request->jsonSerialize(); $result = $this->commandRunner->run($command); if (!isset($result->authenticated)) { throw new \Exception("Authorization error"); From 00b1647986cdb83e5c071313c4f5bc6c8182e20f Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 6 Sep 2024 06:03:43 -0700 Subject: [PATCH 11/36] fix: getbyids --- languages/php/example.php | 7 +++++++ languages/php/src/SecretsClient.php | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/languages/php/example.php b/languages/php/example.php index fb250623b..73b96b76f 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -51,6 +51,13 @@ $res = $bitwarden_client->secrets->get($secret_id); print("\tget: '" . $res->key . "'\n"); +// get multiple secrets by ids +$res = $bitwarden_client->secrets->get_by_ids([$secret_id]); +print("\tget_by_ids:\n"); +foreach ($res->data as $secret) { + print("\t\tID: '" . $secret->id . "', Name: '" . $secret->key . "'\n"); +} + // list secrets $res = $bitwarden_client->secrets->list($organization_id); print("\tlist:\n"); diff --git a/languages/php/src/SecretsClient.php b/languages/php/src/SecretsClient.php index d5c0b0cef..89e8e980f 100644 --- a/languages/php/src/SecretsClient.php +++ b/languages/php/src/SecretsClient.php @@ -36,7 +36,7 @@ public function get_by_ids(array $secret_ids): \stdClass $project_get_by_ids_request->ids = $secret_ids; $project_get_by_ids_request->validate(); $secrets_command = new SecretsCommand(); - $secrets_command->get_by_ids = $project_get_by_ids_request->jsonSerialize(); + $secrets_command->getByIds = $project_get_by_ids_request->jsonSerialize(); return $this->run_secret_command($secrets_command); } From c8ae6b1927e6614efe35f8b0fa4625006f038d65 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 6 Sep 2024 06:05:33 -0700 Subject: [PATCH 12/36] refactor: projects.put -> projects.update --- languages/php/README.md | 3 ++- languages/php/example.php | 2 +- languages/php/src/ProjectsClient.php | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/languages/php/README.md b/languages/php/README.md index 87169edd8..029479cdd 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -38,6 +38,7 @@ $bitwarden_client->login_access_token($access_token, $state_file); ``` After successful authorization you can interact with client to manage your projects and secrets. + ```php $organization_id = ""; @@ -57,7 +58,7 @@ $res = $bitwarden_client->projects->list($organization_id); // update project $name = "Updated PHP project" -$res = $bitwarden_client->projects->put($project_id, $name, $organization_id); +$res = $bitwarden_client->projects->update($project_id, $name, $organization_id); // get secret $res = $bitwarden_client->secrets->get($secret_id); diff --git a/languages/php/example.php b/languages/php/example.php index 73b96b76f..2acf436bc 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -38,7 +38,7 @@ } // update project -$res = $bitwarden_client->projects->put($project_id, 'php test awesome', $organization_id); +$res = $bitwarden_client->projects->update($project_id, 'php test awesome', $organization_id); print("\tupdate: '" . $res->name . "'\n\n"); // create secret diff --git a/languages/php/src/ProjectsClient.php b/languages/php/src/ProjectsClient.php index 6b6f9fb6a..92d7dd53f 100644 --- a/languages/php/src/ProjectsClient.php +++ b/languages/php/src/ProjectsClient.php @@ -50,7 +50,7 @@ public function create(string $project_name, string $organization_id): \stdClass return $this->run_project_command($project_command); } - public function put(string $project_id, string $project_name, string $organization_id): \stdClass + public function update(string $project_id, string $project_name, string $organization_id): \stdClass { $project_put_request = new ProjectPutRequest(); $project_put_request->organizationId = $organization_id; From 513b888dda04f8228c882a291b2e173a9f50233e Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 6 Sep 2024 08:17:10 -0700 Subject: [PATCH 13/36] feat: secret syncing --- languages/php/example.php | 13 ++++++++++++- languages/php/src/SecretsClient.php | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/languages/php/example.php b/languages/php/example.php index 2acf436bc..f2f5f42cc 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -41,8 +41,19 @@ $res = $bitwarden_client->projects->update($project_id, 'php test awesome', $organization_id); print("\tupdate: '" . $res->name . "'\n\n"); -// create secret +// sync secrets print("Secrets:\n"); +print("\tsyncing secrets...\n"); +$res = $bitwarden_client->secrets->sync($organization_id,null); +$now = new DateTime(); +$now_string = $now->format('Y-m-d\TH:i:s.u\Z'); +print("\t\tsync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n"); + +print("\tsyncing again to ensure no changes since last sync...\n"); +$res = $bitwarden_client->secrets->sync($organization_id, $now_string); +print("\t\tsync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n"); + +// create secret $res = $bitwarden_client->secrets->create("New Key", "hello world", $organization_id, [$project_id], "123"); $secret_id = $res->id; print("\tcreate: '" . $secret_id . "'\n"); diff --git a/languages/php/src/SecretsClient.php b/languages/php/src/SecretsClient.php index 89e8e980f..8226e3610 100644 --- a/languages/php/src/SecretsClient.php +++ b/languages/php/src/SecretsClient.php @@ -10,6 +10,7 @@ use Bitwarden\Sdk\Schemas\SecretsCommand; use Bitwarden\Sdk\Schemas\SecretsDeleteRequest; use Bitwarden\Sdk\Schemas\SecretsGetRequest; +use Bitwarden\Sdk\Schemas\SecretsSyncRequest; class SecretsClient { @@ -89,6 +90,21 @@ public function delete(array $secrets_ids): \stdClass return $this->run_secret_command($secrets_command); } + public function sync(string $organization_id, ?string $last_synced_date): \stdClass + { + if (empty($last_synced_date)) { + $last_synced_date = "1970-01-01T00:00:00.000Z"; + } + + $secrets_sync_request = new SecretsSyncRequest(); + $secrets_sync_request->organizationId = $organization_id; + $secrets_sync_request->lastSyncedDate = $last_synced_date; + $secrets_sync_request->validate(); + $secrets_command = new SecretsCommand(); + $secrets_command->sync = $secrets_sync_request->jsonSerialize(); + return $this->run_secret_command($secrets_command); + } + public function run_secret_command($secretsCommand): \stdClass { $command = new Command(); From 5f8d32200a486746d69978cdc6660d77f12784c9 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 6 Sep 2024 08:18:21 -0700 Subject: [PATCH 14/36] Manually generated secretSyncRequest schema --- .../php/src/schemas/SecretsSyncRequest.php | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 languages/php/src/schemas/SecretsSyncRequest.php diff --git a/languages/php/src/schemas/SecretsSyncRequest.php b/languages/php/src/schemas/SecretsSyncRequest.php new file mode 100644 index 000000000..430be16fc --- /dev/null +++ b/languages/php/src/schemas/SecretsSyncRequest.php @@ -0,0 +1,45 @@ +organizationId = Schema::string(); + $properties->organizationId->format = "uuid"; + $properties->organizationId->description = "Organization ID"; + $properties->lastSyncedDate = Schema::string(); + $properties->lastSyncedDate->format = "date-time"; + $properties->lastSyncedDate->description = "Last synced date"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->organizationId, + ); + $ownerSchema->setFromRef('#/definitions/SecretsSyncRequest'); + } +} From 7767ffcafc26e5caa5b6f299272d3fe7e6a93cb4 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 6 Sep 2024 08:37:10 -0700 Subject: [PATCH 15/36] udpate function args --- languages/php/example.php | 8 ++++---- languages/php/src/ProjectsClient.php | 4 ++-- languages/php/src/SecretsClient.php | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/languages/php/example.php b/languages/php/example.php index f2f5f42cc..6d99718a8 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -22,7 +22,7 @@ // create project print("Projects:\n"); -$res = $bitwarden_client->projects->create('php project', $organization_id); +$res = $bitwarden_client->projects->create($organization_id, 'php project'); $project_id = $res->id; print("\tcreate: '" . $project_id . "'\n"); @@ -38,7 +38,7 @@ } // update project -$res = $bitwarden_client->projects->update($project_id, 'php test awesome', $organization_id); +$res = $bitwarden_client->projects->update($organization_id, $project_id, 'php test awesome'); print("\tupdate: '" . $res->name . "'\n\n"); // sync secrets @@ -54,7 +54,7 @@ print("\t\tsync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n"); // create secret -$res = $bitwarden_client->secrets->create("New Key", "hello world", $organization_id, [$project_id], "123"); +$res = $bitwarden_client->secrets->create($organization_id, "New Key", "New value", "New note", [$project_id]); $secret_id = $res->id; print("\tcreate: '" . $secret_id . "'\n"); @@ -77,7 +77,7 @@ } // update secret -$res = $bitwarden_client->secrets->update($secret_id, "hello world 2", "hello", $organization_id, [$project_id], "123"); +$res = $bitwarden_client->secrets->update($organization_id, $secret_id, "Updated key", "Updated value", "Updated note", [$project_id]); print("\tupdate: '" . $res->key . "'\n\n"); // delete secret diff --git a/languages/php/src/ProjectsClient.php b/languages/php/src/ProjectsClient.php index 92d7dd53f..582a70743 100644 --- a/languages/php/src/ProjectsClient.php +++ b/languages/php/src/ProjectsClient.php @@ -39,7 +39,7 @@ public function list(string $organization_id): \stdClass return $this->run_project_command($project_command); } - public function create(string $project_name, string $organization_id): \stdClass + public function create(string $organization_id, string $project_name): \stdClass { $project_create_request = new ProjectCreateRequest(); $project_create_request->name = $project_name; @@ -50,7 +50,7 @@ public function create(string $project_name, string $organization_id): \stdClass return $this->run_project_command($project_command); } - public function update(string $project_id, string $project_name, string $organization_id): \stdClass + public function update(string $organization_id, string $project_id, string $project_name): \stdClass { $project_put_request = new ProjectPutRequest(); $project_put_request->organizationId = $organization_id; diff --git a/languages/php/src/SecretsClient.php b/languages/php/src/SecretsClient.php index 8226e3610..ef949ce85 100644 --- a/languages/php/src/SecretsClient.php +++ b/languages/php/src/SecretsClient.php @@ -51,7 +51,7 @@ public function list(string $organization_id): \stdClass return $this->run_secret_command($secrets_command); } - public function create(string $key, string $note, string $organization_id, array $project_ids, string $value): \stdClass + public function create(string $organization_id, string $key, string $value, string $note, array $project_ids): \stdClass { $secrets_create_request = new SecretCreateRequest(); $secrets_create_request->organizationId = $organization_id; @@ -65,7 +65,7 @@ public function create(string $key, string $note, string $organization_id, array return $this->run_secret_command($secrets_command); } - public function update(string $id, string $key, string $note, string $organization_id, array $project_ids, string $value): \stdClass + public function update(string $organization_id, string $id, string $key, string $value, string $note, array $project_ids): \stdClass { $secrets_put_request = new SecretPutRequest(); $secrets_put_request->id = $id; From c44f52aedcd1a4f17c6e6c1d0a42e6a7e25db313 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 6 Sep 2024 08:50:48 -0700 Subject: [PATCH 16/36] tweak output format --- languages/php/example.php | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/languages/php/example.php b/languages/php/example.php index 6d99718a8..642511a87 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -24,11 +24,11 @@ print("Projects:\n"); $res = $bitwarden_client->projects->create($organization_id, 'php project'); $project_id = $res->id; -print("\tcreate: '" . $project_id . "'\n"); +print("\tcreate: '" . $project_id . "'\n\n"); // get project $res = $bitwarden_client->projects->get($project_id); -print("\tget: '" . $res->name . "'\n"); +print("\tget: '" . $res->name . "'\n\n"); // list projects $res = $bitwarden_client->projects->list($organization_id); @@ -36,6 +36,7 @@ foreach ($res->data as $project) { print("\t\tID: '" . $project->id . "', Name: '" . $project->name . "'\n"); } +print("\n"); // update project $res = $bitwarden_client->projects->update($organization_id, $project_id, 'php test awesome'); @@ -43,38 +44,40 @@ // sync secrets print("Secrets:\n"); -print("\tsyncing secrets...\n"); +print("\tSyncing secrets...\n"); $res = $bitwarden_client->secrets->sync($organization_id,null); $now = new DateTime(); $now_string = $now->format('Y-m-d\TH:i:s.u\Z'); -print("\t\tsync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n"); +print("\t\tSync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n\n"); -print("\tsyncing again to ensure no changes since last sync...\n"); +print("\tSyncing again to ensure no changes since last sync...\n"); $res = $bitwarden_client->secrets->sync($organization_id, $now_string); -print("\t\tsync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n"); +print("\t\tSync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n\n"); // create secret $res = $bitwarden_client->secrets->create($organization_id, "New Key", "New value", "New note", [$project_id]); $secret_id = $res->id; -print("\tcreate: '" . $secret_id . "'\n"); +print("\tcreate: '" . $secret_id . "'\n\n"); // get secret $res = $bitwarden_client->secrets->get($secret_id); -print("\tget: '" . $res->key . "'\n"); +print("\tget: '" . $res->key . "'\n\n"); // get multiple secrets by ids $res = $bitwarden_client->secrets->get_by_ids([$secret_id]); print("\tget_by_ids:\n"); foreach ($res->data as $secret) { - print("\t\tID: '" . $secret->id . "', Name: '" . $secret->key . "'\n"); + print("\t\tID: '" . $secret->id . "', Key: '" . $secret->key . "'\n"); } +print("\n"); // list secrets $res = $bitwarden_client->secrets->list($organization_id); print("\tlist:\n"); foreach ($res->data as $secret) { - print("\t\tID: '" . $secret->id . "', Name: '" . $secret->key . "'\n"); + print("\t\tID: '" . $secret->id . "', Key: '" . $secret->key . "'\n"); } +print("\n"); // update secret $res = $bitwarden_client->secrets->update($organization_id, $secret_id, "Updated key", "Updated value", "Updated note", [$project_id]); @@ -85,12 +88,14 @@ $res = $bitwarden_client->secrets->delete([$secret_id]); print("\tdelete:\n"); foreach ($res->data as $secret) { - print("\t\tdeleted secret: '" . $secret->id . "'\n\n"); + print("\t\tdeleted secret: '" . $secret->id . "'\n"); } +print("\n"); // delete project $res = $bitwarden_client->projects->delete([$project_id]); print("\tdelete:\n"); foreach ($res->data as $project) { - print("\t\tdeleted project: '" . $project->id . "'\n\n"); + print("\t\tdeleted project: '" . $project->id . "'\n"); } +print("\n"); From ef6a72583f746f0b8662edffdd0d5af6ef66bd3d Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:45:58 -0700 Subject: [PATCH 17/36] move loginaccesstoken into authclient --- languages/php/example.php | 2 +- languages/php/src/BitwardenClient.php | 50 +++++++++++++++++---------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/languages/php/example.php b/languages/php/example.php index 642511a87..3590d9f9e 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -14,7 +14,7 @@ $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); try { - $bitwarden_client->login_access_token($access_token, $state_file); + $bitwarden_client->auth()->login_access_token($access_token, $state_file); } catch (Exception $e) { print("Error: " . $e->getMessage() . "\n"); exit(1); diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index bddd3fbeb..4e65529ef 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -6,8 +6,34 @@ use Bitwarden\Sdk\schemas\ClientSettings; use Bitwarden\Sdk\Schemas\Command; use FFI; -use Swaggest\JsonDiff\Exception; +class AuthClient { + private CommandRunner $commandRunner; + + public function __construct(CommandRunner $commandRunner) { + $this->commandRunner = $commandRunner; + } + + /** + * @throws \Exception + */ + public function login_access_token(string $access_token, string $state_file): void + { + $access_token_request = new AccessTokenLoginRequest(); + $access_token_request->accessToken = $access_token; + $access_token_request->stateFile = $state_file; + $command = new Command(); + $command->loginAccessToken = $access_token_request->jsonSerialize(); + $result = $this->commandRunner->run($command); + if (!isset($result->authenticated)) { + throw new \Exception("Authorization error"); + } + + if ($result->authenticated == False) { + throw new \Exception("Unauthorized"); + } + } +} class BitwardenClient { @@ -21,6 +47,8 @@ class BitwardenClient private CommandRunner $commandRunner; + private ?AuthClient $authClient; + private FFI\CData $handle; public function __construct(BitwardenSettings $bitwardenSettings) @@ -38,24 +66,10 @@ public function __construct(BitwardenSettings $bitwardenSettings) $this->secrets = new SecretsClient($this->commandRunner); } - /** - * @throws \Exception - */ - public function login_access_token(string $access_token, string $state_file): void + public function auth(): AuthClient { - $access_token_request = new AccessTokenLoginRequest(); - $access_token_request->accessToken = $access_token; - $access_token_request->stateFile = $state_file; - $command = new Command(); - $command->loginAccessToken = $access_token_request->jsonSerialize(); - $result = $this->commandRunner->run($command); - if (!isset($result->authenticated)) { - throw new \Exception("Authorization error"); - } - - if ($result->authenticated == False) { - throw new \Exception("Unauthorized"); - } + $this->authClient = new AuthClient($this->commandRunner); + return $this->authClient; } public function __destruct() From 0c9500d881b621637b9187d26627f2893119b718 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Mon, 9 Sep 2024 06:23:13 -0700 Subject: [PATCH 18/36] Manually update PHP schemas --- .../src/schemas/AccessTokenLoginRequest.php | 2 + .../src/schemas/BitwardenClassStructure.php | 11 - .../schemas/BitwardenClassStructureTrait.php | 189 ------------------ languages/php/src/schemas/ClientSettings.php | 17 +- languages/php/src/schemas/Command.php | 34 ++-- .../php/src/schemas/ProjectCreateRequest.php | 2 + .../php/src/schemas/ProjectGetRequest.php | 3 +- .../php/src/schemas/ProjectPutRequest.php | 2 + languages/php/src/schemas/ProjectsCommand.php | 42 ++-- .../php/src/schemas/SecretCreateRequest.php | 5 + .../php/src/schemas/SecretPutRequest.php | 7 +- languages/php/src/schemas/SecretsCommand.php | 46 ++--- .../php/src/schemas/SecretsSyncRequest.php | 13 +- 13 files changed, 73 insertions(+), 300 deletions(-) delete mode 100644 languages/php/src/schemas/BitwardenClassStructure.php delete mode 100644 languages/php/src/schemas/BitwardenClassStructureTrait.php diff --git a/languages/php/src/schemas/AccessTokenLoginRequest.php b/languages/php/src/schemas/AccessTokenLoginRequest.php index a08805f92..8c22066b3 100644 --- a/languages/php/src/schemas/AccessTokenLoginRequest.php +++ b/languages/php/src/schemas/AccessTokenLoginRequest.php @@ -14,6 +14,7 @@ /** * Login to Bitwarden with access token * Built from #/definitions/AccessTokenLoginRequest + * @property string|null $stateFile */ class AccessTokenLoginRequest extends ClassStructure { @@ -28,6 +29,7 @@ public static function setUpProperties($properties, Schema $ownerSchema) { $properties->accessToken = Schema::string(); $properties->accessToken->description = "Bitwarden service API access token"; + $properties->stateFile = (new Schema())->setType([Schema::STRING, Schema::NULL]); $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; $ownerSchema->description = "Login to Bitwarden with access token"; diff --git a/languages/php/src/schemas/BitwardenClassStructure.php b/languages/php/src/schemas/BitwardenClassStructure.php deleted file mode 100644 index fd50354d4..000000000 --- a/languages/php/src/schemas/BitwardenClassStructure.php +++ /dev/null @@ -1,11 +0,0 @@ -properties = $properties; - $schema->objectItemClass = $className; - $schemaWrapper = new Wrapper($schema); - static::setUpProperties($properties, $schema); - if (null === $schema->getFromRefs()) { - $schema->setFromRef('#/definitions/' . $className); - } - if ($properties->isEmpty()) { - $schema->properties = null; - } - $properties->lock(); - } - - return $schemaWrapper; - } - - /** - * @return Properties|static|null - */ - public static function properties() - { - return static::schema()->getProperties(); - } - - /** - * @param mixed $data - * @param Context $options - * @return static|mixed - * @throws \Swaggest\JsonSchema\Exception - * @throws \Swaggest\JsonSchema\InvalidValue - */ - public static function import($data, Context $options = null) - { - return static::schema()->in($data, $options); - } - - /** - * @param mixed $data - * @param Context $options - * @return mixed - * @throws \Swaggest\JsonSchema\InvalidValue - * @throws \Exception - */ - public static function export($data, Context $options = null) - { - return static::schema()->out($data, $options); - } - - /** - * @param ObjectItemContract $objectItem - * @return static - */ - public static function pick(ObjectItemContract $objectItem) - { - $className = get_called_class(); - return $objectItem->getNestedObject($className); - } - - /** - * @return static - */ - public static function create() - { - return new static; - } - - protected $__validateOnSet = true; // todo skip validation during import - - /** - * @return \stdClass - */ - #[\ReturnTypeWillChange] - public function jsonSerialize() - { - $result = new \stdClass(); - $schema = static::schema(); - $properties = $schema->getProperties(); - $processed = array(); - if (null !== $properties) { - foreach ($properties->getDataKeyMap() as $propertyName => $dataName) { - $value = $this->$propertyName ?? null; - - // Value is exported if exists. - if (null !== $value || array_key_exists($propertyName, $this->__arrayOfData)) { - $result->$dataName = $value; - $processed[$propertyName] = true; - continue; - } - - // Non-existent value is only exported if belongs to nullable property (having 'null' in type array). - $property = $schema->getProperty($propertyName); - if ($property instanceof Schema) { - $types = $property->type; - if ($types === Schema::NULL || (is_array($types) && in_array(Schema::NULL, $types))) { - $result->$dataName = $value; - } - } - } - } - foreach ($schema->getNestedPropertyNames() as $name) { - /** @var ObjectItem $nested */ - $nested = $this->$name; - if (null !== $nested) { - foreach ((array)$nested->jsonSerialize() as $key => $value) { - $result->$key = $value; - } - } - } - - if (!empty($this->__arrayOfData)) { - foreach ($this->__arrayOfData as $name => $value) { - if (!isset($processed[$name])) { - $result->$name = $this->{$name}; - } - } - } - - return $result; - } - - /** - * @return static|NameMirror - */ - public static function names(Properties $properties = null, $mapping = Schema::DEFAULT_MAPPING) - { - if ($properties !== null) { - return new NameMirror($properties->getDataKeyMap($mapping)); - } - - static $nameflector = null; - if (null === $nameflector) { - $nameflector = new NameMirror(); - } - return $nameflector; - } - - public function __set($name, $column) // todo nested schemas - { - if ($this->__validateOnSet) { - if ($property = static::schema()->getProperty($name)) { - $property->out($column); - } - } - $this->__arrayOfData[$name] = $column; - return $this; - } - - public static function className() - { - return get_called_class(); - } - - /** - * @throws \Exception - * @throws \Swaggest\JsonSchema\InvalidValue - */ - public function validate() - { - static::schema()->out($this); - } -} - diff --git a/languages/php/src/schemas/ClientSettings.php b/languages/php/src/schemas/ClientSettings.php index c27cc3322..9717169c4 100644 --- a/languages/php/src/schemas/ClientSettings.php +++ b/languages/php/src/schemas/ClientSettings.php @@ -12,14 +12,12 @@ /** - * ClientSettings * Basic client behavior settings. These settings specify the various targets and behavior of the Bitwarden Client. They are optional and uneditable once the client is initialized. - * + * * Defaults to - * - * ``` # use bitwarden::client::client_settings::{ClientSettings, DeviceType}; # use assert_matches::assert_matches; let settings = ClientSettings { identity_url: "https://identity.bitwarden.com".to_string(), api_url: "https://api.bitwarden.com".to_string(), user_agent: "Bitwarden Rust-SDK".to_string(), device_type: DeviceType::SDK, }; let default = ClientSettings::default(); assert_matches!(settings, default); ``` - * - * Targets `localhost:8080` for debug builds. + * + * ``` # use bitwarden_core::{ClientSettings, DeviceType}; let settings = ClientSettings { identity_url: "https://identity.bitwarden.com".to_string(), api_url: "https://api.bitwarden.com".to_string(), user_agent: "Bitwarden Rust-SDK".to_string(), device_type: DeviceType::SDK, }; let default = ClientSettings::default(); ``` + * Built from #/definitions/ClientSettings */ class ClientSettings extends ClassStructure { @@ -126,8 +124,7 @@ public static function setUpProperties($properties, Schema $ownerSchema) $properties->deviceType->default = "SDK"; $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; - $ownerSchema->schema = "http://json-schema.org/draft-07/schema#"; - $ownerSchema->title = "ClientSettings"; - $ownerSchema->description = "Basic client behavior settings. These settings specify the various targets and behavior of the Bitwarden Client. They are optional and uneditable once the client is initialized.\n\nDefaults to\n\n``` # use bitwarden::client::client_settings::{ClientSettings, DeviceType}; # use assert_matches::assert_matches; let settings = ClientSettings { identity_url: \"https://identity.bitwarden.com\".to_string(), api_url: \"https://api.bitwarden.com\".to_string(), user_agent: \"Bitwarden Rust-SDK\".to_string(), device_type: DeviceType::SDK, }; let default = ClientSettings::default(); assert_matches!(settings, default); ```\n\nTargets `localhost:8080` for debug builds."; + $ownerSchema->description = "Basic client behavior settings. These settings specify the various targets and behavior of the Bitwarden Client. They are optional and uneditable once the client is initialized.\n\nDefaults to\n\n``` # use bitwarden_core::{ClientSettings, DeviceType}; let settings = ClientSettings { identity_url: \"https://identity.bitwarden.com\".to_string(), api_url: \"https://api.bitwarden.com\".to_string(), user_agent: \"Bitwarden Rust-SDK\".to_string(), device_type: DeviceType::SDK, }; let default = ClientSettings::default(); ```"; + $ownerSchema->setFromRef('#/definitions/ClientSettings'); } -} +} \ No newline at end of file diff --git a/languages/php/src/schemas/Command.php b/languages/php/src/schemas/Command.php index cbd649c2f..f9d0403a9 100644 --- a/languages/php/src/schemas/Command.php +++ b/languages/php/src/schemas/Command.php @@ -7,20 +7,21 @@ namespace Bitwarden\Sdk\Schemas; use Swaggest\JsonSchema\Constraint\Properties; -use Swaggest\JsonSchema\JsonSchema; use Swaggest\JsonSchema\Schema; +use Swaggest\JsonSchema\Structure\ClassStructure; -class Command extends BitwardenClassStructure +/** + * Login with Secrets Manager Access Token + * + * This command is for initiating an authentication handshake with Bitwarden. + * + * Returns: [ApiKeyLoginResponse](bitwarden::auth::login::ApiKeyLoginResponse) + */ +class Command extends ClassStructure { - /** @var ProjectsCommand|null */ - public $projects; - - /** @var SecretsCommand|null */ - public $secrets; - - /** @var AccessTokenLoginRequest|null */ - public $accessTokenLogin; + /** @var AccessTokenLoginRequest Login to Bitwarden with access token */ + public $loginAccessToken; /** * @param Properties|static $properties @@ -28,17 +29,12 @@ class Command extends BitwardenClassStructure */ public static function setUpProperties($properties, Schema $ownerSchema) { - $properties->projects = ProjectsCommand::schema(); - $properties->secrets = SecretsCommand::schema(); - $properties->accessTokenLogin = AccessTokenLoginRequest::schema(); - + $properties->loginAccessToken = AccessTokenLoginRequest::schema(); $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; - - $ownerSchema->oneOf = array( - self::names()->projects, - self::names()->secrets, - self::names()->accessTokenLogin, + $ownerSchema->description = "Login with Secrets Manager Access Token\n\nThis command is for initiating an authentication handshake with Bitwarden.\n\nReturns: [ApiKeyLoginResponse](bitwarden::auth::login::ApiKeyLoginResponse)"; + $ownerSchema->required = array( + self::names()->loginAccessToken, ); } } diff --git a/languages/php/src/schemas/ProjectCreateRequest.php b/languages/php/src/schemas/ProjectCreateRequest.php index 6a4e0f082..b63ba42b6 100644 --- a/languages/php/src/schemas/ProjectCreateRequest.php +++ b/languages/php/src/schemas/ProjectCreateRequest.php @@ -32,6 +32,8 @@ public static function setUpProperties($properties, Schema $ownerSchema) $properties->organizationId->description = "Organization where the project will be created"; $properties->organizationId->format = "uuid"; $properties->name = Schema::string(); + $properties->name->maxLength = 500; + $properties->name->minLength = 1; $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; $ownerSchema->required = array( diff --git a/languages/php/src/schemas/ProjectGetRequest.php b/languages/php/src/schemas/ProjectGetRequest.php index 972bf18ec..f316273bc 100644 --- a/languages/php/src/schemas/ProjectGetRequest.php +++ b/languages/php/src/schemas/ProjectGetRequest.php @@ -8,12 +8,13 @@ use Swaggest\JsonSchema\Constraint\Properties; use Swaggest\JsonSchema\Schema; +use Swaggest\JsonSchema\Structure\ClassStructure; /** * Built from #/definitions/ProjectGetRequest */ -class ProjectGetRequest extends BitwardenClassStructure +class ProjectGetRequest extends ClassStructure { /** @var string ID of the project to retrieve */ public $id; diff --git a/languages/php/src/schemas/ProjectPutRequest.php b/languages/php/src/schemas/ProjectPutRequest.php index 96b9705e7..327e6cbb7 100644 --- a/languages/php/src/schemas/ProjectPutRequest.php +++ b/languages/php/src/schemas/ProjectPutRequest.php @@ -38,6 +38,8 @@ public static function setUpProperties($properties, Schema $ownerSchema) $properties->organizationId->description = "Organization ID of the project to modify"; $properties->organizationId->format = "uuid"; $properties->name = Schema::string(); + $properties->name->maxLength = 500; + $properties->name->minLength = 1; $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; $ownerSchema->required = array( diff --git a/languages/php/src/schemas/ProjectsCommand.php b/languages/php/src/schemas/ProjectsCommand.php index 22645db3c..6b605ca3a 100644 --- a/languages/php/src/schemas/ProjectsCommand.php +++ b/languages/php/src/schemas/ProjectsCommand.php @@ -7,27 +7,14 @@ namespace Bitwarden\Sdk\Schemas; use Swaggest\JsonSchema\Constraint\Properties; -use Swaggest\JsonSchema\JsonSchema; use Swaggest\JsonSchema\Schema; +use Swaggest\JsonSchema\Structure\ClassStructure; -/** - * > Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the projects whose IDs match the provided ones - * - * Returns: [ProjectsDeleteResponse](bitwarden::secrets_manager::projects::ProjectsDeleteResponse) - */ -class ProjectsCommand extends BitwardenClassStructure +class ProjectsCommand extends ClassStructure { - public ?\stdClass $delete; - - public ?\stdClass $get; - - public ?\stdClass $list; - - public ?\stdClass $create; - - public ?\stdClass $update; - + /** @var ProjectGetRequest|ProjectsListRequest|ProjectsCommandOneOf2|ProjectPutRequest|ProjectCreateRequest */ + public $projects; /** * @param Properties|static $properties @@ -35,21 +22,16 @@ class ProjectsCommand extends BitwardenClassStructure */ public static function setUpProperties($properties, Schema $ownerSchema) { - $properties->delete = ProjectsDeleteRequest::schema() ? ProjectsDeleteRequest::schema() : null; - $properties->get = ProjectGetRequest::schema() ? ProjectGetRequest::schema() : null; - $properties->list = ProjectsListRequest::schema() ? ProjectsListRequest::schema() : null; - $properties->update = ProjectPutRequest::schema() ? ProjectPutRequest::schema() : null; - $properties->create = ProjectCreateRequest::schema() ? ProjectCreateRequest::schema() : null; + $properties->projects = new Schema(); + $properties->projects->get = ProjectGetRequest::schema(); + $properties->projects->list = ProjectsListRequest::schema(); + $properties->projects->update = ProjectPutRequest::schema(); + $properties->projects->create = ProjectCreateRequest::schema(); + $properties->projects->setFromRef('#/definitions/ProjectsCommand'); $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; - $ownerSchema->description = "> Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the projects whose IDs match the provided ones\n\nReturns: [ProjectsDeleteResponse](bitwarden::secrets_manager::projects::ProjectsDeleteResponse)"; - - $ownerSchema->oneOf = array( - self::names()->create, - self::names()->delete, - self::names()->get, - self::names()->list, - self::names()->update, + $ownerSchema->required = array( + self::names()->projects, ); } } diff --git a/languages/php/src/schemas/SecretCreateRequest.php b/languages/php/src/schemas/SecretCreateRequest.php index d34b36e98..a2bad860d 100644 --- a/languages/php/src/schemas/SecretCreateRequest.php +++ b/languages/php/src/schemas/SecretCreateRequest.php @@ -39,8 +39,13 @@ public static function setUpProperties($properties, Schema $ownerSchema) $properties->organizationId->description = "Organization where the secret will be created"; $properties->organizationId->format = "uuid"; $properties->key = Schema::string(); + $properties->key->maxLength = 500; + $properties->key->minLength = 1; $properties->value = Schema::string(); + $properties->value->maxLength = 25000; + $properties->value->minLength = 1; $properties->note = Schema::string(); + $properties->note->maxLength = 7000; $properties->projectIds = (new Schema())->setType([Schema::_ARRAY, Schema::NULL]); $properties->projectIds->items = Schema::string(); $properties->projectIds->items->format = "uuid"; diff --git a/languages/php/src/schemas/SecretPutRequest.php b/languages/php/src/schemas/SecretPutRequest.php index d890a909d..59edec16d 100644 --- a/languages/php/src/schemas/SecretPutRequest.php +++ b/languages/php/src/schemas/SecretPutRequest.php @@ -45,8 +45,13 @@ public static function setUpProperties($properties, Schema $ownerSchema) $properties->organizationId->description = "Organization ID of the secret to modify"; $properties->organizationId->format = "uuid"; $properties->key = Schema::string(); + $properties->key->maxLength = 500; + $properties->key->minLength = 1; $properties->value = Schema::string(); + $properties->value->maxLength = 25000; + $properties->value->minLength = 1; $properties->note = Schema::string(); + $properties->note->maxLength = 7000; $properties->projectIds = (new Schema())->setType([Schema::_ARRAY, Schema::NULL]); $properties->projectIds->items = Schema::string(); $properties->projectIds->items->format = "uuid"; @@ -61,4 +66,4 @@ public static function setUpProperties($properties, Schema $ownerSchema) ); $ownerSchema->setFromRef('#/definitions/SecretPutRequest'); } -} +} \ No newline at end of file diff --git a/languages/php/src/schemas/SecretsCommand.php b/languages/php/src/schemas/SecretsCommand.php index 1ed8c97c5..cddc8ce49 100644 --- a/languages/php/src/schemas/SecretsCommand.php +++ b/languages/php/src/schemas/SecretsCommand.php @@ -8,27 +8,13 @@ use Swaggest\JsonSchema\Constraint\Properties; use Swaggest\JsonSchema\Schema; -//use Swaggest\JsonSchema\Structure\ClassStructure; +use Swaggest\JsonSchema\Structure\ClassStructure; -/** - * > Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the secrets whose IDs match the provided ones - * - * Returns: [SecretsDeleteResponse](bitwarden::secrets_manager::secrets::SecretsDeleteResponse) - */ -class SecretsCommand extends BitwardenClassStructure +class SecretsCommand extends ClassStructure { - public ?\stdClass $delete; - - public ?\stdClass $get; - - public ?\stdClass $getByIds; - - public ?\stdClass $list; - - public ?\stdClass $create; - - public ?\stdClass $put; + /** @var SecretsDeleteRequest|SecretsGetRequest|SecretCreateRequest|SecretPutRequest|SecretIdentifiersRequest|SecretsGetRequest|SecretsSyncRequest */ + public $secrets; /** * @param Properties|static $properties @@ -36,21 +22,19 @@ class SecretsCommand extends BitwardenClassStructure */ public static function setUpProperties($properties, Schema $ownerSchema) { - $properties->delete = SecretsDeleteRequest::schema() ? SecretsDeleteRequest::schema() : null; - $properties->getByIds = SecretsGetRequest::schema() ? SecretGetRequest::schema() : null; - $properties->create = SecretCreateRequest::schema() ? SecretCreateRequest::schema() : null; - $properties->put = SecretPutRequest::schema() ? SecretPutRequest::schema() : null; - $properties->list = SecretIdentifiersRequest::schema() ? SecretIdentifiersRequest::schema() : null; - $properties->get = SecretsGetRequest::schema() ? SecretGetRequest::schema() : null; + $properties->secrets = new Schema(); + $properties->secrets->delete = SecretsDeleteRequest::schema(); + $properties->secrets->getByIds = SecretsGetRequest::schema(); + $properties->secrets->create = SecretCreateRequest::schema(); + $properties->secrets->update = SecretPutRequest::schema(); + $properties->secrets->list = SecretIdentifiersRequest::schema(); + $properties->secrets->get = SecretsGetRequest::schema(); + $properties->secrets->sync = SecretsSyncRequest::schema(); + $properties->secrets->setFromRef('#/definitions/SecretsCommand'); $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; - $ownerSchema->description = "> Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the secrets whose IDs match the provided ones\n\nReturns: [SecretsDeleteResponse](bitwarden::secrets_manager::secrets::SecretsDeleteResponse)"; - $ownerSchema->oneOf = array( - self::names()->create, - self::names()->put, - self::names()->list, - self::names()->getByIds, - self::names()->delete, + $ownerSchema->required = array( + self::names()->secrets, ); } } diff --git a/languages/php/src/schemas/SecretsSyncRequest.php b/languages/php/src/schemas/SecretsSyncRequest.php index 430be16fc..4d98db0f4 100644 --- a/languages/php/src/schemas/SecretsSyncRequest.php +++ b/languages/php/src/schemas/SecretsSyncRequest.php @@ -13,15 +13,12 @@ /** * Built from #/definitions/SecretsSyncRequest + * @property string|null $lastSyncedDate Optional date time a sync last occurred */ - class SecretsSyncRequest extends ClassStructure { - - /** @var string */ + /** @var string Organization to sync secrets from */ public $organizationId; - /** @var string */ - public $lastSyncedDate; /** * @param Properties|static $properties @@ -30,11 +27,11 @@ class SecretsSyncRequest extends ClassStructure public static function setUpProperties($properties, Schema $ownerSchema) { $properties->organizationId = Schema::string(); + $properties->organizationId->description = "Organization to sync secrets from"; $properties->organizationId->format = "uuid"; - $properties->organizationId->description = "Organization ID"; - $properties->lastSyncedDate = Schema::string(); + $properties->lastSyncedDate = (new Schema())->setType([Schema::STRING, Schema::NULL]); + $properties->lastSyncedDate->description = "Optional date time a sync last occurred"; $properties->lastSyncedDate->format = "date-time"; - $properties->lastSyncedDate->description = "Last synced date"; $ownerSchema->type = Schema::OBJECT; $ownerSchema->additionalProperties = false; $ownerSchema->required = array( From 931d781dbc54b6722310152ee8a25bcd5086f850 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Tue, 10 Sep 2024 06:16:53 -0700 Subject: [PATCH 19/36] fix schema casing; newlines --- languages/php/src/BitwardenClient.php | 5 +++-- languages/php/src/schemas/ClientSettings.php | 4 ++-- languages/php/src/schemas/ProjectsDeleteRequest.php | 2 +- languages/php/src/schemas/ProjectsListRequest.php | 2 +- languages/php/src/schemas/SecretCreateRequest.php | 2 +- languages/php/src/schemas/SecretGetRequest.php | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index 4e65529ef..499983b3c 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -3,8 +3,9 @@ namespace Bitwarden\Sdk; use Bitwarden\Sdk\Schemas\AccessTokenLoginRequest; -use Bitwarden\Sdk\schemas\ClientSettings; +use Bitwarden\Sdk\Schemas\ClientSettings; use Bitwarden\Sdk\Schemas\Command; +use Bitwarden\Sdk\Schemas; use FFI; class AuthClient { @@ -53,7 +54,7 @@ class BitwardenClient public function __construct(BitwardenSettings $bitwardenSettings) { - $this->clientSettings = new ClientSettings(); + $this->clientSettings = new \Bitwarden\Sdk\Schemas\ClientSettings(); $this->clientSettings->apiUrl = $bitwardenSettings->get_api_url(); $this->clientSettings->identityUrl = $bitwardenSettings->get_identity_url(); $this->clientSettings->userAgent = "Bitwarden PHP-SDK"; diff --git a/languages/php/src/schemas/ClientSettings.php b/languages/php/src/schemas/ClientSettings.php index 9717169c4..a64c143b8 100644 --- a/languages/php/src/schemas/ClientSettings.php +++ b/languages/php/src/schemas/ClientSettings.php @@ -13,9 +13,9 @@ /** * Basic client behavior settings. These settings specify the various targets and behavior of the Bitwarden Client. They are optional and uneditable once the client is initialized. - * + * * Defaults to - * + * * ``` # use bitwarden_core::{ClientSettings, DeviceType}; let settings = ClientSettings { identity_url: "https://identity.bitwarden.com".to_string(), api_url: "https://api.bitwarden.com".to_string(), user_agent: "Bitwarden Rust-SDK".to_string(), device_type: DeviceType::SDK, }; let default = ClientSettings::default(); ``` * Built from #/definitions/ClientSettings */ diff --git a/languages/php/src/schemas/ProjectsDeleteRequest.php b/languages/php/src/schemas/ProjectsDeleteRequest.php index 87a7cfad7..445cbbb0b 100644 --- a/languages/php/src/schemas/ProjectsDeleteRequest.php +++ b/languages/php/src/schemas/ProjectsDeleteRequest.php @@ -36,4 +36,4 @@ public static function setUpProperties($properties, Schema $ownerSchema) ); $ownerSchema->setFromRef('#/definitions/ProjectsDeleteRequest'); } -} +} \ No newline at end of file diff --git a/languages/php/src/schemas/ProjectsListRequest.php b/languages/php/src/schemas/ProjectsListRequest.php index cc1a9474f..2adf55ecb 100644 --- a/languages/php/src/schemas/ProjectsListRequest.php +++ b/languages/php/src/schemas/ProjectsListRequest.php @@ -35,4 +35,4 @@ public static function setUpProperties($properties, Schema $ownerSchema) ); $ownerSchema->setFromRef('#/definitions/ProjectsListRequest'); } -} +} \ No newline at end of file diff --git a/languages/php/src/schemas/SecretCreateRequest.php b/languages/php/src/schemas/SecretCreateRequest.php index a2bad860d..a878cbd14 100644 --- a/languages/php/src/schemas/SecretCreateRequest.php +++ b/languages/php/src/schemas/SecretCreateRequest.php @@ -60,4 +60,4 @@ public static function setUpProperties($properties, Schema $ownerSchema) ); $ownerSchema->setFromRef('#/definitions/SecretCreateRequest'); } -} +} \ No newline at end of file diff --git a/languages/php/src/schemas/SecretGetRequest.php b/languages/php/src/schemas/SecretGetRequest.php index f31f7cad3..4a4721de4 100644 --- a/languages/php/src/schemas/SecretGetRequest.php +++ b/languages/php/src/schemas/SecretGetRequest.php @@ -35,4 +35,4 @@ public static function setUpProperties($properties, Schema $ownerSchema) ); $ownerSchema->setFromRef('#/definitions/SecretGetRequest'); } -} +} \ No newline at end of file From efbf6554c997ccaaf01756fbb31a039ed85248b8 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Tue, 10 Sep 2024 06:43:45 -0700 Subject: [PATCH 20/36] revert fully-qualified call to ClientSettings; unnecessary --- languages/php/src/BitwardenClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index 499983b3c..62e760ddc 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -54,7 +54,7 @@ class BitwardenClient public function __construct(BitwardenSettings $bitwardenSettings) { - $this->clientSettings = new \Bitwarden\Sdk\Schemas\ClientSettings(); + $this->clientSettings = new ClientSettings(); $this->clientSettings->apiUrl = $bitwardenSettings->get_api_url(); $this->clientSettings->identityUrl = $bitwardenSettings->get_identity_url(); $this->clientSettings->userAgent = "Bitwarden PHP-SDK"; From 13acbc2b490e658b8b997278af0e0b573a0bf379 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Tue, 10 Sep 2024 07:45:39 -0700 Subject: [PATCH 21/36] add basic sync example to readme --- languages/php/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/languages/php/README.md b/languages/php/README.md index c3bbca6ff..439c7cd89 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -104,6 +104,13 @@ $value = "Updated value"; $res = $bitwarden_client->secrets->update($organization_id, $secret_id, $key, $value, $note, [$project_id]); ``` +### Sync secrets + +```php +$last_synced_date = "2024-09-01T00:00:00Z"; +$res = $bitwarden_client->secrets->sync($organization_id, $last_synced_date); +``` + ### Delete secret ```php From 653f47b5a70569ab0553661833f7396a03c26587 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:38:08 -0700 Subject: [PATCH 22/36] add state file to example --- languages/php/INSTALL.md | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/php/INSTALL.md b/languages/php/INSTALL.md index efa609630..fec62a20f 100644 --- a/languages/php/INSTALL.md +++ b/languages/php/INSTALL.md @@ -47,6 +47,7 @@ composer install ```shell export ACCESS_TOKEN="" +export STATE_FILE="" export ORGANIZATION_ID="" export API_URL="https://api.bitwarden.com" export IDENTITY_URL="https://identity.bitwarden.com" From e5a05966a913b3c7598e9000222447002603e683 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 11 Sep 2024 07:14:45 -0700 Subject: [PATCH 23/36] Update languages/php/README.md Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com> --- languages/php/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/README.md b/languages/php/README.md index 439c7cd89..a758da378 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -38,7 +38,7 @@ The default for `api_url` is `https://api.bitwarden.com` and for `identity_url` ```php $name = "PHP project"; -$res = $bitwarden_client->projects->create($name, $organization_id); +$res = $bitwarden_client->projects->create($organization_id, $name); $project_id = $res->id; ``` From 729eb3d61ce671d4ea0a9b360f3539b1c3c798fa Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:03:45 -0700 Subject: [PATCH 24/36] rm secretSync because git is being weird --- .../php/src/schemas/SecretsSyncRequest.php | 42 ------------------- 1 file changed, 42 deletions(-) delete mode 100644 languages/php/src/schemas/SecretsSyncRequest.php diff --git a/languages/php/src/schemas/SecretsSyncRequest.php b/languages/php/src/schemas/SecretsSyncRequest.php deleted file mode 100644 index 4d98db0f4..000000000 --- a/languages/php/src/schemas/SecretsSyncRequest.php +++ /dev/null @@ -1,42 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization to sync secrets from"; - $properties->organizationId->format = "uuid"; - $properties->lastSyncedDate = (new Schema())->setType([Schema::STRING, Schema::NULL]); - $properties->lastSyncedDate->description = "Optional date time a sync last occurred"; - $properties->lastSyncedDate->format = "date-time"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->organizationId, - ); - $ownerSchema->setFromRef('#/definitions/SecretsSyncRequest'); - } -} From 7fecc774f7794dc1db144e47598b14c7b81892a9 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:04:15 -0700 Subject: [PATCH 25/36] fix weird directory naming in remote git branch --- .../php/src/Schemas/SecretsSyncRequest.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 languages/php/src/Schemas/SecretsSyncRequest.php diff --git a/languages/php/src/Schemas/SecretsSyncRequest.php b/languages/php/src/Schemas/SecretsSyncRequest.php new file mode 100644 index 000000000..4d98db0f4 --- /dev/null +++ b/languages/php/src/Schemas/SecretsSyncRequest.php @@ -0,0 +1,42 @@ +organizationId = Schema::string(); + $properties->organizationId->description = "Organization to sync secrets from"; + $properties->organizationId->format = "uuid"; + $properties->lastSyncedDate = (new Schema())->setType([Schema::STRING, Schema::NULL]); + $properties->lastSyncedDate->description = "Optional date time a sync last occurred"; + $properties->lastSyncedDate->format = "date-time"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->organizationId, + ); + $ownerSchema->setFromRef('#/definitions/SecretsSyncRequest'); + } +} From e20a6b414a60d6bd5cd21f5dcad94ff6bbfe78e6 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:02:53 -0700 Subject: [PATCH 26/36] pr feedback; refactor auth --- languages/php/src/BitwardenClient.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index 62e760ddc..b80d92289 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -30,7 +30,7 @@ public function login_access_token(string $access_token, string $state_file): vo throw new \Exception("Authorization error"); } - if ($result->authenticated == False) { + if ($result->authenticated == false) { throw new \Exception("Unauthorized"); } } @@ -48,7 +48,7 @@ class BitwardenClient private CommandRunner $commandRunner; - private ?AuthClient $authClient; + public AuthClient $auth; private FFI\CData $handle; @@ -65,12 +65,7 @@ public function __construct(BitwardenSettings $bitwardenSettings) $this->commandRunner = new CommandRunner($this->bitwarden_lib, $this->handle); $this->projects = new ProjectsClient($this->commandRunner); $this->secrets = new SecretsClient($this->commandRunner); - } - - public function auth(): AuthClient - { - $this->authClient = new AuthClient($this->commandRunner); - return $this->authClient; + $this->auth = new AuthClient($this->commandRunner); } public function __destruct() From 7bc8b9c08c672af458fd29f918177a28a39e2b01 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:04:46 -0700 Subject: [PATCH 27/36] update readme --- languages/php/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/README.md b/languages/php/README.md index a758da378..e9c0b12b2 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -28,7 +28,7 @@ $identity_url = "https://identity.bitwarden.com"; $bitwarden_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($bitwarden_settings); -$bitwarden_client->login_access_token($access_token, $state_file); +$bitwarden_client->auth->login_access_token($access_token, $state_file); ``` Initialize `BitwardenSettings` by passing `$api_url` and `$identity_url` or set to null to use the defaults. From 4b1f271a01f11c4c50910a3c39d9e68a3b4df655 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:07:50 -0700 Subject: [PATCH 28/36] update example --- languages/php/example.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/example.php b/languages/php/example.php index 3590d9f9e..db6f3ad75 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -14,7 +14,7 @@ $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); try { - $bitwarden_client->auth()->login_access_token($access_token, $state_file); + $bitwarden_client->auth->login_access_token($access_token, $state_file); } catch (Exception $e) { print("Error: " . $e->getMessage() . "\n"); exit(1); From 534d94bd7a4363db469bca09b1905e852340f43c Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:08:11 -0700 Subject: [PATCH 29/36] more specific exception message --- languages/php/src/BitwardenClient.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index b80d92289..63b4bc264 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -25,13 +25,13 @@ public function login_access_token(string $access_token, string $state_file): vo $access_token_request->stateFile = $state_file; $command = new Command(); $command->loginAccessToken = $access_token_request->jsonSerialize(); - $result = $this->commandRunner->run($command); - if (!isset($result->authenticated)) { - throw new \Exception("Authorization error"); - } - - if ($result->authenticated == false) { - throw new \Exception("Unauthorized"); + try { + $result = $this->commandRunner->run($command); + if (!isset($result->authenticated) || !$result->authenticated) { + throw new Exception("Unauthorized"); + } + } catch (Exception $exception) { + throw new Exception("Authorization error: " . $exception->getMessage()); } } } From 5a8d730111d51f1c86e01a83f0ad5d57c66640a0 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:56:43 -0700 Subject: [PATCH 30/36] apply grammar suggestions --- languages/php/INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/php/INSTALL.md b/languages/php/INSTALL.md index fec62a20f..299053389 100644 --- a/languages/php/INSTALL.md +++ b/languages/php/INSTALL.md @@ -2,7 +2,7 @@ ## Introduction -Composer is used to build PHP Bitwarden client library. +Composer is used to build the PHP Bitwarden client library. ## Prerequisites @@ -16,7 +16,7 @@ Composer is used to build PHP Bitwarden client library. - Linux x86_64: `src/lib/linux-x64/libbitwarden_c.so` - macOS x86_64: `src/lib/macos-x64/libbitwarden_c.dylib` - macOS aarch64: `src/lib/macos-arm64/libbitwarden_c.dylib` - - If you prefer to build SDK yourself, see [SDK README.md](../../README.md) for instructions. + - If you prefer to build the SDK yourself, see the [SDK README.md](../../README.md) for instructions. ## Build Commands From 1ffd2d91fbabee72b83b6b1e5b66d40ffa0a3048 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:58:46 -0700 Subject: [PATCH 31/36] apply formatting suggestions --- languages/php/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/languages/php/README.md b/languages/php/README.md index e9c0b12b2..c830d1627 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -1,7 +1,6 @@ # Bitwarden Secrets Manager SDK wrapper for PHP -PHP bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some -functionality. +PHP bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some functionality. ## Installation @@ -19,8 +18,7 @@ Review the help documentation on [Access Tokens]. ```php require_once 'vendor/autoload.php'; -$access_token = ''; -$state_file = ""; +$access_token = ""; $organization_id = ""; $api_url = "https://api.bitwarden.com"; $identity_url = "https://identity.bitwarden.com"; From 64e984c2cbaffdef39ea17af688f378d1876bfec Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 13 Sep 2024 06:14:14 -0700 Subject: [PATCH 32/36] Update languages/php/README.md --- languages/php/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/languages/php/README.md b/languages/php/README.md index c830d1627..61991bd0e 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -19,6 +19,7 @@ Review the help documentation on [Access Tokens]. require_once 'vendor/autoload.php'; $access_token = ""; +$state_file = ""; $organization_id = ""; $api_url = "https://api.bitwarden.com"; $identity_url = "https://identity.bitwarden.com"; From 49b5023eca174864a228d4e21d6740e3dc026536 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:35:49 +0200 Subject: [PATCH 33/36] [SM-1402] Automatic PHP schema generation (#1036) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 🎟️ Tracking https://bitwarden.atlassian.net/browse/SM-1402 (Not part of this ticket, but agreed with @tangowithfoxtrot that it would make sense to do so) ## 📔 Objective Automatic PHP Schema generation using quicktype. The schema is not compatible with previously generated Swaggest based schema - PHP code changes are required (does not affect the usage, `README.md` and `example.php` works as before) Notable code changes: - Schema class fields are private, no setters or getters. Can only init the classes via constructor. (Could enable getters in schema generation, but the quicktype does not respond well with nested arrays that are part of schema, as a result PHP generated schema file does not compile) - Schema class constructors are initialized with named arguments, which is more readable than `new Command(null, null, null, null, null, $secrets_command, null, null) - Uses PHP native json serialization, but SDK does not react well to null fields, so adjusted the code to remove it just before JSON serialization. - Separated `AuthClient` into separate file - Imports with `uses` ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes --- languages/php/.gitignore | 2 + languages/php/composer.json | 4 +- languages/php/composer.lock | 230 +----------------- languages/php/example.php | 168 ++++++------- languages/php/src/AuthClient.php | 35 +++ languages/php/src/BitwardenClient.php | 60 ++--- languages/php/src/BitwardenLib.php | 75 ++++-- languages/php/src/CommandRunner.php | 22 +- languages/php/src/ProjectsClient.php | 75 +++--- .../src/Schemas/AccessTokenLoginRequest.php | 41 ---- languages/php/src/Schemas/ClientSettings.php | 130 ---------- languages/php/src/Schemas/Command.php | 40 --- .../php/src/Schemas/ProjectCreateRequest.php | 45 ---- .../php/src/Schemas/ProjectGetRequest.php | 38 --- .../php/src/Schemas/ProjectPutRequest.php | 52 ---- languages/php/src/Schemas/ProjectsCommand.php | 37 --- .../php/src/Schemas/ProjectsDeleteRequest.php | 39 --- .../php/src/Schemas/ProjectsListRequest.php | 38 --- .../php/src/Schemas/SecretCreateRequest.php | 63 ----- .../php/src/Schemas/SecretGetRequest.php | 38 --- .../src/Schemas/SecretIdentifiersRequest.php | 38 --- .../php/src/Schemas/SecretPutRequest.php | 69 ------ .../src/Schemas/SecretVerificationRequest.php | 35 --- languages/php/src/Schemas/SecretsCommand.php | 40 --- .../php/src/Schemas/SecretsDeleteRequest.php | 39 --- .../php/src/Schemas/SecretsGetRequest.php | 39 --- .../php/src/Schemas/SecretsSyncRequest.php | 42 ---- languages/php/src/SecretsClient.php | 109 +++++---- support/scripts/schemas.ts | 21 ++ 29 files changed, 329 insertions(+), 1335 deletions(-) create mode 100644 languages/php/src/AuthClient.php delete mode 100644 languages/php/src/Schemas/AccessTokenLoginRequest.php delete mode 100644 languages/php/src/Schemas/ClientSettings.php delete mode 100644 languages/php/src/Schemas/Command.php delete mode 100644 languages/php/src/Schemas/ProjectCreateRequest.php delete mode 100644 languages/php/src/Schemas/ProjectGetRequest.php delete mode 100644 languages/php/src/Schemas/ProjectPutRequest.php delete mode 100644 languages/php/src/Schemas/ProjectsCommand.php delete mode 100644 languages/php/src/Schemas/ProjectsDeleteRequest.php delete mode 100644 languages/php/src/Schemas/ProjectsListRequest.php delete mode 100644 languages/php/src/Schemas/SecretCreateRequest.php delete mode 100644 languages/php/src/Schemas/SecretGetRequest.php delete mode 100644 languages/php/src/Schemas/SecretIdentifiersRequest.php delete mode 100644 languages/php/src/Schemas/SecretPutRequest.php delete mode 100644 languages/php/src/Schemas/SecretVerificationRequest.php delete mode 100644 languages/php/src/Schemas/SecretsCommand.php delete mode 100644 languages/php/src/Schemas/SecretsDeleteRequest.php delete mode 100644 languages/php/src/Schemas/SecretsGetRequest.php delete mode 100644 languages/php/src/Schemas/SecretsSyncRequest.php diff --git a/languages/php/.gitignore b/languages/php/.gitignore index b2a69e9a0..5d6ed424e 100644 --- a/languages/php/.gitignore +++ b/languages/php/.gitignore @@ -1,2 +1,4 @@ .DS_Store vendor +src/lib/ +src/Schemas/ diff --git a/languages/php/composer.json b/languages/php/composer.json index 85447e72a..fce61f890 100644 --- a/languages/php/composer.json +++ b/languages/php/composer.json @@ -7,13 +7,13 @@ "version": "0.1.0", "require": { "php": "^8.0", - "swaggest/json-schema": "^0.12.42", "ext-ffi": "*" }, "autoload": { "psr-4": { "Bitwarden\\Sdk\\": "src/" - } + }, + "files": ["src/Schemas/Schemas.php"] }, "authors": [ { diff --git a/languages/php/composer.lock b/languages/php/composer.lock index 8856663d8..187511304 100644 --- a/languages/php/composer.lock +++ b/languages/php/composer.lock @@ -4,234 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c4bbd1e56c4c6ddbdb68e0015ccad231", - "packages": [ - { - "name": "phplang/scope-exit", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/phplang/scope-exit.git", - "reference": "239b73abe89f9414aa85a7ca075ec9445629192b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phplang/scope-exit/zipball/239b73abe89f9414aa85a7ca075ec9445629192b", - "reference": "239b73abe89f9414aa85a7ca075ec9445629192b", - "shasum": "" - }, - "require-dev": { - "phpunit/phpunit": "*" - }, - "type": "library", - "autoload": { - "psr-4": { - "PhpLang\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD" - ], - "authors": [ - { - "name": "Sara Golemon", - "email": "pollita@php.net", - "homepage": "https://twitter.com/SaraMG", - "role": "Developer" - } - ], - "description": "Emulation of SCOPE_EXIT construct from C++", - "homepage": "https://github.com/phplang/scope-exit", - "keywords": [ - "cleanup", - "exit", - "scope" - ], - "support": { - "issues": "https://github.com/phplang/scope-exit/issues", - "source": "https://github.com/phplang/scope-exit/tree/master" - }, - "time": "2016-09-17T00:15:18+00:00" - }, - { - "name": "swaggest/json-diff", - "version": "v3.10.4", - "source": { - "type": "git", - "url": "https://github.com/swaggest/json-diff.git", - "reference": "f4e511708060ff7511a3743fab4aa484a062bcfb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/swaggest/json-diff/zipball/f4e511708060ff7511a3743fab4aa484a062bcfb", - "reference": "f4e511708060ff7511a3743fab4aa484a062bcfb", - "shasum": "" - }, - "require": { - "ext-json": "*" - }, - "require-dev": { - "phperf/phpunit": "4.8.37" - }, - "type": "library", - "autoload": { - "psr-4": { - "Swaggest\\JsonDiff\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Viacheslav Poturaev", - "email": "vearutop@gmail.com" - } - ], - "description": "JSON diff/rearrange/patch/pointer library for PHP", - "support": { - "issues": "https://github.com/swaggest/json-diff/issues", - "source": "https://github.com/swaggest/json-diff/tree/v3.10.4" - }, - "time": "2022-11-09T13:21:05+00:00" - }, - { - "name": "swaggest/json-schema", - "version": "v0.12.42", - "source": { - "type": "git", - "url": "https://github.com/swaggest/php-json-schema.git", - "reference": "d23adb53808b8e2da36f75bc0188546e4cbe3b45" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/swaggest/php-json-schema/zipball/d23adb53808b8e2da36f75bc0188546e4cbe3b45", - "reference": "d23adb53808b8e2da36f75bc0188546e4cbe3b45", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=5.4", - "phplang/scope-exit": "^1.0", - "swaggest/json-diff": "^3.8.2", - "symfony/polyfill-mbstring": "^1.19" - }, - "require-dev": { - "phperf/phpunit": "4.8.37" - }, - "suggest": { - "ext-mbstring": "For better performance" - }, - "type": "library", - "autoload": { - "psr-4": { - "Swaggest\\JsonSchema\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Viacheslav Poturaev", - "email": "vearutop@gmail.com" - } - ], - "description": "High definition PHP structures with JSON-schema based validation", - "support": { - "email": "vearutop@gmail.com", - "issues": "https://github.com/swaggest/php-json-schema/issues", - "source": "https://github.com/swaggest/php-json-schema/tree/v0.12.42" - }, - "time": "2023-09-12T14:43:42+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - } - ], + "content-hash": "1769eb8cdcb42d17f993aa0ef123895b", + "packages": [], "packages-dev": [], "aliases": [], "minimum-stability": "stable", diff --git a/languages/php/example.php b/languages/php/example.php index db6f3ad75..acc7ca5ed 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -10,92 +10,94 @@ $api_url = getenv('API_URL'); $identity_url = getenv('IDENTITY_URL'); -$client_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); - -$bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); try { + $client_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); + + $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); + $bitwarden_client->auth->login_access_token($access_token, $state_file); + + // create project + print("Projects:\n"); + $res = $bitwarden_client->projects->create($organization_id, 'php project'); + $project_id = $res->id; + print("\tcreate: '" . $project_id . "'\n\n"); + + // get project + $res = $bitwarden_client->projects->get($project_id); + print("\tget: '" . $res->name . "'\n\n"); + + // list projects + $res = $bitwarden_client->projects->list($organization_id); + print("\tlist:\n"); + foreach ($res->data as $project) { + print("\t\tID: '" . $project->id . "', Name: '" . $project->name . "'\n"); + } + print("\n"); + + // update project + $res = $bitwarden_client->projects->update($organization_id, $project_id, 'php test awesome'); + print("\tupdate: '" . $res->name . "'\n\n"); + + // sync secrets + print("Secrets:\n"); + print("\tSyncing secrets...\n"); + $res = $bitwarden_client->secrets->sync($organization_id, null); + $now = new DateTime(); + $now_string = $now->format('Y-m-d\TH:i:s.u\Z'); + print("\t\tSync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n\n"); + + print("\tSyncing again to ensure no changes since last sync...\n"); + $res = $bitwarden_client->secrets->sync($organization_id, $now_string); + print("\t\tSync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n\n"); + + // create secret + $res = $bitwarden_client->secrets->create($organization_id, "New Key", "New value", "New note", [$project_id]); + $secret_id = $res->id; + print("\tcreate: '" . $secret_id . "'\n\n"); + + // get secret + $res = $bitwarden_client->secrets->get($secret_id); + print("\tget: '" . $res->key . "'\n\n"); + + // get multiple secrets by ids + $res = $bitwarden_client->secrets->get_by_ids([$secret_id]); + print("\tget_by_ids:\n"); + foreach ($res->data as $secret) { + print("\t\tID: '" . $secret->id . "', Key: '" . $secret->key . "'\n"); + } + print("\n"); + + // list secrets + $res = $bitwarden_client->secrets->list($organization_id); + print("\tlist:\n"); + foreach ($res->data as $secret) { + print("\t\tID: '" . $secret->id . "', Key: '" . $secret->key . "'\n"); + } + print("\n"); + + // update secret + $res = $bitwarden_client->secrets->update($organization_id, $secret_id, "Updated key", "Updated value", "Updated note", [$project_id]); + print("\tupdate: '" . $res->key . "'\n\n"); + + // delete secret + print("Cleaning up secrets and projects:\n"); + $res = $bitwarden_client->secrets->delete([$secret_id]); + print("\tdelete:\n"); + foreach ($res->data as $secret) { + print("\t\tdeleted secret: '" . $secret->id . "'\n"); + } + print("\n"); + + // delete project + $res = $bitwarden_client->projects->delete([$project_id]); + print("\tdelete:\n"); + foreach ($res->data as $project) { + print("\t\tdeleted project: '" . $project->id . "'\n"); + } + print("\n"); + } catch (Exception $e) { print("Error: " . $e->getMessage() . "\n"); exit(1); } - -// create project -print("Projects:\n"); -$res = $bitwarden_client->projects->create($organization_id, 'php project'); -$project_id = $res->id; -print("\tcreate: '" . $project_id . "'\n\n"); - -// get project -$res = $bitwarden_client->projects->get($project_id); -print("\tget: '" . $res->name . "'\n\n"); - -// list projects -$res = $bitwarden_client->projects->list($organization_id); -print("\tlist:\n"); -foreach ($res->data as $project) { - print("\t\tID: '" . $project->id . "', Name: '" . $project->name . "'\n"); -} -print("\n"); - -// update project -$res = $bitwarden_client->projects->update($organization_id, $project_id, 'php test awesome'); -print("\tupdate: '" . $res->name . "'\n\n"); - -// sync secrets -print("Secrets:\n"); -print("\tSyncing secrets...\n"); -$res = $bitwarden_client->secrets->sync($organization_id,null); -$now = new DateTime(); -$now_string = $now->format('Y-m-d\TH:i:s.u\Z'); -print("\t\tSync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n\n"); - -print("\tSyncing again to ensure no changes since last sync...\n"); -$res = $bitwarden_client->secrets->sync($organization_id, $now_string); -print("\t\tSync has changes: " . ($res->hasChanges ? 'true' : 'false') . "\n\n"); - -// create secret -$res = $bitwarden_client->secrets->create($organization_id, "New Key", "New value", "New note", [$project_id]); -$secret_id = $res->id; -print("\tcreate: '" . $secret_id . "'\n\n"); - -// get secret -$res = $bitwarden_client->secrets->get($secret_id); -print("\tget: '" . $res->key . "'\n\n"); - -// get multiple secrets by ids -$res = $bitwarden_client->secrets->get_by_ids([$secret_id]); -print("\tget_by_ids:\n"); -foreach ($res->data as $secret) { - print("\t\tID: '" . $secret->id . "', Key: '" . $secret->key . "'\n"); -} -print("\n"); - -// list secrets -$res = $bitwarden_client->secrets->list($organization_id); -print("\tlist:\n"); -foreach ($res->data as $secret) { - print("\t\tID: '" . $secret->id . "', Key: '" . $secret->key . "'\n"); -} -print("\n"); - -// update secret -$res = $bitwarden_client->secrets->update($organization_id, $secret_id, "Updated key", "Updated value", "Updated note", [$project_id]); -print("\tupdate: '" . $res->key . "'\n\n"); - -// delete secret -print("Cleaning up secrets and projects:\n"); -$res = $bitwarden_client->secrets->delete([$secret_id]); -print("\tdelete:\n"); -foreach ($res->data as $secret) { - print("\t\tdeleted secret: '" . $secret->id . "'\n"); -} -print("\n"); - -// delete project -$res = $bitwarden_client->projects->delete([$project_id]); -print("\tdelete:\n"); -foreach ($res->data as $project) { - print("\t\tdeleted project: '" . $project->id . "'\n"); -} -print("\n"); diff --git a/languages/php/src/AuthClient.php b/languages/php/src/AuthClient.php new file mode 100644 index 000000000..449c76905 --- /dev/null +++ b/languages/php/src/AuthClient.php @@ -0,0 +1,35 @@ +commandRunner = $commandRunner; + } + + /** + * @throws Exception + */ + public function login_access_token(string $access_token, ?string $state_file): void + { + $access_token_request = new AccessTokenLoginRequest($access_token, $state_file); + $command = new Command(passwordLogin: null, apiKeyLogin: null, loginAccessToken: $access_token_request, + getUserApiKey: null, fingerprint: null, sync: null, secrets: null, projects: null, generators: null); + try { + $result = $this->commandRunner->run($command); + if (!isset($result->authenticated) || !$result->authenticated) { + throw new Exception("Unauthorized"); + } + } catch (Exception $exception) { + throw new Exception("Authorization error: " . $exception->getMessage()); + } + } +} diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php index 63b4bc264..c125b6aa7 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -2,67 +2,37 @@ namespace Bitwarden\Sdk; -use Bitwarden\Sdk\Schemas\AccessTokenLoginRequest; use Bitwarden\Sdk\Schemas\ClientSettings; -use Bitwarden\Sdk\Schemas\Command; -use Bitwarden\Sdk\Schemas; -use FFI; - -class AuthClient { - private CommandRunner $commandRunner; - - public function __construct(CommandRunner $commandRunner) { - $this->commandRunner = $commandRunner; - } - - /** - * @throws \Exception - */ - public function login_access_token(string $access_token, string $state_file): void - { - $access_token_request = new AccessTokenLoginRequest(); - $access_token_request->accessToken = $access_token; - $access_token_request->stateFile = $state_file; - $command = new Command(); - $command->loginAccessToken = $access_token_request->jsonSerialize(); - try { - $result = $this->commandRunner->run($command); - if (!isset($result->authenticated) || !$result->authenticated) { - throw new Exception("Unauthorized"); - } - } catch (Exception $exception) { - throw new Exception("Authorization error: " . $exception->getMessage()); - } - } -} +use Bitwarden\Sdk\Schemas\DeviceType; +use JsonException; class BitwardenClient { - private BitwardenLib $bitwarden_lib; - - private ClientSettings $clientSettings; - public ProjectsClient $projects; public SecretsClient $secrets; - private CommandRunner $commandRunner; - public AuthClient $auth; - private FFI\CData $handle; + private BitwardenLib $bitwarden_lib; + private ClientSettings $clientSettings; + + private CommandRunner $commandRunner; + + /** + * @throws JsonException + */ public function __construct(BitwardenSettings $bitwardenSettings) { - $this->clientSettings = new ClientSettings(); - $this->clientSettings->apiUrl = $bitwardenSettings->get_api_url(); - $this->clientSettings->identityUrl = $bitwardenSettings->get_identity_url(); - $this->clientSettings->userAgent = "Bitwarden PHP-SDK"; + $this->clientSettings = new ClientSettings(apiUrl: $bitwardenSettings->get_api_url(), + deviceType: DeviceType::$SDK, identityUrl: $bitwardenSettings->get_identity_url(), + userAgent: "Bitwarden PHP-SDK"); $this->bitwarden_lib = new BitwardenLib(); - $this->handle = $this->bitwarden_lib->init($this->clientSettings); + $this->bitwarden_lib->init($this->clientSettings); - $this->commandRunner = new CommandRunner($this->bitwarden_lib, $this->handle); + $this->commandRunner = new CommandRunner($this->bitwarden_lib); $this->projects = new ProjectsClient($this->commandRunner); $this->secrets = new SecretsClient($this->commandRunner); $this->auth = new AuthClient($this->commandRunner); diff --git a/languages/php/src/BitwardenLib.php b/languages/php/src/BitwardenLib.php index 399aba6e8..53be3299b 100644 --- a/languages/php/src/BitwardenLib.php +++ b/languages/php/src/BitwardenLib.php @@ -4,10 +4,11 @@ use Bitwarden\Sdk\Schemas\ClientSettings; use Bitwarden\Sdk\Schemas\Command; +use Exception; use FFI; -use Swaggest\JsonDiff\Exception; -use Swaggest\JsonSchema\JsonSchema; - +use JsonException; +use RuntimeException; +use stdClass; class BitwardenLib { @@ -15,36 +16,36 @@ class BitwardenLib public FFI\CData $handle; /** - * @throws \Exception + * @throws Exception */ public function __construct() { $lib_file = null; if (PHP_OS === 'WINNT') { - $lib_file = __DIR__.'/lib/windows-x64/bitwarden_c.dll'; - if (file_exists($lib_file) == false) { - $lib_file = __DIR__.'/../../../target/debug/bitwarden_c.dll'; + $lib_file = __DIR__ . '/lib/windows-x64/bitwarden_c.dll'; + if (!file_exists($lib_file)) { + $lib_file = __DIR__ . '/../../../target/debug/bitwarden_c.dll'; } } elseif (PHP_OS === 'Linux') { - $lib_file = __DIR__.'/lib/linux-x64/libbitwarden_c.so'; - if (file_exists($lib_file) == false) { - $lib_file = __DIR__.'/../../../target/debug/libbitwarden_c.so'; + $lib_file = __DIR__ . '/lib/linux-x64/libbitwarden_c.so'; + if (!file_exists($lib_file)) { + $lib_file = __DIR__ . '/../../../target/debug/libbitwarden_c.so'; } } elseif (PHP_OS === 'Darwin') { $architecture = trim(exec('uname -m')); if ($architecture === 'x86_64' || $architecture === 'amd64') { - $lib_file = __DIR__.'/lib/macos-x64/libbitwarden_c.dylib'; + $lib_file = __DIR__ . '/lib/macos-x64/libbitwarden_c.dylib'; } elseif ($architecture === 'arm64') { - $lib_file = __DIR__.'/lib/macos-arm64/libbitwarden_c.dylib'; + $lib_file = __DIR__ . '/lib/macos-arm64/libbitwarden_c.dylib'; } - if (file_exists($lib_file) == false) { - $lib_file = __DIR__.'/../../../target/debug/libbitwarden_c.dylib'; + if (!file_exists($lib_file)) { + $lib_file = __DIR__ . '/../../../target/debug/libbitwarden_c.dylib'; } } - if ($lib_file == null || is_file($lib_file) == false) { - throw new \Exception("Lib file not found"); + if ($lib_file == null || !is_file($lib_file)) { + throw new Exception("Lib file not found"); } $this->ffi = FFI::cdef(' @@ -55,20 +56,29 @@ public function __construct() ); } + /** + * @throws JsonException + * @throws Exception + */ public function init(ClientSettings $client_settings): FFI\CData { - $this->handle = $this->ffi->init(json_encode($client_settings->jsonSerialize())); + $encoded_json = $this::json_encode_sdk_format($client_settings->to()); + $this->handle = $this->ffi->init($encoded_json); return $this->handle; } - public function run_command(Command $command): \stdClass + /** + * @throws JsonException + * @throws Exception + */ + public function run_command(Command $command): stdClass { - $encoded_json = json_encode($command->jsonSerialize()); + $encoded_json = $this::json_encode_sdk_format($command->to()); try { $result = $this->ffi->run_command($encoded_json, $this->handle); return json_decode(FFI::string($result)); - } catch (\FFI\Exception $e) { - throw new \RuntimeException('Error occurred during FFI operation: ' . $e->getMessage()); + } catch (FFI\Exception $e) { + throw new RuntimeException('Error occurred during FFI operation: ' . $e->getMessage()); } } @@ -76,4 +86,27 @@ public function free_mem(): void { $this->ffi->free_mem($this->handle); } + + /** + * @throws JsonException + */ + private static function json_encode_sdk_format($object): string + { + $withoutNull = function ($a) use (&$withoutNull) { + if (is_object($a)) { + $a = array_filter((array)$a); + foreach ($a as $k => $v) { + $a[$k] = $withoutNull($v); + } + + return (object)$a; + } + + return $a; + }; + + $object_no_nulls = $withoutNull($object); + + return json_encode($object_no_nulls, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES); + } } diff --git a/languages/php/src/CommandRunner.php b/languages/php/src/CommandRunner.php index 9eec68b2d..532b9625e 100644 --- a/languages/php/src/CommandRunner.php +++ b/languages/php/src/CommandRunner.php @@ -2,36 +2,32 @@ namespace Bitwarden\Sdk; - use Bitwarden\Sdk\Schemas\Command; -use FFI; +use Exception; +use stdClass; class CommandRunner { - private FFI\CData $handle; - private BitwardenLib $bitwardenLib; - public function __construct(BitwardenLib $bitwardenLib, $handle) + public function __construct(BitwardenLib $bitwardenLib) { $this->bitwardenLib = $bitwardenLib; - $this->handle = $handle; } /** - * @throws \Exception + * @throws Exception */ - public function run(Command $command): \stdClass + public function run(Command $command): stdClass { $result = $this->bitwardenLib->run_command($command); - if ($result->success == true) { + if ($result->success) { return $result->data; } - if (isset($result->errorMessage)) - { - throw new \Exception($result->errorMessage); + if (isset($result->errorMessage)) { + throw new Exception($result->errorMessage); } - throw new \Exception("Unknown error occurred"); + throw new Exception("Unknown error occurred"); } } diff --git a/languages/php/src/ProjectsClient.php b/languages/php/src/ProjectsClient.php index 582a70743..cca44f1e6 100644 --- a/languages/php/src/ProjectsClient.php +++ b/languages/php/src/ProjectsClient.php @@ -9,6 +9,8 @@ use Bitwarden\Sdk\Schemas\ProjectsCommand; use Bitwarden\Sdk\Schemas\ProjectsDeleteRequest; use Bitwarden\Sdk\Schemas\ProjectsListRequest; +use Exception; +use stdClass; class ProjectsClient { @@ -19,63 +21,74 @@ public function __construct(CommandRunner $commandRunner) $this->commandRunner = $commandRunner; } - public function get(string $project_id): \stdClass + /** + * @throws Exception + */ + public function get(string $project_id): stdClass { - $project_get_request = new ProjectGetRequest(); - $project_get_request->id = $project_id; + $project_get_request = new ProjectGetRequest($project_id); $project_get_request->validate(); - $project_command = new ProjectsCommand(); - $project_command->get = $project_get_request->jsonSerialize(); + $project_command = new ProjectsCommand(get: $project_get_request, create: null, list: null, update: null, + delete: null); return $this->run_project_command($project_command); } - public function list(string $organization_id): \stdClass + /** + * @throws Exception + */ + public function list(string $organization_id): stdClass { - $project_list_request = new ProjectsListRequest(); - $project_list_request->organizationId = $organization_id; + $project_list_request = new ProjectsListRequest($organization_id); $project_list_request->validate(); - $project_command = new ProjectsCommand(); - $project_command->list = $project_list_request->jsonSerialize(); + $project_command = new ProjectsCommand(get: null, create: null, list: $project_list_request, update: null, + delete: null); return $this->run_project_command($project_command); } - public function create(string $organization_id, string $project_name): \stdClass + /** + * @throws Exception + */ + public function create(string $organization_id, string $project_name): stdClass { - $project_create_request = new ProjectCreateRequest(); - $project_create_request->name = $project_name; - $project_create_request->organizationId = $organization_id; + $project_create_request = new ProjectCreateRequest(name: $project_name, organizationId: $organization_id); $project_create_request->validate(); - $project_command = new ProjectsCommand(); - $project_command->create = $project_create_request->jsonSerialize(); + $project_command = new ProjectsCommand(get: null, create: $project_create_request, list: null, update: null, + delete: null); return $this->run_project_command($project_command); } - public function update(string $organization_id, string $project_id, string $project_name): \stdClass + /** + * @throws Exception + */ + public function update(string $organization_id, string $project_id, string $project_name): stdClass { - $project_put_request = new ProjectPutRequest(); - $project_put_request->organizationId = $organization_id; - $project_put_request->name = $project_name; - $project_put_request->id = $project_id; + $project_put_request = new ProjectPutRequest(id: $project_id, name: $project_name, + organizationId: $organization_id); $project_put_request->validate(); - $project_command = new ProjectsCommand(); - $project_command->update = $project_put_request->jsonSerialize(); + $project_command = new ProjectsCommand(get: null, create: null, list: null, update: $project_put_request, + delete: null); return $this->run_project_command($project_command); } - public function delete(array $ids): \stdClass + /** + * @throws Exception + */ + public function delete(array $ids): stdClass { - $projects_delete_request = new ProjectsDeleteRequest(); - $projects_delete_request->ids = $ids; + $projects_delete_request = new ProjectsDeleteRequest($ids); $projects_delete_request->validate(); - $project_command = new ProjectsCommand(); - $project_command->delete = $projects_delete_request->jsonSerialize(); + $project_command = new ProjectsCommand(get: null, create: null, list: null, update: null, + delete: $projects_delete_request); return $this->run_project_command($project_command); } - public function run_project_command($projectCommand): \stdClass + /** + * @throws Exception + */ + public function run_project_command($projectCommand): stdClass { - $command = new Command(); - $command->projects = $projectCommand; + $command = new Command(passwordLogin: null, apiKeyLogin: null, loginAccessToken: null, getUserApiKey: null, + fingerprint: null, sync: null, secrets: null, projects: $projectCommand, generators: null); return $this->commandRunner->run($command); } } diff --git a/languages/php/src/Schemas/AccessTokenLoginRequest.php b/languages/php/src/Schemas/AccessTokenLoginRequest.php deleted file mode 100644 index 8c22066b3..000000000 --- a/languages/php/src/Schemas/AccessTokenLoginRequest.php +++ /dev/null @@ -1,41 +0,0 @@ -accessToken = Schema::string(); - $properties->accessToken->description = "Bitwarden service API access token"; - $properties->stateFile = (new Schema())->setType([Schema::STRING, Schema::NULL]); - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->description = "Login to Bitwarden with access token"; - $ownerSchema->required = array( - self::names()->accessToken, - ); - $ownerSchema->setFromRef('#/definitions/AccessTokenLoginRequest'); - } -} diff --git a/languages/php/src/Schemas/ClientSettings.php b/languages/php/src/Schemas/ClientSettings.php deleted file mode 100644 index a64c143b8..000000000 --- a/languages/php/src/Schemas/ClientSettings.php +++ /dev/null @@ -1,130 +0,0 @@ -identityUrl = Schema::string(); - $properties->identityUrl->description = "The identity url of the targeted Bitwarden instance. Defaults to `https://identity.bitwarden.com`"; - $properties->identityUrl->default = "https://identity.bitwarden.com"; - $properties->apiUrl = Schema::string(); - $properties->apiUrl->description = "The api url of the targeted Bitwarden instance. Defaults to `https://api.bitwarden.com`"; - $properties->apiUrl->default = "https://api.bitwarden.com"; - $properties->userAgent = Schema::string(); - $properties->userAgent->description = "The user_agent to sent to Bitwarden. Defaults to `Bitwarden Rust-SDK`"; - $properties->userAgent->default = "Bitwarden Rust-SDK"; - $properties->deviceType = new Schema(); - $propertiesDeviceTypeAllOf0 = Schema::string(); - $propertiesDeviceTypeAllOf0->enum = array( - self::ANDROID, - self::I_OS, - self::CHROME_EXTENSION, - self::FIREFOX_EXTENSION, - self::OPERA_EXTENSION, - self::EDGE_EXTENSION, - self::WINDOWS_DESKTOP, - self::MAC_OS_DESKTOP, - self::LINUX_DESKTOP, - self::CHROME_BROWSER, - self::FIREFOX_BROWSER, - self::OPERA_BROWSER, - self::EDGE_BROWSER, - self::IE_BROWSER, - self::UNKNOWN_BROWSER, - self::ANDROID_AMAZON, - self::UWP, - self::SAFARI_BROWSER, - self::VIVALDI_BROWSER, - self::VIVALDI_EXTENSION, - self::SAFARI_EXTENSION, - self::SDK, - ); - $propertiesDeviceTypeAllOf0->setFromRef('#/definitions/DeviceType'); - $properties->deviceType->allOf[0] = $propertiesDeviceTypeAllOf0; - $properties->deviceType->description = "Device type to send to Bitwarden. Defaults to SDK"; - $properties->deviceType->default = "SDK"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->description = "Basic client behavior settings. These settings specify the various targets and behavior of the Bitwarden Client. They are optional and uneditable once the client is initialized.\n\nDefaults to\n\n``` # use bitwarden_core::{ClientSettings, DeviceType}; let settings = ClientSettings { identity_url: \"https://identity.bitwarden.com\".to_string(), api_url: \"https://api.bitwarden.com\".to_string(), user_agent: \"Bitwarden Rust-SDK\".to_string(), device_type: DeviceType::SDK, }; let default = ClientSettings::default(); ```"; - $ownerSchema->setFromRef('#/definitions/ClientSettings'); - } -} \ No newline at end of file diff --git a/languages/php/src/Schemas/Command.php b/languages/php/src/Schemas/Command.php deleted file mode 100644 index f9d0403a9..000000000 --- a/languages/php/src/Schemas/Command.php +++ /dev/null @@ -1,40 +0,0 @@ -loginAccessToken = AccessTokenLoginRequest::schema(); - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->description = "Login with Secrets Manager Access Token\n\nThis command is for initiating an authentication handshake with Bitwarden.\n\nReturns: [ApiKeyLoginResponse](bitwarden::auth::login::ApiKeyLoginResponse)"; - $ownerSchema->required = array( - self::names()->loginAccessToken, - ); - } -} diff --git a/languages/php/src/Schemas/ProjectCreateRequest.php b/languages/php/src/Schemas/ProjectCreateRequest.php deleted file mode 100644 index b63ba42b6..000000000 --- a/languages/php/src/Schemas/ProjectCreateRequest.php +++ /dev/null @@ -1,45 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization where the project will be created"; - $properties->organizationId->format = "uuid"; - $properties->name = Schema::string(); - $properties->name->maxLength = 500; - $properties->name->minLength = 1; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->name, - self::names()->organizationId, - ); - $ownerSchema->setFromRef('#/definitions/ProjectCreateRequest'); - } -} diff --git a/languages/php/src/Schemas/ProjectGetRequest.php b/languages/php/src/Schemas/ProjectGetRequest.php deleted file mode 100644 index f316273bc..000000000 --- a/languages/php/src/Schemas/ProjectGetRequest.php +++ /dev/null @@ -1,38 +0,0 @@ -id = Schema::string(); - $properties->id->description = "ID of the project to retrieve"; - $properties->id->format = "uuid"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->id, - ); - $ownerSchema->setFromRef('#/definitions/ProjectGetRequest'); - } -} diff --git a/languages/php/src/Schemas/ProjectPutRequest.php b/languages/php/src/Schemas/ProjectPutRequest.php deleted file mode 100644 index 327e6cbb7..000000000 --- a/languages/php/src/Schemas/ProjectPutRequest.php +++ /dev/null @@ -1,52 +0,0 @@ -id = Schema::string(); - $properties->id->description = "ID of the project to modify"; - $properties->id->format = "uuid"; - $properties->organizationId = Schema::string(); - $properties->organizationId->description = "Organization ID of the project to modify"; - $properties->organizationId->format = "uuid"; - $properties->name = Schema::string(); - $properties->name->maxLength = 500; - $properties->name->minLength = 1; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->id, - self::names()->name, - self::names()->organizationId, - ); - $ownerSchema->setFromRef('#/definitions/ProjectPutRequest'); - } -} diff --git a/languages/php/src/Schemas/ProjectsCommand.php b/languages/php/src/Schemas/ProjectsCommand.php deleted file mode 100644 index 6b605ca3a..000000000 --- a/languages/php/src/Schemas/ProjectsCommand.php +++ /dev/null @@ -1,37 +0,0 @@ -projects = new Schema(); - $properties->projects->get = ProjectGetRequest::schema(); - $properties->projects->list = ProjectsListRequest::schema(); - $properties->projects->update = ProjectPutRequest::schema(); - $properties->projects->create = ProjectCreateRequest::schema(); - $properties->projects->setFromRef('#/definitions/ProjectsCommand'); - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->projects, - ); - } -} diff --git a/languages/php/src/Schemas/ProjectsDeleteRequest.php b/languages/php/src/Schemas/ProjectsDeleteRequest.php deleted file mode 100644 index 445cbbb0b..000000000 --- a/languages/php/src/Schemas/ProjectsDeleteRequest.php +++ /dev/null @@ -1,39 +0,0 @@ -ids = Schema::arr(); - $properties->ids->items = Schema::string(); - $properties->ids->items->format = "uuid"; - $properties->ids->description = "IDs of the projects to delete"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->ids, - ); - $ownerSchema->setFromRef('#/definitions/ProjectsDeleteRequest'); - } -} \ No newline at end of file diff --git a/languages/php/src/Schemas/ProjectsListRequest.php b/languages/php/src/Schemas/ProjectsListRequest.php deleted file mode 100644 index 2adf55ecb..000000000 --- a/languages/php/src/Schemas/ProjectsListRequest.php +++ /dev/null @@ -1,38 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization to retrieve all the projects from"; - $properties->organizationId->format = "uuid"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->organizationId, - ); - $ownerSchema->setFromRef('#/definitions/ProjectsListRequest'); - } -} \ No newline at end of file diff --git a/languages/php/src/Schemas/SecretCreateRequest.php b/languages/php/src/Schemas/SecretCreateRequest.php deleted file mode 100644 index a878cbd14..000000000 --- a/languages/php/src/Schemas/SecretCreateRequest.php +++ /dev/null @@ -1,63 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization where the secret will be created"; - $properties->organizationId->format = "uuid"; - $properties->key = Schema::string(); - $properties->key->maxLength = 500; - $properties->key->minLength = 1; - $properties->value = Schema::string(); - $properties->value->maxLength = 25000; - $properties->value->minLength = 1; - $properties->note = Schema::string(); - $properties->note->maxLength = 7000; - $properties->projectIds = (new Schema())->setType([Schema::_ARRAY, Schema::NULL]); - $properties->projectIds->items = Schema::string(); - $properties->projectIds->items->format = "uuid"; - $properties->projectIds->description = "IDs of the projects that this secret will belong to"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->key, - self::names()->note, - self::names()->organizationId, - self::names()->value, - ); - $ownerSchema->setFromRef('#/definitions/SecretCreateRequest'); - } -} \ No newline at end of file diff --git a/languages/php/src/Schemas/SecretGetRequest.php b/languages/php/src/Schemas/SecretGetRequest.php deleted file mode 100644 index 4a4721de4..000000000 --- a/languages/php/src/Schemas/SecretGetRequest.php +++ /dev/null @@ -1,38 +0,0 @@ -id = Schema::string(); - $properties->id->description = "ID of the secret to retrieve"; - $properties->id->format = "uuid"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->id, - ); - $ownerSchema->setFromRef('#/definitions/SecretGetRequest'); - } -} \ No newline at end of file diff --git a/languages/php/src/Schemas/SecretIdentifiersRequest.php b/languages/php/src/Schemas/SecretIdentifiersRequest.php deleted file mode 100644 index b4e75b801..000000000 --- a/languages/php/src/Schemas/SecretIdentifiersRequest.php +++ /dev/null @@ -1,38 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization to retrieve all the secrets from"; - $properties->organizationId->format = "uuid"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->organizationId, - ); - $ownerSchema->setFromRef('#/definitions/SecretIdentifiersRequest'); - } -} diff --git a/languages/php/src/Schemas/SecretPutRequest.php b/languages/php/src/Schemas/SecretPutRequest.php deleted file mode 100644 index 59edec16d..000000000 --- a/languages/php/src/Schemas/SecretPutRequest.php +++ /dev/null @@ -1,69 +0,0 @@ -id = Schema::string(); - $properties->id->description = "ID of the secret to modify"; - $properties->id->format = "uuid"; - $properties->organizationId = Schema::string(); - $properties->organizationId->description = "Organization ID of the secret to modify"; - $properties->organizationId->format = "uuid"; - $properties->key = Schema::string(); - $properties->key->maxLength = 500; - $properties->key->minLength = 1; - $properties->value = Schema::string(); - $properties->value->maxLength = 25000; - $properties->value->minLength = 1; - $properties->note = Schema::string(); - $properties->note->maxLength = 7000; - $properties->projectIds = (new Schema())->setType([Schema::_ARRAY, Schema::NULL]); - $properties->projectIds->items = Schema::string(); - $properties->projectIds->items->format = "uuid"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->id, - self::names()->key, - self::names()->note, - self::names()->organizationId, - self::names()->value, - ); - $ownerSchema->setFromRef('#/definitions/SecretPutRequest'); - } -} \ No newline at end of file diff --git a/languages/php/src/Schemas/SecretVerificationRequest.php b/languages/php/src/Schemas/SecretVerificationRequest.php deleted file mode 100644 index 95cfd1e15..000000000 --- a/languages/php/src/Schemas/SecretVerificationRequest.php +++ /dev/null @@ -1,35 +0,0 @@ -masterPassword = (new Schema())->setType([Schema::STRING, Schema::NULL]); - $properties->masterPassword->description = "The user's master password to use for user verification. If supplied, this will be used for verification purposes."; - $properties->otp = (new Schema())->setType([Schema::STRING, Schema::NULL]); - $properties->otp->description = "Alternate user verification method through OTP. This is provided for users who have no master password due to use of Customer Managed Encryption. Must be present and valid if master_password is absent."; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->setFromRef('#/definitions/SecretVerificationRequest'); - } -} diff --git a/languages/php/src/Schemas/SecretsCommand.php b/languages/php/src/Schemas/SecretsCommand.php deleted file mode 100644 index cddc8ce49..000000000 --- a/languages/php/src/Schemas/SecretsCommand.php +++ /dev/null @@ -1,40 +0,0 @@ -secrets = new Schema(); - $properties->secrets->delete = SecretsDeleteRequest::schema(); - $properties->secrets->getByIds = SecretsGetRequest::schema(); - $properties->secrets->create = SecretCreateRequest::schema(); - $properties->secrets->update = SecretPutRequest::schema(); - $properties->secrets->list = SecretIdentifiersRequest::schema(); - $properties->secrets->get = SecretsGetRequest::schema(); - $properties->secrets->sync = SecretsSyncRequest::schema(); - $properties->secrets->setFromRef('#/definitions/SecretsCommand'); - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->secrets, - ); - } -} diff --git a/languages/php/src/Schemas/SecretsDeleteRequest.php b/languages/php/src/Schemas/SecretsDeleteRequest.php deleted file mode 100644 index 35138fcb1..000000000 --- a/languages/php/src/Schemas/SecretsDeleteRequest.php +++ /dev/null @@ -1,39 +0,0 @@ -ids = Schema::arr(); - $properties->ids->items = Schema::string(); - $properties->ids->items->format = "uuid"; - $properties->ids->description = "IDs of the secrets to delete"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->ids, - ); - $ownerSchema->setFromRef('#/definitions/SecretsDeleteRequest'); - } -} diff --git a/languages/php/src/Schemas/SecretsGetRequest.php b/languages/php/src/Schemas/SecretsGetRequest.php deleted file mode 100644 index 4758dabf4..000000000 --- a/languages/php/src/Schemas/SecretsGetRequest.php +++ /dev/null @@ -1,39 +0,0 @@ -ids = Schema::arr(); - $properties->ids->items = Schema::string(); - $properties->ids->items->format = "uuid"; - $properties->ids->description = "IDs of the secrets to retrieve"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->ids, - ); - $ownerSchema->setFromRef('#/definitions/SecretsGetRequest'); - } -} diff --git a/languages/php/src/Schemas/SecretsSyncRequest.php b/languages/php/src/Schemas/SecretsSyncRequest.php deleted file mode 100644 index 4d98db0f4..000000000 --- a/languages/php/src/Schemas/SecretsSyncRequest.php +++ /dev/null @@ -1,42 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization to sync secrets from"; - $properties->organizationId->format = "uuid"; - $properties->lastSyncedDate = (new Schema())->setType([Schema::STRING, Schema::NULL]); - $properties->lastSyncedDate->description = "Optional date time a sync last occurred"; - $properties->lastSyncedDate->format = "date-time"; - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - $ownerSchema->required = array( - self::names()->organizationId, - ); - $ownerSchema->setFromRef('#/definitions/SecretsSyncRequest'); - } -} diff --git a/languages/php/src/SecretsClient.php b/languages/php/src/SecretsClient.php index ef949ce85..85bc334d5 100644 --- a/languages/php/src/SecretsClient.php +++ b/languages/php/src/SecretsClient.php @@ -11,6 +11,8 @@ use Bitwarden\Sdk\Schemas\SecretsDeleteRequest; use Bitwarden\Sdk\Schemas\SecretsGetRequest; use Bitwarden\Sdk\Schemas\SecretsSyncRequest; +use Exception; +use stdClass; class SecretsClient { @@ -21,94 +23,103 @@ public function __construct(CommandRunner $commandRunner) $this->commandRunner = $commandRunner; } - public function get(string $secret_id): \stdClass + /** + * @throws Exception + */ + public function get(string $secret_id): stdClass { - $secret_get_request = new SecretGetRequest(); - $secret_get_request->id = $secret_id; + $secret_get_request = new SecretGetRequest($secret_id); $secret_get_request->validate(); - $secret_command = new SecretsCommand(); - $secret_command->get = $secret_get_request->jsonSerialize(); - return $this->run_secret_command($secret_command); + $secrets_command = new SecretsCommand(get: $secret_get_request, getByIds: null, create: null, list: null, + update: null, delete: null, sync: null); + return $this->run_secret_command($secrets_command); } - public function get_by_ids(array $secret_ids): \stdClass + /** + * @throws Exception + */ + public function get_by_ids(array $secret_ids): stdClass { - $project_get_by_ids_request = new SecretsGetRequest(); - $project_get_by_ids_request->ids = $secret_ids; + $project_get_by_ids_request = new SecretsGetRequest($secret_ids); $project_get_by_ids_request->validate(); - $secrets_command = new SecretsCommand(); - $secrets_command->getByIds = $project_get_by_ids_request->jsonSerialize(); + $secrets_command = new SecretsCommand(get: null, getByIds: $project_get_by_ids_request, create: null, list: null, + update: null, delete: null, sync: null); return $this->run_secret_command($secrets_command); } - public function list(string $organization_id): \stdClass + /** + * @throws Exception + */ + public function list(string $organization_id): stdClass { - $secrets_list_request = new SecretIdentifiersRequest(); - $secrets_list_request->organizationId = $organization_id; + $secrets_list_request = new SecretIdentifiersRequest($organization_id); $secrets_list_request->validate(); - $secrets_command = new SecretsCommand(); - $secrets_command->list = $secrets_list_request->jsonSerialize(); + $secrets_command = new SecretsCommand(get: null, getByIds: null, create: null, list: $secrets_list_request, + update: null, delete: null, sync: null); return $this->run_secret_command($secrets_command); } - public function create(string $organization_id, string $key, string $value, string $note, array $project_ids): \stdClass + /** + * @throws Exception + */ + public function create(string $organization_id, string $key, string $value, string $note, array $project_ids): stdClass { - $secrets_create_request = new SecretCreateRequest(); - $secrets_create_request->organizationId = $organization_id; - $secrets_create_request->projectIds = $project_ids; - $secrets_create_request->key = $key; - $secrets_create_request->note = $note; - $secrets_create_request->value = $value; + $secrets_create_request = new SecretCreateRequest(key: $key, note: $note, organizationId: $organization_id, + projectIds: $project_ids, value: $value); $secrets_create_request->validate(); - $secrets_command = new SecretsCommand(); - $secrets_command->create = $secrets_create_request->jsonSerialize(); + $secrets_command = new SecretsCommand(get: null, getByIds: null, create: $secrets_create_request, list: null, + update: null, delete: null, sync: null); return $this->run_secret_command($secrets_command); } - public function update(string $organization_id, string $id, string $key, string $value, string $note, array $project_ids): \stdClass + /** + * @throws Exception + */ + public function update(string $organization_id, string $id, string $key, string $value, string $note, array $project_ids): stdClass { - $secrets_put_request = new SecretPutRequest(); - $secrets_put_request->id = $id; - $secrets_put_request->organizationId = $organization_id; - $secrets_put_request->projectIds = $project_ids; - $secrets_put_request->key = $key; - $secrets_put_request->note = $note; - $secrets_put_request->value = $value; + $secrets_put_request = new SecretPutRequest(id: $id, key: $key, note: $note, organizationId: $organization_id, + projectIds: $project_ids, value: $value); $secrets_put_request->validate(); - $secrets_command = new SecretsCommand(); - $secrets_command->update = $secrets_put_request->jsonSerialize(); + $secrets_command = new SecretsCommand(get: null, getByIds: null, create: null, list: null, + update: $secrets_put_request, delete: null, sync: null); return $this->run_secret_command($secrets_command); } - public function delete(array $secrets_ids): \stdClass + /** + * @throws Exception + */ + public function delete(array $secrets_ids): stdClass { - $secrets_delete_request = new SecretsDeleteRequest(); - $secrets_delete_request->ids = $secrets_ids; + $secrets_delete_request = new SecretsDeleteRequest($secrets_ids); $secrets_delete_request->validate(); - $secrets_command = new SecretsCommand(); - $secrets_command->delete = $secrets_delete_request->jsonSerialize(); + $secrets_command = new SecretsCommand(get: null, getByIds: null, create: null, list: null, + update: null, delete: $secrets_delete_request, sync: null); return $this->run_secret_command($secrets_command); } - public function sync(string $organization_id, ?string $last_synced_date): \stdClass + /** + * @throws Exception + */ + public function sync(string $organization_id, ?string $last_synced_date): stdClass { if (empty($last_synced_date)) { $last_synced_date = "1970-01-01T00:00:00.000Z"; } - $secrets_sync_request = new SecretsSyncRequest(); - $secrets_sync_request->organizationId = $organization_id; - $secrets_sync_request->lastSyncedDate = $last_synced_date; + $secrets_sync_request = new SecretsSyncRequest(lastSyncedDate: $last_synced_date, organizationId: $organization_id); $secrets_sync_request->validate(); - $secrets_command = new SecretsCommand(); - $secrets_command->sync = $secrets_sync_request->jsonSerialize(); + $secrets_command = new SecretsCommand(get: null, getByIds: null, create: null, list: null, + update: null, delete: null, sync: $secrets_sync_request); return $this->run_secret_command($secrets_command); } - public function run_secret_command($secretsCommand): \stdClass + /** + * @throws Exception + */ + public function run_secret_command($secretsCommand): stdClass { - $command = new Command(); - $command->secrets = $secretsCommand; + $command = new Command(passwordLogin: null, apiKeyLogin: null, loginAccessToken: null, getUserApiKey: null, + fingerprint: null, sync: null, secrets: $secretsCommand, projects: null, generators: null); return $this->commandRunner->run($command); } } diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 5ea71408c..3eaad1903 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -117,9 +117,30 @@ async function main() { java.forEach((file, path) => { writeToFile(javaDir + path, file.lines); }); + + const php = await quicktype({ + inputData, + lang: "php", + inferUuids: false, + inferDateTimes: false, + rendererOptions: { + "acronym-style": "camel", + "with-get": false, + }, + }); + + const phpDir = "./languages/php/src/Schemas/"; + if (!fs.existsSync(phpDir)) { + fs.mkdirSync(phpDir); + } + + php.lines.splice(1, 0, "namespace Bitwarden\\Sdk\\Schemas;", "use stdClass;", "use Exception;"); + + writeToFile("./languages/php/src/Schemas/Schemas.php", php.lines); } main(); + function writeToFile(filename: string, lines: string[]) { const output = fs.createWriteStream(filename); lines.forEach((line) => { From a57e2ed6e99467c61b343724972bbbc2bf6bbad7 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 18 Sep 2024 06:21:04 -0700 Subject: [PATCH 34/36] add link to access token --- languages/php/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/README.md b/languages/php/README.md index 61991bd0e..2df2e331e 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -11,7 +11,7 @@ See the [installation instructions](./INSTALL.md) ### Create access token To interact with the client first you need to obtain the access token from Bitwarden. -Review the help documentation on [Access Tokens]. +Review the help documentation on [Access Tokens](https://bitwarden.com/help/access-tokens/). ### Create new Bitwarden client From 028c43df1c3cadb94d826e03b131ce35247820b0 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 18 Sep 2024 06:24:48 -0700 Subject: [PATCH 35/36] update project name --- languages/php/example.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/example.php b/languages/php/example.php index acc7ca5ed..864a4ca23 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -36,7 +36,7 @@ print("\n"); // update project - $res = $bitwarden_client->projects->update($organization_id, $project_id, 'php test awesome'); + $res = $bitwarden_client->projects->update($organization_id, $project_id, 'php test project'); print("\tupdate: '" . $res->name . "'\n\n"); // sync secrets From f255347e6f3f6b7318eeb6df40920b43324cbd6c Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 18 Sep 2024 06:34:09 -0700 Subject: [PATCH 36/36] Revert "add link to access token" This reverts commit a57e2ed6e99467c61b343724972bbbc2bf6bbad7. Access token link was already there. --- languages/php/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/php/README.md b/languages/php/README.md index 2df2e331e..61991bd0e 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -11,7 +11,7 @@ See the [installation instructions](./INSTALL.md) ### Create access token To interact with the client first you need to obtain the access token from Bitwarden. -Review the help documentation on [Access Tokens](https://bitwarden.com/help/access-tokens/). +Review the help documentation on [Access Tokens]. ### Create new Bitwarden client