Skip to content

Commit

Permalink
Merge pull request #112 from packbackbooks/logging
Browse files Browse the repository at this point in the history
Add the ability to mask log data
  • Loading branch information
dbhynds authored Nov 27, 2023
2 parents 3ddfb3e + e1f1aee commit 8ca7783
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
37 changes: 32 additions & 5 deletions src/LtiServiceConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public function getAccessToken(ILtiRegistration $registration, array $scopes)
$registration->getAuthTokenUrl(),
ServiceRequest::TYPE_AUTH
);
$request->setPayload(['form_params' => $authRequest]);
$request->setPayload(['form_params' => $authRequest])
->setMaskResponseLogs(true);
$response = $this->makeRequest($request);

$tokenData = $this->getResponseBody($response);
Expand Down Expand Up @@ -177,11 +178,16 @@ public function getAll(
return $results;
}

private function logRequest(
public static function getLogMessage(
IServiceRequest $request,
array $responseHeaders,
?array $responseBody
): void {
): string {
if ($request->getMaskResponseLogs()) {
$responseHeaders = static::maskValues($responseHeaders);
$responseBody = static::maskValues($responseBody);
}

$contextArray = [
'request_method' => $request->getMethod(),
'request_url' => $request->getUrl(),
Expand All @@ -195,11 +201,32 @@ private function logRequest(
$contextArray['request_body'] = $requestBody;
}

error_log(implode(' ', array_filter([
return implode(' ', array_filter([
$request->getErrorPrefix(),
json_decode($requestBody)->userId ?? null,
print_r($contextArray, true),
])));
]));
}

private function logRequest(
IServiceRequest $request,
array $responseHeaders,
?array $responseBody
): void {
error_log(static::getLogMessage($request, $responseHeaders, $responseBody));
}

private static function maskValues(?array $payload)
{
if (!isset($payload) || empty($payload)) {
return $payload;
}

foreach ($payload as $key => $value) {
$payload[$key] = '***';
}

return $payload;
}

private function getAccessTokenCacheKey(ILtiRegistration $registration, array $scopes)
Expand Down
15 changes: 15 additions & 0 deletions src/ServiceRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class ServiceRequest implements IServiceRequest
private $contentType = 'application/json';
private $accept = 'application/json';

// Other
private $maskResponseLogs = false;

public function __construct(string $method, string $url, $type = self::UNSUPPORTED)
{
$this->method = $method;
Expand Down Expand Up @@ -120,6 +123,18 @@ public function setContentType(string $contentType): IServiceRequest
return $this;
}

public function getMaskResponseLogs(): bool
{
return $this->maskResponseLogs;
}

public function setMaskResponseLogs(bool $shouldMask): IServiceRequest
{
$this->maskResponseLogs = $shouldMask;

return $this;
}

public function getErrorPrefix(): string
{
$defaultMessage = 'Logging request data:';
Expand Down
30 changes: 30 additions & 0 deletions tests/LtiServiceConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,36 @@ public function testItGetsAll()
$this->assertEquals($expected, $result);
}

public function testItBuildsLogMessage()
{
$this->mockMakeRequest();
$this->request->shouldReceive('getErrorPrefix')
->once()->andReturn('Logging request data:');
$this->request->shouldReceive('getMaskResponseLogs')
->once()->andReturn(false);

$result = $this->connector::getLogMessage($this->request, ['foo' => 'bar'], ['baz' => 'bat']);

$expected = "Logging request data: id Array\n(\n [request_method] => POST\n [request_url] => https://example.com\n [response_headers] => Array\n (\n [foo] => bar\n )\n\n [response_body] => {\"baz\":\"bat\"}\n [request_body] => {\"userId\":\"id\"}\n)\n";

$this->assertEquals($expected, $result);
}

public function testItMasksSensitiveDataInLogMessage()
{
$this->mockMakeRequest();
$this->request->shouldReceive('getErrorPrefix')
->once()->andReturn('Logging request data:');
$this->request->shouldReceive('getMaskResponseLogs')
->once()->andReturn(true);

$result = $this->connector::getLogMessage($this->request, ['foo' => 'bar'], ['baz' => 'bat']);

$expected = "Logging request data: id Array\n(\n [request_method] => POST\n [request_url] => https://example.com\n [response_headers] => Array\n (\n [foo] => ***\n )\n\n [response_body] => {\"baz\":\"***\"}\n [request_body] => {\"userId\":\"id\"}\n)\n";

$this->assertEquals($expected, $result);
}

private function mockMakeRequest()
{
// It makes another request
Expand Down

0 comments on commit 8ca7783

Please sign in to comment.