Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
dermatthes committed Jan 30, 2024
1 parent f4df134 commit b2d56fb
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 16 deletions.
29 changes: 23 additions & 6 deletions src/Driver/FileSystemObjectStoreDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use Phore\FileSystem\Exception\PathOutOfBoundsException;
use Phore\FileSystem\PhoreDirectory;
use Phore\FileSystem\PhoreFile;
use Phore\ObjectStore\Encryption\ObjectStoreEncryption;
use Phore\ObjectStore\Encryption\PassThruNoEncryption;
use Phore\ObjectStore\Type\ObjectStoreObject;
use Psr\Http\Message\StreamInterface;

Expand All @@ -29,7 +31,12 @@ class FileSystemObjectStoreDriver implements ObjectStoreDriver
*/
private $rootDir;

public function __construct(string $rootDir)
/**
* @var ObjectStoreEncryption
*/
private $encryption;

public function __construct(string $rootDir, ObjectStoreEncryption $encryption = null)
{
if (!class_exists('\Phore\FileSystem\PhoreDirectory')) {
throw new InvalidArgumentException('PhoreFilesystem is currently not installed. Install phore/filesystem to use FileSystemObjectStoreDriver');
Expand All @@ -39,6 +46,9 @@ public function __construct(string $rootDir)
throw new InvalidArgumentException("Root directory '$rootDir' not accessible");
}
$this->rootDir = phore_dir($rootDirAbs);
$this->encryption = $encryption;
if ($this->encryption === null)
$this->encryption = new PassThruNoEncryption();
}


Expand Down Expand Up @@ -70,7 +80,7 @@ public function put(string $objectId, $content, array $metadata = null)
if (!$dir->isDirectory()) {
$dir->mkdir();
}
$file->set_contents($content);
$file->set_contents($this->encryption->encrypt($content));
if ($metadata !== null) {
$this->rootDir->withSubPath($objectId . self::META_SUFFIX)->asFile()->set_json($metadata);
}
Expand Down Expand Up @@ -109,7 +119,7 @@ public function get(string $objectId, array &$meta = null): string
if (!$file->isFile()) {
throw new NotFoundException("Object '$objectId' not existing.", 0);
}
return $file->get_contents();
return $this->encryption->decrypt($file->get_contents());
}

/**
Expand All @@ -120,6 +130,9 @@ public function get(string $objectId, array &$meta = null): string
*/
public function getStream(string $objectId, array &$meta = null): StreamInterface
{
if ( ! $this->encryption->supportsStreaming())
throw new InvalidArgumentException("Encryption does not support streaming.");

return $this->rootDir->withSubPath($objectId)->asFile()->fopen('r');
}

Expand Down Expand Up @@ -176,11 +189,15 @@ public function append(string $objectId, string $appendData)
{
$targetFile = $this->rootDir->withSubPath($objectId)->asFile();

$data = "";
if ($targetFile->exists()) {
$targetFile->append_content($appendData);
} else {
$targetFile->set_contents($appendData);
$data = $this->encryption->decrypt($targetFile->get_contents());
}

$data .= $appendData;

$targetFile->set_contents($this->encryption->encrypt($appendData));

return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Driver/ObjectStoreDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function has(string $objectId): bool;
* @return mixed
*/
public function put(string $objectId, $content, array $metadata = null);

/**
* @param string $objectId
* @param $resource
Expand Down
25 changes: 19 additions & 6 deletions src/Driver/PhoreGoogleObjectStoreDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Phore\FileSystem\Exception\FileParsingException;
use Phore\FileSystem\PhoreFile;
use Phore\HttpClient\Ex\PhoreHttpRequestException;
use Phore\ObjectStore\Encryption\ObjectStoreEncryption;
use Psr\Http\Message\StreamInterface;


Expand Down Expand Up @@ -51,6 +52,11 @@ class PhoreGoogleObjectStoreDriver implements ObjectStoreDriver
*/
public $retry;

/**
* @var ObjectStoreEncryption
*/
public $encryption;

/**
* PhoreGoogleObjectStoreDriver constructor.
* @param string $configFilePath
Expand All @@ -60,14 +66,18 @@ class PhoreGoogleObjectStoreDriver implements ObjectStoreDriver
* @throws FileParsingException
* @throws PhoreHttpRequestException
*/
public function __construct(string $configFilePath, string $bucketName, bool $retry = false)
public function __construct(string $configFilePath, string $bucketName, bool $retry = false, ObjectStoreEncryption $encryption = null)
{
$this->config = phore_file($configFilePath)->get_json();
$this->bucketName = $bucketName;
$this->base_url .= '/b/' . $bucketName;
$this->retry = $retry;

$this->accessToken = $this->_getJwt()['access_token'];

$this->encryption = $encryption;
if ($this->encryption === null)
$this->encryption = new PassThruNoEncryption();
}

public function setRetries(int $retries)
Expand Down Expand Up @@ -179,7 +189,7 @@ public function put(string $objectId, $content, array $metadata = null)
try {
phore_http_request(self::UPLOAD_URI . '?uploadType=media&name={object}', ['bucket' => $this->bucketName, 'object' => $objectId])
->withBearerAuth($this->accessToken)
->withPostBody($content)->withHeaders(['Content-Type' => $this->_getContentType($objectId)])->send();
->withPostBody($this->encryption->encrypt($content))->withHeaders(['Content-Type' => $this->_getContentType($objectId)])->send();
return true;
} catch (PhoreHttpRequestException $ex) {
if ($this->retry) {
Expand All @@ -197,7 +207,7 @@ public function put(string $objectId, $content, array $metadata = null)
}
$meta = phore_json_encode($meta);
$delimiter = 'delimiter';
$body = "--$delimiter\nContent-Type: application/json; charset=UTF-8\n\n$meta\n\n--$delimiter\nContent-Type: {$this->_getContentType($objectId)}\n\n$content\n--$delimiter--";
$body = "--$delimiter\nContent-Type: application/json; charset=UTF-8\n\n$meta\n\n--$delimiter\nContent-Type: {$this->_getContentType($objectId)}\n\n{$this->encryption->encrypt($content)}\n--$delimiter--";

do {
try {
Expand Down Expand Up @@ -237,8 +247,8 @@ public function get(string $objectId, array &$meta = null): string
$i = 0;
do {
try {
return phore_http_request(self::DOWNLOAD_URI . '?alt=media', ['bucket' => $this->bucketName, 'object' => $objectId])
->withBearerAuth($this->accessToken)->send()->getBody();
return $this->encryption->decrypt(phore_http_request(self::DOWNLOAD_URI . '?alt=media', ['bucket' => $this->bucketName, 'object' => $objectId])
->withBearerAuth($this->accessToken)->send()->getBody());
} catch (PhoreHttpRequestException $ex) {
if ($this->retry) {
$i++;
Expand Down Expand Up @@ -332,6 +342,9 @@ public function rename(string $objectId, string $newObjectId)
*/
public function append(string $objectId, string $data)
{
if ( ! $this->encryption->supportsAppending())
throw new InvalidArgumentException("Streaming is unsupported on this enryption method.");

$meta = $this->getMeta($objectId);
if ($meta === []) {
$this->put($objectId, $data);
Expand Down
16 changes: 16 additions & 0 deletions src/Encryption/ObjectStoreEncryption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Phore\ObjectStore\Encryption;

interface ObjectStoreEncryption
{

public function encrypt(string $data) : string;

public function decrypt(string $data) : string;


public function supportsStreaming() : bool;
public function supportsAppending() : bool;

}
27 changes: 27 additions & 0 deletions src/Encryption/PassThruNoEncryption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Phore\ObjectStore\Encryption;

class PassThruNoEncryption implements ObjectStoreEncryption
{
public function encrypt(string $data): string
{
return $data;
}

public function decrypt(string $data): string
{
return $data;
}

public function supportsAppending(): bool
{
return true;
}

public function supportsStreaming(): bool
{
return true;
}

}
45 changes: 45 additions & 0 deletions src/Encryption/SodiumSyncEncryption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Phore\ObjectStore\Encryption;

class SodiumSyncEncryption implements ObjectStoreEncryption
{
private $key;

public function __construct(string $key)
{
if (strlen($key) !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
throw new \InvalidArgumentException("Key must be exactly " . SODIUM_CRYPTO_SECRETBOX_KEYBYTES . " bytes long");
}
$this->key = $key;
}

public function encrypt(string $data): string
{
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$encrypted = sodium_crypto_secretbox($data, $nonce, $this->key);
return $nonce . $encrypted;
}

public function decrypt(string $data): string
{
$nonce = mb_substr($data, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, "8bit");
$encrypted = mb_substr($data, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, "8bit");
$decrypted = sodium_crypto_secretbox_open($encrypted, $nonce, $this->key);
if ($decrypted === false) {
throw new \InvalidArgumentException("Could not decrypt data");
}
return $decrypted;
}

public function supportsStreaming(): bool
{
return false;
}

public function supportsAppending(): bool
{
return false;
}

}
4 changes: 3 additions & 1 deletion src/ObjectStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ObjectStore
* @var ObjectStoreDriver
*/
private $driver;


/**
* ObjectStore constructor.
Expand All @@ -45,6 +45,7 @@ class ObjectStore
public function __construct(ObjectStoreDriver $objectStoreDriver)
{
$this->driver = $objectStoreDriver;

}

/**
Expand Down Expand Up @@ -131,6 +132,7 @@ public function getDriver(): ObjectStoreDriver
{
return $this->driver;
}


/**
* @param string $objectId
Expand Down
9 changes: 7 additions & 2 deletions src/Type/ObjectStoreObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,21 @@ public function getStream(): StreamInterface
}

/**
* @return array
* @template T
* @param class-string<T> $cast
* @return array|T
* @throws NotFoundException
*/
public function getJson(): array
public function getJson(string $cast = null): array|object
{
$data = $this->get();
$ret = json_decode($data, true);
if ($ret === null) {
throw new \InvalidArgumentException("Cannot json-decode data from object '$this->objectId'");
}
if ($cast !== null) {
$ret = phore_hydrate($ret, $cast);
}
return $ret;
}

Expand Down

0 comments on commit b2d56fb

Please sign in to comment.