diff --git a/lib/Client.php b/lib/Client.php index ea5c6ffe..28adf4a9 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -13,6 +13,7 @@ class Client public const METHOD_POST = "post"; public const METHOD_DELETE = "delete"; public const METHOD_PUT = "put"; + public const METHOD_PATCH = "patch"; private static $_requestClient; diff --git a/lib/RBAC.php b/lib/RBAC.php new file mode 100644 index 00000000..76f410e2 --- /dev/null +++ b/lib/RBAC.php @@ -0,0 +1,151 @@ + $slug, + "name" => $name, + ]; + + if (isset($description)) { + $params["description"] = $description; + } + if (isset($resourceTypeSlug)) { + $params["resource_type_slug"] = $resourceTypeSlug; + } + + $response = Client::request(Client::METHOD_POST, $path, null, $params, true); + + return Resource\Permission::constructFromResponse($response); + } + + /** + * List Permissions. + * + * @param int $limit Maximum number of records to return + * @param null|string $before Permission ID to look before + * @param null|string $after Permission ID to look after + * @param null|string $order The order in which to paginate records + * + * @throws Exception\WorkOSException + * + * @return array{?string, ?string, Resource\Permission[]} + */ + public function listPermissions( + int $limit = self::DEFAULT_PAGE_SIZE, + ?string $before = null, + ?string $after = null, + ?string $order = null + ) { + $path = "authorization/permissions"; + + $params = [ + "limit" => $limit, + "before" => $before, + "after" => $after, + "order" => $order, + ]; + + $response = Client::request(Client::METHOD_GET, $path, null, $params, true); + + $permissions = []; + list($before, $after) = Util\Request::parsePaginationArgs($response); + foreach ($response["data"] as $responseData) { + \array_push($permissions, Resource\Permission::constructFromResponse($responseData)); + } + + return [$before, $after, $permissions]; + } + + /** + * Get a Permission. + * + * @param string $slug The slug of the Permission + * + * @throws Exception\WorkOSException + * + * @return Resource\Permission + */ + public function getPermission(string $slug) + { + $path = "authorization/permissions/{$slug}"; + + $response = Client::request(Client::METHOD_GET, $path, null, null, true); + + return Resource\Permission::constructFromResponse($response); + } + + /** + * Update a Permission. + * + * @param string $slug The slug of the Permission to update + * @param null|string $name The updated name of the Permission + * @param null|string $description The updated description of the Permission + * + * @throws Exception\WorkOSException + * + * @return Resource\Permission + */ + public function updatePermission( + string $slug, + ?string $name = null, + ?string $description = null + ) { + $path = "authorization/permissions/{$slug}"; + + $params = []; + + if (isset($name)) { + $params["name"] = $name; + } + if (isset($description)) { + $params["description"] = $description; + } + + $response = Client::request(Client::METHOD_PATCH, $path, null, $params, true); + + return Resource\Permission::constructFromResponse($response); + } + + /** + * Delete a Permission. + * + * @param string $slug The slug of the Permission to delete + * + * @throws Exception\WorkOSException + * + * @return array + */ + public function deletePermission(string $slug) + { + $path = "authorization/permissions/{$slug}"; + + $response = Client::request(Client::METHOD_DELETE, $path, null, null, true); + + return $response; + } +} diff --git a/lib/RequestClient/CurlRequestClient.php b/lib/RequestClient/CurlRequestClient.php index b5b9115e..581249df 100644 --- a/lib/RequestClient/CurlRequestClient.php +++ b/lib/RequestClient/CurlRequestClient.php @@ -71,6 +71,15 @@ public function request($method, $url, ?array $headers = null, ?array $params = } break; + + case Client::METHOD_PATCH: + \array_push($headers, "Content-Type: application/json"); + $opts[\CURLOPT_CUSTOMREQUEST] = 'PATCH'; + $opts[\CURLOPT_POST] = 1; + if (!empty($params)) { + $opts[\CURLOPT_POSTFIELDS] = \json_encode($params); + } + break; } $opts[\CURLOPT_HTTPHEADER] = $headers; diff --git a/lib/Resource/Permission.php b/lib/Resource/Permission.php new file mode 100644 index 00000000..9083096c --- /dev/null +++ b/lib/Resource/Permission.php @@ -0,0 +1,43 @@ + "id", + "slug" => "slug", + "name" => "name", + "description" => "description", + "resource_type_slug" => "resource_type_slug", + "system" => "system", + "created_at" => "created_at", + "updated_at" => "updated_at" + ]; +} diff --git a/tests/WorkOS/RBACTest.php b/tests/WorkOS/RBACTest.php new file mode 100644 index 00000000..d849035c --- /dev/null +++ b/tests/WorkOS/RBACTest.php @@ -0,0 +1,194 @@ +traitSetUp(); + + $this->withApiKey(); + $this->rbac = new RBAC(); + } + + public function testCreatePermission() + { + $path = "authorization/permissions"; + + $result = $this->permissionResponseFixture(); + + $params = [ + "slug" => "posts:read", + "name" => "Read Posts", + "description" => "Allows reading posts", + ]; + + $this->mockRequest( + Client::METHOD_POST, + $path, + null, + $params, + true, + $result + ); + + $permission = $this->permissionFixture(); + + $response = $this->rbac->createPermission("posts:read", "Read Posts", "Allows reading posts"); + $this->assertSame($permission, $response->toArray()); + } + + public function testListPermissions() + { + $path = "authorization/permissions"; + + $result = $this->permissionsListResponseFixture(); + + $params = [ + "limit" => RBAC::DEFAULT_PAGE_SIZE, + "before" => null, + "after" => null, + "order" => null, + ]; + + $this->mockRequest( + Client::METHOD_GET, + $path, + null, + $params, + true, + $result + ); + + $permission = $this->permissionFixture(); + + list($before, $after, $permissions) = $this->rbac->listPermissions(); + $this->assertSame($permission, $permissions[0]->toArray()); + } + + public function testGetPermission() + { + $path = "authorization/permissions/posts:read"; + + $result = $this->permissionResponseFixture(); + + $this->mockRequest( + Client::METHOD_GET, + $path, + null, + null, + true, + $result + ); + + $permission = $this->permissionFixture(); + + $response = $this->rbac->getPermission("posts:read"); + $this->assertSame($permission, $response->toArray()); + } + + public function testUpdatePermission() + { + $path = "authorization/permissions/posts:read"; + + $result = $this->permissionResponseFixture(); + + $params = [ + "name" => "Read Posts Updated", + ]; + + $this->mockRequest( + Client::METHOD_PATCH, + $path, + null, + $params, + true, + $result + ); + + $permission = $this->permissionFixture(); + + $response = $this->rbac->updatePermission("posts:read", "Read Posts Updated"); + $this->assertSame($permission, $response->toArray()); + } + + public function testDeletePermission() + { + $path = "authorization/permissions/posts:read"; + + $this->mockRequest( + Client::METHOD_DELETE, + $path, + null, + null, + true + ); + + $response = $this->rbac->deletePermission("posts:read"); + $this->assertSame([], $response); + } + + // Fixtures + + private function permissionResponseFixture() + { + return json_encode([ + "object" => "permission", + "id" => "perm_01EHQMYV6MBK39QC5PZXHY59C3", + "slug" => "posts:read", + "name" => "Read Posts", + "description" => "Allows reading posts", + "resource_type_slug" => "organization", + "system" => false, + "created_at" => "2024-01-01T00:00:00.000Z", + "updated_at" => "2024-01-01T00:00:00.000Z" + ]); + } + + private function permissionsListResponseFixture() + { + return json_encode([ + "object" => "list", + "data" => [ + [ + "object" => "permission", + "id" => "perm_01EHQMYV6MBK39QC5PZXHY59C3", + "slug" => "posts:read", + "name" => "Read Posts", + "description" => "Allows reading posts", + "resource_type_slug" => "organization", + "system" => false, + "created_at" => "2024-01-01T00:00:00.000Z", + "updated_at" => "2024-01-01T00:00:00.000Z" + ] + ], + "list_metadata" => [ + "before" => null, + "after" => null + ] + ]); + } + + private function permissionFixture() + { + return [ + "id" => "perm_01EHQMYV6MBK39QC5PZXHY59C3", + "slug" => "posts:read", + "name" => "Read Posts", + "description" => "Allows reading posts", + "resource_type_slug" => "organization", + "system" => false, + "created_at" => "2024-01-01T00:00:00.000Z", + "updated_at" => "2024-01-01T00:00:00.000Z" + ]; + } +}