diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c8f77b..e343e3a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,8 @@ jobs: args: --ignore-platform-reqs - uses: php-actions/phpstan@v2 with: - php_version: 7.4 + php_version: 8.1 path: src level: 5 + args: --memory-limit=512M diff --git a/README.md b/README.md index b044eed..425dd3f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # atomic-client PHP Library to access the Pagely atomic APIs -*Note that PHP 7.1+ is required* +*Note that PHP 8.1+ is required* # Installation -Installation assumes you already have git, PHP7.1+, and composer installed. +Installation assumes you already have git, PHP 8.1+, and composer installed. ```bash git clone git@github.com:pagely/atomic-client.git diff --git a/src/API/Accounts/AccountsClient.php b/src/API/Accounts/AccountsClient.php index 3940ca8..9ffc3dd 100644 --- a/src/API/Accounts/AccountsClient.php +++ b/src/API/Accounts/AccountsClient.php @@ -1,22 +1,66 @@ guzzle($this->getBearerTokenMiddleware($accessToken))->get("accounts/{$accountId}/access"); + } + + // this whole function feels super hacky but I don't think there's an API way to get this info + private function getCollabRole(string $accessToken, int $accountId, int $collabId, int $appId = 0): int + { + $r = $this->getCollaborators($accessToken, $accountId); + $collabInfo = json_decode($r->getBody()->getContents(), true); + foreach(@$collabInfo['whoCanAccess'] as $tidbit) { + if (($tidbit['appId'] == $appId) && ($tidbit['sourceId'] == $collabId)) { + return $tidbit['role']; + } + } + return 0; + } + + public function addCollaboratorToAcct(string $accessToken, string $newAcctEmail, string $newAcctName, int $newAcctId, int $newAcctRole, int $newAppId) { + return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) + ->post("accounts/{$newAcctId}/collaborators", ['json' => [ + 'email' => $newAcctEmail, + 'name' => $newAcctName, + 'role' => $newAcctRole, + 'appId' => $newAppId + ], + ]); + } + + public function removeCollaboratorFromAcct(string $accessToken, int $acctId, int $collabId, int $appId = 0) + { + $role = $this->getCollabRole($accessToken, $acctId, $collabId, $appId); + return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) + ->delete("accounts/{$acctId}/collaborators/{$collabId}/{$role}/{$appId}"); + } + + // this is named createSshPublicKey in upstream mgmt-client + public function addSshKey( + string $accessToken, + int $accountId, + string $key, + ?string $orchestration = null, + ?string $sshUsername = null, + ) { return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) ->post("accounts/{$accountId}/ssh/keys", [ - 'json' => [ - 'key' => $sshKey - ], + 'json' => array_filter(compact( + 'key', + 'orchestration', + 'sshUsername', + )), ]); } + } diff --git a/src/Command/Accounts/AddCollabToAcctCommand.php b/src/Command/Accounts/AddCollabToAcctCommand.php new file mode 100644 index 0000000..1137910 --- /dev/null +++ b/src/Command/Accounts/AddCollabToAcctCommand.php @@ -0,0 +1,99 @@ +authClient = $authApi; + $this->api = $accounts; + parent::__construct($name); + } + + public function configure() + { + parent::configure(); + $this + ->setDescription('Add collaborator to account or app') + ->addArgument('email', InputArgument::REQUIRED, 'Email address') + ->addArgument('accountId', InputArgument::REQUIRED, 'Account ID') + ->addArgument('roleId', InputArgument::REQUIRED, 'Role') + ->addOption('app', null, InputOption::VALUE_OPTIONAL, 'App ID (acct-level if omitted)', 0) + ->addOption('displayname', null, InputOption::VALUE_OPTIONAL, 'Display Name', 0) + ; + $this->addOauthOptions(); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $newAcctEmail = $input->getArgument('email'); + $newAcctName = $input->getArgument('displayname'); + if ($newAcctName === 0) { $newAcctName = $input->getArgument('email'); } + $newAcctId = $input->getArgument('accountId'); + $newAcctRole = $this->roleToInt($input->getArgument('roleId')); + if ($newAcctRole === false) { + $output->writeln ("Invalid role, must be one of 'app-only-minimal', 'app-only', 'billing', 'tech', 'sub-admin', 'super-admin', 'owner'"); + return Command::FAILURE; + } + $newAppId = $input->getArgument('app'); + $token = $this->token->token; + + $r = $this->api->addCollaboratorToAcct($token, + $newAcctEmail, $newAcctName, $newAcctId, $newAcctRole, $newAppId); + $output->writeln(json_encode(json_decode($r->getBody()->getContents()), JSON_PRETTY_PRINT)); + + return 0; + } + + private function roleToInt(string $role) + { + $role = strtolower($role); + switch($role) { + case "app-only-minimal": + case "apponlyminimal": + case "1": + return 1; + case "app-only": + case "apponly": + case "2": + return 2; + case "billing": + case "4": + return 4; + case "tech": + case "6": + return 6; + case "sub-admin": + case "subadmin": + case "8": + return 8; + case "super-admin": + case "superadmin": + case "9": + return 9; + case "owner": + case "10": + return 10; + default: + return false; + } + // return false; + } +} diff --git a/src/Command/Accounts/ListCollabsCommand.php b/src/Command/Accounts/ListCollabsCommand.php new file mode 100644 index 0000000..651d149 --- /dev/null +++ b/src/Command/Accounts/ListCollabsCommand.php @@ -0,0 +1,49 @@ +authClient = $authApi; + $this->api = $apps; + parent::__construct($name); + } + + public function configure() + { + parent::configure(); + $this + ->setDescription('List collaborators on account') + ->addArgument('accountId', InputArgument::REQUIRED, 'Account ID') + ; + $this->addOauthOptions(); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $accountId = $input->getArgument('accountId'); + $token = $this->token->token; + + $r = $this->api->getCollaborators($token, $accountId); + $output->writeln(json_encode(json_decode($r->getBody()->getContents()), JSON_PRETTY_PRINT)); + + return 0; + } +} diff --git a/src/Command/Accounts/RemoveCollabFromAcctCommand.php b/src/Command/Accounts/RemoveCollabFromAcctCommand.php new file mode 100644 index 0000000..ad30479 --- /dev/null +++ b/src/Command/Accounts/RemoveCollabFromAcctCommand.php @@ -0,0 +1,53 @@ +authClient = $authApi; + $this->api = $apps; + parent::__construct($name); + } + + public function configure() + { + parent::configure(); + $this + ->setDescription('Remove collaborator from account or app') + ->addArgument('accountId', InputArgument::REQUIRED, 'Account ID') + ->addArgument('collabId', InputArgument::REQUIRED, 'Collab User ID') + ->addArgument('appId', InputArgument::OPTIONAL, 'App ID (acct-level if omitted)', 0) + ; + $this->addOauthOptions(); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $accountId = $input->getArgument('accountId'); + $collabId = $input->getArgument('collabId'); + $appId = $input->getArgument('appId'); + $token = $this->token->token; + + $r = $this->api->removeCollaboratorFromAcct($token, $accountId, $collabId, $appId); + $output->writeln(json_encode(json_decode($r->getBody()->getContents()), JSON_PRETTY_PRINT)); + + return 0; + } +}