Skip to content

Commit 317873c

Browse files
committed
Added support for schema creation and existance checking
1 parent 6fcfacd commit 317873c

File tree

2 files changed

+329
-0
lines changed

2 files changed

+329
-0
lines changed

lib/AuditLogs.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,110 @@ public function createExport($organizationId, $rangeStart, $rangeEnd, $actions =
115115
* @param string $auditLogExportId Unique identifier of the Audit Log Export
116116
*
117117
* @throws Exception\WorkOSException
118+
* @throws \InvalidArgumentException
118119
*
119120
* @return Resource\AuditLogExport
120121
*/
121122
public function getExport($auditLogExportId)
122123
{
124+
// Validate export ID parameter to prevent path traversal
125+
if (!is_string($auditLogExportId) || !preg_match('/^[a-zA-Z0-9._-]+$/', $auditLogExportId)) {
126+
throw new \InvalidArgumentException('Invalid export ID format. Export ID must be a string containing only alphanumeric characters, dots, underscores, and hyphens.');
127+
}
128+
123129
$getExportPath = "audit_logs/exports/{$auditLogExportId}";
124130

125131
$response = Client::request(Client::METHOD_GET, $getExportPath, null, null, true);
126132

127133
return Resource\AuditLogExport::constructFromResponse($response);
128134
}
135+
136+
/**
137+
* Create an audit log action schema.
138+
*
139+
* @param string $action The action name for the schema
140+
* @param array $schema Array containing the schema definition
141+
*
142+
* @throws Exception\WorkOSException
143+
* @throws \InvalidArgumentException
144+
*
145+
* @return array The created schema response
146+
*/
147+
public function createSchema($action, $schema)
148+
{
149+
// Validate action parameter to prevent path traversal
150+
if (!is_string($action) || !preg_match('/^[a-zA-Z0-9._-]+$/', $action)) {
151+
throw new \InvalidArgumentException('Invalid action format. Action must be a string containing only alphanumeric characters, dots, underscores, and hyphens.');
152+
}
153+
154+
$schemaPath = "audit_logs/actions/{$action}/schemas";
155+
156+
$response = Client::request(Client::METHOD_POST, $schemaPath, null, $schema, true);
157+
158+
return $response;
159+
}
160+
161+
/**
162+
* Check if an audit log action schema exists.
163+
*
164+
* @param string $action The action name to check
165+
*
166+
* @throws Exception\WorkOSException
167+
* @throws \InvalidArgumentException
168+
*
169+
* @return bool True if schema exists, false if not found
170+
*/
171+
public function schemaExists($action)
172+
{
173+
// Validate action parameter to prevent path traversal
174+
if (!is_string($action) || !preg_match('/^[a-zA-Z0-9._-]+$/', $action)) {
175+
throw new \InvalidArgumentException('Invalid action format. Action must be a string containing only alphanumeric characters, dots, underscores, and hyphens.');
176+
}
177+
178+
$schemaPath = "audit_logs/actions/{$action}/schemas";
179+
180+
try {
181+
Client::request(Client::METHOD_GET, $schemaPath, null, null, true);
182+
return true;
183+
} catch (Exception\NotFoundException $e) {
184+
return false;
185+
}
186+
}
187+
188+
/**
189+
* List all registered audit log actions.
190+
*
191+
* @param int $limit Maximum number of actions to return (default: 100)
192+
* @param null|string $before Action ID to look before
193+
* @param null|string $after Action ID to look after
194+
* @param null|string $order The order in which to paginate records ("asc" or "desc")
195+
*
196+
* @throws Exception\WorkOSException
197+
*
198+
* @return array Array of registered actions
199+
*/
200+
public function listActions($limit = 100, $before = null, $after = null, $order = null)
201+
{
202+
$actionsPath = "audit_logs/actions";
203+
204+
$params = [
205+
"limit" => $limit
206+
];
207+
208+
if ($before !== null) {
209+
$params["before"] = $before;
210+
}
211+
212+
if ($after !== null) {
213+
$params["after"] = $after;
214+
}
215+
216+
if ($order !== null) {
217+
$params["order"] = $order;
218+
}
219+
220+
$response = Client::request(Client::METHOD_GET, $actionsPath, null, $params, true);
221+
222+
return $response;
223+
}
129224
}

tests/WorkOS/AuditLogsTest.php

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,136 @@ public function testGetExport()
133133

134134
$this->assertSame($getExportFixture, $auditLogGetExport->toArray());
135135
}
136+
137+
public function testCreateSchema()
138+
{
139+
$path = "audit_logs/actions/document.updated/schemas";
140+
141+
$action = "document.updated";
142+
$schema = [
143+
"targets" => [
144+
[
145+
"type" => "document"
146+
],
147+
[
148+
"type" => "user"
149+
]
150+
]
151+
];
152+
153+
$params = $schema;
154+
155+
$result = $this->createSchemaResponseFixture();
156+
157+
$this->mockRequest(
158+
Client::METHOD_POST,
159+
$path,
160+
null,
161+
$params,
162+
true,
163+
$result
164+
);
165+
166+
$response = $this->al->createSchema($action, $schema);
167+
$schemaFixture = $this->createSchemaFixture();
168+
169+
$this->assertSame($schemaFixture, $response);
170+
}
171+
172+
public function testSchemaExists()
173+
{
174+
$path = "audit_logs/actions/document.updated/schemas";
175+
$action = "document.updated";
176+
177+
$result = $this->schemaExistsResponseFixture();
178+
179+
$this->mockRequest(
180+
Client::METHOD_GET,
181+
$path,
182+
null,
183+
null,
184+
true,
185+
$result
186+
);
187+
188+
$exists = $this->al->schemaExists($action);
189+
190+
$this->assertTrue($exists);
191+
}
192+
193+
public function testSchemaExistsNotFound()
194+
{
195+
$path = "audit_logs/actions/nonexistent.action/schemas";
196+
$action = "nonexistent.action";
197+
198+
$this->mockRequest(
199+
Client::METHOD_GET,
200+
$path,
201+
null,
202+
null,
203+
true,
204+
null,
205+
null,
206+
404
207+
);
208+
209+
$exists = $this->al->schemaExists($action);
210+
211+
$this->assertFalse($exists);
212+
}
213+
214+
public function testListActions()
215+
{
216+
$path = "audit_logs/actions";
217+
218+
$params = [
219+
"limit" => 100
220+
];
221+
222+
$result = $this->listActionsResponseFixture();
223+
224+
$this->mockRequest(
225+
Client::METHOD_GET,
226+
$path,
227+
null,
228+
$params,
229+
true,
230+
$result
231+
);
232+
233+
$response = $this->al->listActions();
234+
$actionsFixture = $this->listActionsFixture();
235+
236+
$this->assertSame($actionsFixture, $response);
237+
}
238+
239+
public function testListActionsWithPagination()
240+
{
241+
$path = "audit_logs/actions";
242+
243+
$params = [
244+
"limit" => 50,
245+
"before" => "action_123",
246+
"after" => "action_456",
247+
"order" => "desc"
248+
];
249+
250+
$result = $this->listActionsResponseFixture();
251+
252+
$this->mockRequest(
253+
Client::METHOD_GET,
254+
$path,
255+
null,
256+
$params,
257+
true,
258+
$result
259+
);
260+
261+
$response = $this->al->listActions(50, "action_123", "action_456", "desc");
262+
$actionsFixture = $this->listActionsFixture();
263+
264+
$this->assertSame($actionsFixture, $response);
265+
}
136266
// Fixtures
137267

138268
private function createEventFixture()
@@ -196,4 +326,108 @@ private function getExportResponseFixture()
196326
"updated_at" => "2022-08-18T18:07:10.822Z",
197327
]);
198328
}
329+
330+
private function createSchemaFixture()
331+
{
332+
return [
333+
"object" => "audit_log_schema",
334+
"id" => "schema_123",
335+
"action" => "document.updated",
336+
"targets" => [
337+
["type" => "document"],
338+
["type" => "user"]
339+
],
340+
"created_at" => "2022-08-18T18:07:10.822Z",
341+
"updated_at" => "2022-08-18T18:07:10.822Z",
342+
];
343+
}
344+
345+
private function createSchemaResponseFixture()
346+
{
347+
return json_encode([
348+
"object" => "audit_log_schema",
349+
"id" => "schema_123",
350+
"action" => "document.updated",
351+
"targets" => [
352+
["type" => "document"],
353+
["type" => "user"]
354+
],
355+
"created_at" => "2022-08-18T18:07:10.822Z",
356+
"updated_at" => "2022-08-18T18:07:10.822Z",
357+
]);
358+
}
359+
360+
private function schemaExistsResponseFixture()
361+
{
362+
return json_encode([
363+
"object" => "audit_log_schema",
364+
"id" => "schema_123",
365+
"action" => "document.updated",
366+
"targets" => [
367+
["type" => "document"]
368+
],
369+
"created_at" => "2022-08-18T18:07:10.822Z",
370+
"updated_at" => "2022-08-18T18:07:10.822Z",
371+
]);
372+
}
373+
374+
private function listActionsFixture()
375+
{
376+
return [
377+
"object" => "list",
378+
"data" => [
379+
[
380+
"object" => "audit_log_action",
381+
"id" => "action_123",
382+
"name" => "document.updated",
383+
"description" => "Document was updated",
384+
"created_at" => "2022-08-18T18:07:10.822Z",
385+
"updated_at" => "2022-08-18T18:07:10.822Z",
386+
],
387+
[
388+
"object" => "audit_log_action",
389+
"id" => "action_456",
390+
"name" => "user.created",
391+
"description" => "User was created",
392+
"created_at" => "2022-08-18T18:07:10.822Z",
393+
"updated_at" => "2022-08-18T18:07:10.822Z",
394+
]
395+
],
396+
"list_metadata" => [
397+
"before" => null,
398+
"after" => "action_456",
399+
"limit" => 100
400+
]
401+
];
402+
}
403+
404+
private function listActionsResponseFixture()
405+
{
406+
return json_encode([
407+
"object" => "list",
408+
"data" => [
409+
[
410+
"object" => "audit_log_action",
411+
"id" => "action_123",
412+
"name" => "document.updated",
413+
"description" => "Document was updated",
414+
"created_at" => "2022-08-18T18:07:10.822Z",
415+
"updated_at" => "2022-08-18T18:07:10.822Z",
416+
],
417+
[
418+
"object" => "audit_log_action",
419+
"id" => "action_456",
420+
"name" => "user.created",
421+
"description" => "User was created",
422+
"created_at" => "2022-08-18T18:07:10.822Z",
423+
"updated_at" => "2022-08-18T18:07:10.822Z",
424+
]
425+
],
426+
"list_metadata" => [
427+
"before" => null,
428+
"after" => "action_456",
429+
"limit" => 100
430+
]
431+
]);
432+
}
199433
}

0 commit comments

Comments
 (0)