From c623fb8a74437eaa7ff0a88f20411a5585f15672 Mon Sep 17 00:00:00 2001 From: David Smith Date: Thu, 31 Oct 2024 11:07:37 -0500 Subject: [PATCH] finally ready for someone other than me to review :D --- src/API/Accounts/AccountsClient.php | 190 +----------------- .../Accounts/AddCollabToAcctCommand.php | 56 +++++- .../Accounts/RemoveCollabFromAcctCommand.php | 4 +- 3 files changed, 56 insertions(+), 194 deletions(-) diff --git a/src/API/Accounts/AccountsClient.php b/src/API/Accounts/AccountsClient.php index d70fde1..6b81f23 100644 --- a/src/API/Accounts/AccountsClient.php +++ b/src/API/Accounts/AccountsClient.php @@ -13,13 +13,12 @@ public function getCollaborators(string $accessToken, string $accountId) return $this->guzzle($this->getBearerTokenMiddleware($accessToken))->get("accounts/{$accountId}/access"); } - public function getCollabRole(string $accessToken, int $accountId, int $collabId, int $appId = 0): int + // 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) { - // print_r($tidbit); - // should this output be validated or similar? if (($tidbit['appId'] == $appId) && ($tidbit['sourceId'] == $collabId)) { return $tidbit['role']; } @@ -27,74 +26,25 @@ public function getCollabRole(string $accessToken, int $accountId, int $collabId return 0; } - public function addCollaboratorToAcct(string $accessToken, string $newAcctEmail, string $newAcctName, int $newAcctRole, int $newAcctId) + 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' => 0 + 'appId' => $newAppId ], ]); } - public function removeCollaboratorFromAcct(string $accessToken, int $acctId, int $collabId, int $appId = 0) { - // $role = 6; // this is a temp hack, need to actually get user's role somehow + 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}"); } - public function removeCollaboratorsForApp(string $accessToken, string $accountId, int $appId) - { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->delete("accounts/{$accountId}/collaborators/apps/{$appId}"); - } - - // This API is both for removing access from individual apps, as well - // as removing access for whole accounts. fun! - /** - * @param string $accessToken - * @param int|string $targetAccountId - * @param ?int $sourceAccountId - * @param null $role - * @param int $appId - * @return \Psr\Http\Message\ResponseInterface - * @throws \Exception - */ - public function removeAccess(string $accessToken, $targetAccountId, $sourceAccountId = null, $role = null, $appId = 0) - { - if ($sourceAccountId) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->delete("accounts/{$targetAccountId}/collaborators/{$sourceAccountId}/{$role}/{$appId}"); - } - - // returned, so at thsi point we know no sourceAccountId was given. - - if ($appId) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->delete("accounts/{$targetAccountId}/collaborators/apps/{$appId}"); - } - - throw new \Exception('Invalid arguments - must include source & role [& app], or app by itself'); - } - - public function listSshPublicKeys( - string $accessToken, - string $accountId, - ?string $orchestration = null, - ) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->get("accounts/{$accountId}/ssh/keys", [ - 'json' => array_filter( - compact( - 'orchestration', - ) - ), - ]); - } - public function createSshPublicKey( string $accessToken, string $accountId, @@ -112,132 +62,4 @@ public function createSshPublicKey( ]); } - public function deleteSshPublicKey( - string $accessToken, - string $accountId, - string $sshKeyId, - ?string $orchestration = null, - ) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->delete("accounts/{$accountId}/ssh/keys/{$sshKeyId}", [ - 'json' => array_filter(compact( - 'orchestration', - )), - ]); - } - - public function createSshUser( - string $accessToken, - string $sshUsername, - string $ownerId, - string $ownerType, - string $sshUserType, - bool $sftpOnly = false, - array $appIds = [], - bool $replace = false, - bool $disabled = false, - bool $generatePassword = false, - ?string $password = null, - ?\DateTimeInterface $expiry = null - ) { - $expiry = $expiry ? $expiry->format(\DateTimeInterface::ATOM) : null; - - $nonNullParams = array_filter(compact( - 'sshUsername', - 'ownerType', - 'sshUserType', - 'sftpOnly', - 'appIds', - 'replace', - 'disabled', - 'generatePassword', - 'password', - 'expiry', - ), function ($value) { - return $value !== null; - }); - - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->post("accounts/{$ownerId}/ssh/user", [ - 'json' => $nonNullParams, - ]); - } - - public function getSshUser( - string $accessToken, - string $sshUsername, - ) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->get("accounts/ssh/users/{$sshUsername}"); - } - - public function updateSshUser( - string $accessToken, - string $ownerId, - #[\SensitiveParameter] - ?string $password = null, - ?bool $sftpOnly = null, - ?bool $disabled = null, - ?\DateTimeInterface $expiry = null - ) { - $expiry = $expiry ? $expiry->format(\DateTimeInterface::ATOM) : null; - - $nonNullParams = array_filter(compact( - 'password', - 'sftpOnly', - 'disabled', - 'expiry', - ), function ($value) { - return $value !== null; - }); - - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->patch("accounts/{$ownerId}/ssh/user", [ - 'json' => $nonNullParams, - ]); - } - - public function createSshApps( - string $accessToken, - string $sshUsername, - array $appIds, - ) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->post('accounts/ssh/apps/create', [ - 'json' => [ - 'sshUsername' => $sshUsername, - 'appIds' => $appIds, - ], - ]); - } - - public function listApps( - string $accessToken, - string $sshUsername, - ) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->get("accounts/ssh/users/{$sshUsername}/apps"); - } - - public function deleteSshUser( - string $accessToken, - string $accountId, - ) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->delete("accounts/{$accountId}/ssh/user"); - } - - public function deleteSshApps( - string $accessToken, - array $appIds, - ) { - return $this->guzzle($this->getBearerTokenMiddleware($accessToken)) - ->post('accounts/ssh/apps', [ - 'json' => [ - 'appIds' => $appIds, - ], - ]); - } - - } diff --git a/src/Command/Accounts/AddCollabToAcctCommand.php b/src/Command/Accounts/AddCollabToAcctCommand.php index 82d4887..b51a54c 100644 --- a/src/Command/Accounts/AddCollabToAcctCommand.php +++ b/src/Command/Accounts/AddCollabToAcctCommand.php @@ -26,16 +26,16 @@ public function __construct(AuthApi $authApi, AccountsClient $apps, $name = 'acc parent::__construct($name); } - // TODO the role should probably be an enum with actually useful text values instead of random ints public function configure() { parent::configure(); $this - ->setDescription('Add collaborator to account') + ->setDescription('Add collaborator to account or app') ->addArgument('email', InputArgument::REQUIRED, 'Email address') ->addArgument('accountId', InputArgument::REQUIRED, 'Account ID') - ->addArgument('roleId', InputArgument::REQUIRED, 'Role ID') - ->addArgument('name', InputArgument::OPTIONAL, 'Display Name', 0) + ->addArgument('roleId', InputArgument::REQUIRED, 'Role') + ->addArgument('appId', InputArgument::OPTIONAL, 'App ID (acct-level if omitted)', 0) + ->addArgument('displayName', InputArgument::OPTIONAL, 'Display Name', 0) ; $this->addOauthOptions(); } @@ -43,16 +43,56 @@ public function configure() public function execute(InputInterface $input, OutputInterface $output): int { $newAcctEmail = $input->getArgument('email'); - $newAcctName = $input->getArgument('name'); + $newAcctName = $input->getArgument('displayName'); if ($newAcctName === 0) { $newAcctName = $input->getArgument('email'); } - $newAcctAppId = $input->getArgument('accountId'); - $newAcctRole = $input->getArgument('roleId'); + $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('appId'); $token = $this->token->token; $r = $this->api->addCollaboratorToAcct($token, - $newAcctEmail, $newAcctName, $newAcctRole, $newAcctAppId); + $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; break; + case "app-only": + case "apponly": + case "2": + return 2; break; + case "billing": + case "4": + return 4; break; + case "tech": + case "6": + return 6; break; + case "sub-admin": + case "subadmin": + case "8": + return 8; break; + case "super-admin": + case "superadmin": + case "9": + return 9; break; + case "owner": + case "10": + return 10; break; + default: + return false; break; + } + return false; + } } diff --git a/src/Command/Accounts/RemoveCollabFromAcctCommand.php b/src/Command/Accounts/RemoveCollabFromAcctCommand.php index 0c4813e..ad30479 100644 --- a/src/Command/Accounts/RemoveCollabFromAcctCommand.php +++ b/src/Command/Accounts/RemoveCollabFromAcctCommand.php @@ -30,10 +30,10 @@ public function configure() { parent::configure(); $this - ->setDescription('Remove collaborator from account') + ->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, or 0 for all apps', 0) + ->addArgument('appId', InputArgument::OPTIONAL, 'App ID (acct-level if omitted)', 0) ; $this->addOauthOptions(); }