diff --git a/lib/Organizations.php b/lib/Organizations.php index 283be2e..93d63f8 100644 --- a/lib/Organizations.php +++ b/lib/Organizations.php @@ -250,4 +250,49 @@ public function listOrganizationRoles($organizationId) return [$roles]; } + + /** + * List feature flags for an organization. + * + * @param string $organizationId WorkOS organization ID to fetch feature flags for + * @param int $limit Maximum number of records to return + * @param null|string $before FeatureFlag ID to look before + * @param null|string $after FeatureFlag ID to look after + * @param Resource\Order $order The Order in which to paginate records + * + * @throws Exception\WorkOSException + * + * @return array{?string, ?string, Resource\FeatureFlag[]} An array containing the FeatureFlag ID to use as before and after cursor, and an array of FeatureFlag instances + */ + public function listOrganizationFeatureFlags( + $organizationId, + $limit = self::DEFAULT_PAGE_SIZE, + $before = null, + $after = null, + $order = null + ) { + $featureFlagsPath = "organizations/{$organizationId}/feature-flags"; + $params = [ + "limit" => $limit, + "before" => $before, + "after" => $after, + "order" => $order + ]; + + $response = Client::request( + Client::METHOD_GET, + $featureFlagsPath, + null, + $params, + true + ); + + $featureFlags = []; + list($before, $after) = Util\Request::parsePaginationArgs($response); + foreach ($response["data"] as $responseData) { + \array_push($featureFlags, Resource\FeatureFlag::constructFromResponse($responseData)); + } + + return [$before, $after, $featureFlags]; + } } diff --git a/lib/Resource/FeatureFlag.php b/lib/Resource/FeatureFlag.php new file mode 100644 index 0000000..8c58a7c --- /dev/null +++ b/lib/Resource/FeatureFlag.php @@ -0,0 +1,37 @@ + "id", + "slug" => "slug", + "name" => "name", + "description" => "description", + "created_at" => "createdAt", + "updated_at" => "updatedAt" + ]; +} diff --git a/lib/Resource/VaultObject.php b/lib/Resource/VaultObject.php new file mode 100644 index 0000000..ed18919 --- /dev/null +++ b/lib/Resource/VaultObject.php @@ -0,0 +1,27 @@ + "id", + "name" => "name", + "updated_at" => "updatedAt", + "value" => "value", + "metadata" => "metadata" + ]; +} diff --git a/lib/Vault.php b/lib/Vault.php new file mode 100644 index 0000000..2f4fd50 --- /dev/null +++ b/lib/Vault.php @@ -0,0 +1,78 @@ + $limit, + "before" => $before, + "after" => $after, + "order" => $order + ]; + + $response = Client::request( + Client::METHOD_GET, + $vaultObjectsPath, + null, + $params, + true + ); + + $vaultObjects = []; + list($before, $after) = Util\Request::parsePaginationArgs($response); + foreach ($response["data"] as $responseData) { + \array_push($vaultObjects, Resource\VaultObject::constructFromResponse($responseData)); + } + + return [$before, $after, $vaultObjects]; + } + + + + +} diff --git a/tests/WorkOS/OrganizationsTest.php b/tests/WorkOS/OrganizationsTest.php index 200cc11..6826798 100644 --- a/tests/WorkOS/OrganizationsTest.php +++ b/tests/WorkOS/OrganizationsTest.php @@ -10,6 +10,11 @@ class OrganizationsTest extends TestCase setUp as protected traitSetUp; } + /** + * @var Organizations + */ + protected $organizations; + protected function setUp(): void { $this->traitSetUp(); @@ -190,6 +195,34 @@ public function testListOrganizationRoles() $this->assertSame($role, $roles[0]->toArray()); } + public function testListOrganizationFeatureFlags() + { + $featureFlagsPath = "organizations/org_01EHQMYV6MBK39QC5PZXHY59C3/feature-flags"; + + $result = $this->featureFlagsResponseFixture(); + + $params = [ + "limit" => 10, + "before" => null, + "after" => null, + "order" => null + ]; + + $this->mockRequest( + Client::METHOD_GET, + $featureFlagsPath, + null, + $params, + true, + $result + ); + + $featureFlag = $this->featureFlagFixture(); + + list($before, $after, $featureFlags) = $this->organizations->listOrganizationFeatureFlags("org_01EHQMYV6MBK39QC5PZXHY59C3"); + $this->assertSame($featureFlag, $featureFlags[0]->toArray()); + } + // Fixtures private function createOrganizationResponseFixture() @@ -342,4 +375,56 @@ private function roleFixture() "updated_at" => "2024-01-01T00:00:00.000Z" ]; } + + private function featureFlagFixture() + { + return [ + "id" => "flag_01K2QR5YSWRB8J7GGAG05Y24HQ", + "slug" => "flag3", + "name" => "Flag3", + "description" => "", + "createdAt" => "2025-08-15T20:54:13.561Z", + "updatedAt" => "2025-08-15T20:54:13.561Z" + ]; + } + + private function featureFlagsResponseFixture() + { + return json_encode([ + "object" => "list", + "data" => [ + [ + "object" => "feature_flag", + "id" => "flag_01K2QR5YSWRB8J7GGAG05Y24HQ", + "slug" => "flag3", + "name" => "Flag3", + "description" => "", + "created_at" => "2025-08-15T20:54:13.561Z", + "updated_at" => "2025-08-15T20:54:13.561Z" + ], + [ + "object" => "feature_flag", + "id" => "flag_01K2QR5HGK2HQVFDZ4T60GWGVD", + "slug" => "flag2", + "name" => "Flag2", + "description" => "", + "created_at" => "2025-08-15T20:53:59.952Z", + "updated_at" => "2025-08-15T20:53:59.952Z" + ], + [ + "object" => "feature_flag", + "id" => "flag_01K2QKSH38RF4P9FV917PE24R3", + "slug" => "flag1", + "name" => "Flag1", + "description" => "", + "created_at" => "2025-08-15T19:37:32.005Z", + "updated_at" => "2025-08-15T19:37:32.005Z" + ], + ], + "list_metadata" => [ + "before" => "", + "after" => "" + ] + ]); + } } diff --git a/tests/WorkOS/VaultTest.php b/tests/WorkOS/VaultTest.php new file mode 100644 index 0000000..2b3e00d --- /dev/null +++ b/tests/WorkOS/VaultTest.php @@ -0,0 +1,139 @@ +traitSetUp(); + + $this->withApiKey(); + $this->vault = new Vault(); + } + + public function testGetVaultObject() + { + $vaultObjectPath = "vault/v1/kv/vault_obj_01EHQMYV6MBK39QC5PZXHY59C3"; + + $result = $this->vaultObjectResponseFixture(); + + $this->mockRequest( + Client::METHOD_GET, + $vaultObjectPath, + null, + null, + true, + $result + ); + + $vaultObject = $this->vaultObjectFixture(); + + $response = $this->vault->getVaultObject("vault_obj_01EHQMYV6MBK39QC5PZXHY59C3"); + $this->assertSame($vaultObject, $response->toArray()); + } + + public function testListVaultObjects() + { + $vaultObjectsPath = "vault/v1/kv"; + + $result = $this->vaultObjectsResponseFixture(); + + $params = [ + "limit" => 10, + "before" => null, + "after" => null, + "order" => null + ]; + + $this->mockRequest( + Client::METHOD_GET, + $vaultObjectsPath, + null, + $params, + true, + $result + ); + + $vaultObjects = $this->vaultObjectsFixture(); + + list($before, $after, $response) = $this->vault->listVaultObjects(); + $this->assertSame($vaultObjects, $response[0]->toArray()); + } + + + + + + + + // Fixtures + + private function vaultObjectResponseFixture() + { + return json_encode([ + "id" => "vault_obj_01EHQMYV6MBK39QC5PZXHY59C3", + "name" => "Test Vault Object", + "updated_at" => "2024-01-01T00:00:00.000Z", + "value" => null, + "metadata" => [] + ]); + } + + private function vaultObjectFixture() + { + return [ + "id" => "vault_obj_01EHQMYV6MBK39QC5PZXHY59C3", + "name" => "Test Vault Object", + "updatedAt" => "2024-01-01T00:00:00.000Z", + "value" => null, + "metadata" => [] + ]; + } + + private function vaultObjectsResponseFixture() + { + return json_encode([ + "object" => "list", + "data" => [ + [ + "id" => "vault_obj_01EHQMYV6MBK39QC5PZXHY59C3", + "name" => "Test Vault Object", + "updated_at" => "2024-01-01T00:00:00.000Z", + "value" => null, + "metadata" => [] + ] + ], + "list_metadata" => [ + "before" => null, + "after" => null + ] + ]); + } + + private function vaultObjectsFixture() + { + return [ + "id" => "vault_obj_01EHQMYV6MBK39QC5PZXHY59C3", + "name" => "Test Vault Object", + "updatedAt" => "2024-01-01T00:00:00.000Z", + "value" => null, + "metadata" => [] + ]; + } + + + + +}