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/INSTALL.md b/languages/php/INSTALL.md new file mode 100644 index 000000000..299053389 --- /dev/null +++ b/languages/php/INSTALL.md @@ -0,0 +1,56 @@ +# PHP Installation + +## Introduction + +Composer is used to build the PHP Bitwarden client library. + +## Prerequisites + +- PHP >= 8.0 +- FFI extension enabled in PHP configuration +- Composer +- 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 the SDK yourself, see the [SDK README.md](../../README.md) for instructions. + +## 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 STATE_FILE="" +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..61991bd0e 100644 --- a/languages/php/README.md +++ b/languages/php/README.md @@ -1,100 +1,121 @@ # 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. ## 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 = ""; +$state_file = ""; +$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); +$bitwarden_client->auth->login_access_token($access_token, $state_file); ``` -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" -$res = $bitwarden_client->projects->create($name, $organization_id); +```php +$name = "PHP project"; +$res = $bitwarden_client->projects->create($organization_id, $name); $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->update($organization_id, $project_id, $name); +``` -// 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($organization_id, $key, $value, $note, [$project_id]); +$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 secrets +### List all secrets + +```php $res = $bitwarden_client->secrets->list($organization_id); +``` + +### Update secret + +```php +$key = "Updated key"; +$note = "Updated note"; +$value = "Updated value"; +$res = $bitwarden_client->secrets->update($organization_id, $secret_id, $key, $value, $note, [$project_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); +### Sync secrets -// delete secret -$res = $bitwarden_sdk->secrets->delete([$secret_id]); +```php +$last_synced_date = "2024-09-01T00:00:00Z"; +$res = $bitwarden_client->secrets->sync($organization_id, $last_synced_date); +``` + +### 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/ 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 fc6b42c4f..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": "7081b1bfe099982a63ad06d5ab9fa66d", - "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 7eafcb96a..864a4ca23 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -3,45 +3,101 @@ 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 $api_url = getenv('API_URL'); $identity_url = getenv('IDENTITY_URL'); -$client_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); +try { + $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); + $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); -// create project -$res = $bitwarden_client->projects->create('php project', $organization_id); -$project_id = $res->id; + $bitwarden_client->auth->login_access_token($access_token, $state_file); -// get project -$res = $bitwarden_client->projects->get($project_id); + // create project + print("Projects:\n"); + $res = $bitwarden_client->projects->create($organization_id, 'php project'); + $project_id = $res->id; + print("\tcreate: '" . $project_id . "'\n\n"); -// list projects -$res = $bitwarden_client->projects->list($organization_id); + // get project + $res = $bitwarden_client->projects->get($project_id); + print("\tget: '" . $res->name . "'\n\n"); -// update project -$res = $bitwarden_client->projects->put($project_id, 'php test awesome', $organization_id); + // 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"); -// create secret -$res = $bitwarden_client->secrets->create("New Key", "hello world", $organization_id, [$project_id], "123"); -$secret_id = $res->id; + // update project + $res = $bitwarden_client->projects->update($organization_id, $project_id, 'php test project'); + print("\tupdate: '" . $res->name . "'\n\n"); -// get secret -$res = $bitwarden_client->secrets->get($secret_id); + // 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"); -// list secrets -$res = $bitwarden_client->secrets->list($organization_id); + 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"); -// update secret -$res = $bitwarden_client->secrets->update($secret_id, "hello world 2", "hello", $organization_id, [$project_id], "123"); + // 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"); -// delete secret -$res = $bitwarden_client->secrets->delete([$secret_id]); + // get secret + $res = $bitwarden_client->secrets->get($secret_id); + print("\tget: '" . $res->key . "'\n\n"); -// delete project -$res = $bitwarden_client->projects->delete([$project_id]); + // 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); +} 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 79fccdf9c..c125b6aa7 100644 --- a/languages/php/src/BitwardenClient.php +++ b/languages/php/src/BitwardenClient.php @@ -2,59 +2,40 @@ namespace Bitwarden\Sdk; -use Bitwarden\Sdk\Schemas\AccessTokenLoginRequest; -use Bitwarden\Sdk\schemas\ClientSettings; -use Bitwarden\Sdk\Schemas\Command; -use FFI; -use Swaggest\JsonDiff\Exception; - +use Bitwarden\Sdk\Schemas\ClientSettings; +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); - } - - /** - * @throws \Exception - */ - public function access_token_login(string $access_token) - { - $access_token_request = new AccessTokenLoginRequest(); - $access_token_request->accessToken = $access_token; - $command = new Command(); - $command->accessTokenLogin = $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->auth = new AuthClient($this->commandRunner); } public function __destruct() diff --git a/languages/php/src/BitwardenLib.php b/languages/php/src/BitwardenLib.php index 351728986..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 = '/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 = '/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 6b6f9fb6a..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 $project_name, string $organization_id): \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 put(string $project_id, string $project_name, string $organization_id): \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/SecretsClient.php b/languages/php/src/SecretsClient.php index d5c0b0cef..85bc334d5 100644 --- a/languages/php/src/SecretsClient.php +++ b/languages/php/src/SecretsClient.php @@ -10,6 +10,9 @@ use Bitwarden\Sdk\Schemas\SecretsCommand; use Bitwarden\Sdk\Schemas\SecretsDeleteRequest; use Bitwarden\Sdk\Schemas\SecretsGetRequest; +use Bitwarden\Sdk\Schemas\SecretsSyncRequest; +use Exception; +use stdClass; class SecretsClient { @@ -20,79 +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->get_by_ids = $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 $key, string $note, string $organization_id, array $project_ids, string $value): \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 $id, string $key, string $note, string $organization_id, array $project_ids, string $value): \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); + } + + /** + * @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(lastSyncedDate: $last_synced_date, organizationId: $organization_id); + $secrets_sync_request->validate(); + $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/languages/php/src/schemas/AccessTokenLoginRequest.php b/languages/php/src/schemas/AccessTokenLoginRequest.php deleted file mode 100644 index a08805f92..000000000 --- a/languages/php/src/schemas/AccessTokenLoginRequest.php +++ /dev/null @@ -1,39 +0,0 @@ -accessToken = Schema::string(); - $properties->accessToken->description = "Bitwarden service API access token"; - $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/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 deleted file mode 100644 index c27cc3322..000000000 --- a/languages/php/src/schemas/ClientSettings.php +++ /dev/null @@ -1,133 +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->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."; - } -} diff --git a/languages/php/src/schemas/Command.php b/languages/php/src/schemas/Command.php deleted file mode 100644 index cbd649c2f..000000000 --- a/languages/php/src/schemas/Command.php +++ /dev/null @@ -1,44 +0,0 @@ -projects = ProjectsCommand::schema(); - $properties->secrets = SecretsCommand::schema(); - $properties->accessTokenLogin = AccessTokenLoginRequest::schema(); - - $ownerSchema->type = Schema::OBJECT; - $ownerSchema->additionalProperties = false; - - $ownerSchema->oneOf = array( - self::names()->projects, - self::names()->secrets, - self::names()->accessTokenLogin, - ); - } -} diff --git a/languages/php/src/schemas/ProjectCreateRequest.php b/languages/php/src/schemas/ProjectCreateRequest.php deleted file mode 100644 index 6a4e0f082..000000000 --- a/languages/php/src/schemas/ProjectCreateRequest.php +++ /dev/null @@ -1,43 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization where the project will be created"; - $properties->organizationId->format = "uuid"; - $properties->name = Schema::string(); - $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 972bf18ec..000000000 --- a/languages/php/src/schemas/ProjectGetRequest.php +++ /dev/null @@ -1,37 +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 96b9705e7..000000000 --- a/languages/php/src/schemas/ProjectPutRequest.php +++ /dev/null @@ -1,50 +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(); - $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 22645db3c..000000000 --- a/languages/php/src/schemas/ProjectsCommand.php +++ /dev/null @@ -1,55 +0,0 @@ - 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 -{ - public ?\stdClass $delete; - - public ?\stdClass $get; - - public ?\stdClass $list; - - public ?\stdClass $create; - - public ?\stdClass $update; - - - /** - * @param Properties|static $properties - * @param Schema $ownerSchema - */ - 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; - $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, - ); - } -} diff --git a/languages/php/src/schemas/ProjectsDeleteRequest.php b/languages/php/src/schemas/ProjectsDeleteRequest.php deleted file mode 100644 index 87a7cfad7..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'); - } -} diff --git a/languages/php/src/schemas/ProjectsListRequest.php b/languages/php/src/schemas/ProjectsListRequest.php deleted file mode 100644 index cc1a9474f..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'); - } -} diff --git a/languages/php/src/schemas/SecretCreateRequest.php b/languages/php/src/schemas/SecretCreateRequest.php deleted file mode 100644 index d34b36e98..000000000 --- a/languages/php/src/schemas/SecretCreateRequest.php +++ /dev/null @@ -1,58 +0,0 @@ -organizationId = Schema::string(); - $properties->organizationId->description = "Organization where the secret will be created"; - $properties->organizationId->format = "uuid"; - $properties->key = Schema::string(); - $properties->value = Schema::string(); - $properties->note = Schema::string(); - $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'); - } -} diff --git a/languages/php/src/schemas/SecretGetRequest.php b/languages/php/src/schemas/SecretGetRequest.php deleted file mode 100644 index f31f7cad3..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'); - } -} 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 d890a909d..000000000 --- a/languages/php/src/schemas/SecretPutRequest.php +++ /dev/null @@ -1,64 +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->value = Schema::string(); - $properties->note = Schema::string(); - $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'); - } -} 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 1ed8c97c5..000000000 --- a/languages/php/src/schemas/SecretsCommand.php +++ /dev/null @@ -1,56 +0,0 @@ - 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 -{ - public ?\stdClass $delete; - - public ?\stdClass $get; - - public ?\stdClass $getByIds; - - public ?\stdClass $list; - - public ?\stdClass $create; - - public ?\stdClass $put; - - /** - * @param Properties|static $properties - * @param Schema $ownerSchema - */ - 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; - $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, - ); - } -} 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/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) => {