-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1236 from nupplaphil/feat/s3
Add S3 Storage Backend
- Loading branch information
Showing
63 changed files
with
8,107 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "friendica-addons/s3_storage", | ||
"description": "Adds the possibility to use S3 as a selectable storage backend", | ||
"type": "friendica-addon", | ||
"authors": [ | ||
{ | ||
"name": "Philipp Holzer", | ||
"email": "[email protected]", | ||
"homepage": "https://blog.philipp.info", | ||
"role": "Developer" | ||
} | ||
], | ||
"require": { | ||
"php": ">=7.0", | ||
"akeeba/s3": "^2.0" | ||
}, | ||
"license": "3-clause BSD license", | ||
"config": { | ||
"optimize-autoloader": true, | ||
"autoloader-suffix": "S3StorageAddon", | ||
"preferred-install": "dist" | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# ADDON s3_storage | ||
# Copyright (C) | ||
# This file is distributed under the same license as the Friendica s3_storage addon package. | ||
# | ||
# | ||
#, fuzzy | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: \n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2022-02-24 23:25+0100\n" | ||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||
"Language-Team: LANGUAGE <[email protected]>\n" | ||
"Language: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: 8bit\n" | ||
|
||
#: src/S3Config.php:113 | ||
msgid "Access Key" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:115 | ||
msgid "Set the Access Key of the S3 storage" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:120 | ||
msgid "Secret Key" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:122 | ||
msgid "Set the Secret Key of the S3 storage" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:127 | ||
msgid "Bucket" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:129 | ||
msgid "The S3 Bucket (name), you want to use with Friendica" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:134 | ||
msgid "Signature Method" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:136 | ||
msgid "" | ||
"Set the signature method to use (BEWARE: v4 will be automatically set to v2 " | ||
"in case the endpoint isn't amazon)" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:141 | ||
#, php-format | ||
msgid "Amazon S3 compatible endpoint (leave empty for '%s')" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:143 | ||
msgid "" | ||
"Set the S3 endpoint. Do NOT use a protocol (You can use a custom endpoint " | ||
"with v2 signatures to access third party services which offer S3 " | ||
"compatibility, e.g. OwnCloud, Google Storage etc.)" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:147 | ||
#, php-format | ||
msgid "AWS region (leave empty for '%s')" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:149 | ||
msgid "The AWS region is mandatory for v4 signatures" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:153 | ||
msgid "Use the dualstack URL (which will ship traffic over ipv6 in most cases)" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:155 | ||
msgid "" | ||
"For more information on these endpoints please read https://docs.aws.amazon." | ||
"com/AmazonS3/latest/dev/dual-stack-endpoints.html" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:159 | ||
msgid "Use legacy, path-style access to the bucket" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:161 | ||
msgid "" | ||
"When it's turned off (default) we use virtual hosting stylepaths which are " | ||
"RECOMMENDED BY AMAZON per http://docs.aws.amazon.com/AmazonS3/latest/API/" | ||
"APIRest.html" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:175 | ||
msgid "Invalid input" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:214 | ||
#, php-format | ||
msgid "error '%s', message '%s'" | ||
msgstr "" | ||
|
||
#: src/S3Config.php:222 | ||
#, php-format | ||
msgid "Bucket %s cannot be not found, possible buckets: %s" | ||
msgstr "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php | ||
/* | ||
* Name: S3 Storage | ||
* Description: Adds the possibility to use Amazon S3 as a selectable storage backend | ||
* Version: 1.0 | ||
* Author: Philipp Holzer | ||
*/ | ||
|
||
use Friendica\Addon\s3_storage\src\S3Client; | ||
use Friendica\Addon\s3_storage\src\S3Config; | ||
use Friendica\App; | ||
use Friendica\Core\Hook; | ||
use Friendica\DI; | ||
|
||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; | ||
|
||
function s3_storage_install($a) | ||
{ | ||
Hook::register('storage_instance' , __FILE__, 's3_storage_instance'); | ||
Hook::register('storage_config' , __FILE__, 's3_storage_config'); | ||
DI::storageManager()->register(S3Client::class); | ||
} | ||
|
||
function s3_storage_uninstall() | ||
{ | ||
DI::storageManager()->unregister(S3Client::class); | ||
} | ||
|
||
function s3_storage_instance(App $a, array &$data) | ||
{ | ||
if ($data['name'] == S3Client::getName()) { | ||
$config = new S3Config(DI::l10n(), DI::config()); | ||
$data['storage'] = new S3Client($config->getConfig(), $config->getBucket()); | ||
} | ||
} | ||
|
||
function s3_storage_config(App $a, array &$data) | ||
{ | ||
if ($data['name'] == S3Client::getName()) { | ||
$data['storage_config'] = new S3Config(DI::l10n(), DI::config()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<?php | ||
|
||
namespace Friendica\Addon\s3_storage\src; | ||
|
||
defined('AKEEBAENGINE') or define('AKEEBAENGINE', 1); | ||
|
||
use Akeeba\Engine\Postproc\Connector\S3v4\Configuration; | ||
use Akeeba\Engine\Postproc\Connector\S3v4\Connector; | ||
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotDeleteFile; | ||
use Akeeba\Engine\Postproc\Connector\S3v4\Input; | ||
use Friendica\Core\Storage\Capability\ICanWriteToStorage; | ||
use Friendica\Core\Storage\Exception\StorageException; | ||
use Friendica\Util\Strings; | ||
|
||
/** | ||
* A WebDav Backend Storage class | ||
*/ | ||
class S3Client implements ICanWriteToStorage | ||
{ | ||
const NAME = 'S3'; | ||
|
||
/** @var Connector */ | ||
protected $connector; | ||
|
||
/** @var string The name of the bucket used for the backend */ | ||
protected $bucket; | ||
|
||
public function __construct(Configuration $config, string $bucket) | ||
{ | ||
$this->connector = new Connector($config); | ||
$this->bucket = $bucket; | ||
} | ||
|
||
/** | ||
* Split data ref and return file path | ||
* | ||
* @param string $reference Data reference | ||
* | ||
* @return string | ||
*/ | ||
private function pathForRef(string $reference): string | ||
{ | ||
$fold1 = substr($reference, 0, 2); | ||
$fold2 = substr($reference, 2, 2); | ||
$file = substr($reference, 4); | ||
|
||
return implode('/', [$fold1, $fold2, $file]); | ||
} | ||
|
||
/** {@inheritDoc} */ | ||
public function __toString(): string | ||
{ | ||
return self::getName(); | ||
} | ||
|
||
/** {@inheritDoc} */ | ||
public static function getName(): string | ||
{ | ||
return self::NAME; | ||
} | ||
|
||
/** {@inheritDoc} */ | ||
public function get(string $reference): string | ||
{ | ||
try { | ||
return $this->connector->getObject($this->bucket, $this->pathForRef($reference), false); | ||
} catch (\RuntimeException $exception) { | ||
throw new StorageException(sprintf('Cannot get reference %s', $reference), $exception->getCode(), $exception); | ||
} | ||
} | ||
|
||
/** {@inheritDoc} */ | ||
public function put(string $data, string $reference = ""): string | ||
{ | ||
if ($reference === '') { | ||
try { | ||
$reference = Strings::getRandomHex(); | ||
} catch (\Exception $exception) { | ||
throw new StorageException('S3 storage failed to generate a random hex', $exception->getCode(), $exception); | ||
} | ||
} | ||
|
||
try { | ||
$input = Input::createFromData($data); | ||
$this->connector->putObject($input, $this->bucket, $this->pathForRef($reference)); | ||
return $reference; | ||
} catch (\Exception $exception) { | ||
throw new StorageException(sprintf('Cannot put data for reference %s', $reference), $exception->getCode(), $exception); | ||
} | ||
} | ||
|
||
/** {@inheritDoc} */ | ||
public function delete(string $reference) | ||
{ | ||
try { | ||
$this->connector->deleteObject($this->bucket, $this->pathForRef($reference)); | ||
} catch (CannotDeleteFile $exception) { | ||
throw new StorageException(sprintf('Cannot delete reference %s', $reference), $exception->getCode(), $exception); | ||
} | ||
} | ||
} |
Oops, something went wrong.