Skip to content

Add form post signature #58

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,20 @@ some cases, to learn more about this, please refer to [OpenStack's Last Note on
To learn more about segmented uploads for large objects, please refer to:
- [OVH's Optimizing Large Object Uploads Documentation](https://docs.ovh.com/gb/en/storage/optimised_method_for_uploading_files_to_object_storage/)
- [OpenStack's Large Object Support Documentation](https://docs.openstack.org/swift/latest/overview_large_objects.html)
## Form Post Middleware

While this feature in not documented by the OVH team, it's explained in the openstack [documentation](https://docs.openstack.org/swift/latest/api/form_post_middleware.html). This setup allows for uploading of files _directly_ to the OVH servers rather than going through the application servers (which is quite inefficient).

The signature can be obtained by using the following command:
```php
Storage::disk('ovh')->getAdapter()->getFormPostSignature('path', time() + 600, 1, 50*1024*1024)
```
The above example will generate a signature which is valid of 600 seconds, allows for 1 file to be uploaded with a maximum size of 50 MB. Parameters can be tweaked as desired.

The upload form can then use this signature as described in the openstack documentation.

Important note:- The upload method in the form _must_ be of the type POST.


# Credits
- ThePHPLeague for the awesome [Flysystem](https://github.com/thephpleague/flysystem)!
Expand Down
35 changes: 33 additions & 2 deletions src/OVHSwiftAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Sausin\LaravelOvh;

use DateTimeInterface;
use League\Flysystem\Config;
use Nimbusoft\Flysystem\OpenStack\SwiftAdapter;
use OpenStack\Common\Error\BadResponseError;
Expand Down Expand Up @@ -91,11 +92,11 @@ public function getUrlConfirm($path): string
* @param array $options
* @return string
*/
public function getTemporaryUrl(string $path, \DateTimeInterface $expiresAt, array $options = []): string
public function getTemporaryUrl(string $path, DateTimeInterface $expiresAt, array $options = []): string
{
// Ensure Temp URL Key is provided for the Disk
if (empty($this->config->getTempUrlKey())) {
throw new \InvalidArgumentException('No Temp URL Key provided for container \''.$this->container->name.'\'');
throw new \InvalidArgumentException("No Temp URL Key provided for container '".$this->container->name."'");
}

// Ensure $path doesn't begin with a slash
Expand Down Expand Up @@ -127,6 +128,36 @@ public function getTemporaryUrl(string $path, \DateTimeInterface $expiresAt, arr
);
}

public function getFormPostSignature(string $path, DateTimeInterface $expiresAt, string $redirect = '', int $maxFileCount = 1, int $maxFileSize = 26214400): string
{
// Ensure Temp URL Key is provided for the Disk
if (empty($this->config->getTempUrlKey())) {
throw new \InvalidArgumentException("No Temp URL Key provided for container '".$this->container->name."'");
}

// check if the 'expires' values is in the past
if (($expiresAt->getTimestamp() ?? 0) < time()) {
throw new \InvalidArgumentException("Value of 'expires' cannot be in the past");
}

// Ensure $path doesn't begin with a slash
$path = ltrim($path, '/');

// The url on the OVH host
$codePath = sprintf(
'/v1/AUTH_%s/%s/%s',
$this->config->getProjectId(),
$this->config->getContainerName(),
$path
);

// Body for the HMAC hash
$body = sprintf("%s\n%s\n%s\n%s\n%s", $codePath, $redirect, $maxFileSize, $maxFileCount, $expiresAt->getTimestamp());

// The actual hash signature
return hash_hmac('sha1', $body, $this->config->getTempUrlKey());
}

/**
* Expose the container to allow for modification to metadata.
*
Expand Down
11 changes: 11 additions & 0 deletions tests/Functional/UrlGenerationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ public function testCanGenerateTemporaryUrl()
$this->assertNotNull($url);
}

public function testCanGenerateFormPostSignature()
{
$this->config->setTempUrlKey('my-key');

$this->object->shouldNotReceive('retrieve', 'getObject');

$signature = $this->adapter->getFormPostSignature('/prefix', now()->addSeconds(60));

$this->assertNotNull($signature);
}

public function testCanGenerateTemporaryUrlOnCustomEndpoint()
{
$this->config
Expand Down