Implemented a new option for S3 sources to allow signed URLs and private buckets to be used. #141
This commit is contained in:
parent
93c6f5da10
commit
f773b10244
@ -42,6 +42,11 @@ abstract class AlbumSourceBase
|
||||
return self::$albumSourceCache[$fullClassName];
|
||||
}
|
||||
|
||||
public function getConfiguration()
|
||||
{
|
||||
return $this->configuration;
|
||||
}
|
||||
|
||||
public function setAlbum(Album $album)
|
||||
{
|
||||
$this->album = $album;
|
||||
|
@ -130,7 +130,19 @@ class AmazonS3Source extends AlbumSourceBase implements IAlbumSource, IAnalysisQ
|
||||
*/
|
||||
public function getUrlToPhoto(Photo $photo, $thumbnail = null)
|
||||
{
|
||||
return $this->getClient()->getObjectUrl($this->configuration->container_name, $this->getPathToPhoto($photo, $thumbnail));
|
||||
$client = $this->getClient();
|
||||
|
||||
if ($this->configuration->s3_signed_urls)
|
||||
{
|
||||
$cmd = $client->getCommand('GetObject', [
|
||||
'Bucket' => $this->configuration->container_name,
|
||||
'Key' => $this->getPathToPhoto($photo, $thumbnail)
|
||||
]);
|
||||
|
||||
return $client->createPresignedRequest($cmd, '+5 minutes')->getUri();
|
||||
}
|
||||
|
||||
return $client->getObjectUrl($this->configuration->container_name, $this->getPathToPhoto($photo, $thumbnail));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,7 +156,11 @@ class AmazonS3Source extends AlbumSourceBase implements IAlbumSource, IAnalysisQ
|
||||
{
|
||||
$photoPath = $this->getPathToPhoto($photo, $thumbnail);
|
||||
|
||||
$this->getClient()->upload($this->configuration->container_name, $photoPath, fopen($tempFilename, 'r+'), 'public-read');
|
||||
$uploadAcl = $this->configuration->s3_signed_urls
|
||||
? 'private'
|
||||
: 'public-read';
|
||||
|
||||
$this->getClient()->upload($this->configuration->container_name, $photoPath, fopen($tempFilename, 'r+'), $uploadAcl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,6 @@ use App\Album;
|
||||
use App\Photo;
|
||||
use App\Storage;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
|
||||
interface IAlbumSource
|
||||
{
|
||||
@ -32,6 +31,12 @@ interface IAlbumSource
|
||||
*/
|
||||
function fetchPhotoContent(Photo $photo, $thumbnail = null);
|
||||
|
||||
/**
|
||||
* Gets the configuration of the source.
|
||||
* @return mixed
|
||||
*/
|
||||
function getConfiguration();
|
||||
|
||||
/**
|
||||
* Gets the name of this album source.
|
||||
* @return string
|
||||
|
@ -55,12 +55,14 @@ class StorageController extends Controller
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-storage');
|
||||
|
||||
$filesystemDefaultLocation = sprintf('%s/storage/app/albums', dirname(dirname(dirname(dirname(__DIR__)))));
|
||||
$storage = new Storage();
|
||||
$storage->s3_signed_urls = true;
|
||||
|
||||
return Theme::render('admin.create_storage', [
|
||||
'album_sources' => UserConfig::albumSources(),
|
||||
'filesystem_default_location' => $filesystemDefaultLocation,
|
||||
'info' => $request->session()->get('info'),
|
||||
'storage' => new Storage()
|
||||
'storage' => $storage
|
||||
]);
|
||||
}
|
||||
|
||||
@ -94,6 +96,7 @@ class StorageController extends Controller
|
||||
$storage->is_active = true;
|
||||
$storage->is_default = (strtolower($request->get('is_default')) == 'on');
|
||||
$storage->is_internal = false;
|
||||
$storage->s3_signed_urls = (strtolower($request->get('s3_signed_urls')) == 'on');
|
||||
|
||||
if ($storage->source != 'LocalFilesystemSource' && isset($storage->location))
|
||||
{
|
||||
@ -219,10 +222,12 @@ class StorageController extends Controller
|
||||
'cdn_url',
|
||||
'access_key',
|
||||
'secret_key',
|
||||
'b2_bucket_type'
|
||||
'b2_bucket_type',
|
||||
's3_signed_urls'
|
||||
]));
|
||||
$storage->is_active = (strtolower($request->get('is_active')) == 'on');
|
||||
$storage->is_default = (strtolower($request->get('is_default')) == 'on');
|
||||
$storage->s3_signed_urls = (strtolower($request->get('s3_signed_urls')) == 'on');
|
||||
|
||||
if ($storage->is_default && !$storage->is_active)
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App;
|
||||
|
||||
use App\AlbumSources\IAlbumSource;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
@ -110,9 +111,14 @@ class Photo extends Model
|
||||
|
||||
public function thumbnailUrl($thumbnailName = null, $cacheBust = true)
|
||||
{
|
||||
$url = $this->album->getAlbumSource()->getUrlToPhoto($this, $thumbnailName);
|
||||
/** @var IAlbumSource $source */
|
||||
$source = $this->album->getAlbumSource();
|
||||
$sourceConfiguration = $source->getConfiguration();
|
||||
|
||||
if ($cacheBust)
|
||||
$url = $source->getUrlToPhoto($this, $thumbnailName);
|
||||
|
||||
// Cache busting doesn't work with S3 signed URLs
|
||||
if ($cacheBust && !$sourceConfiguration->s3_signed_urls)
|
||||
{
|
||||
// Append the timestamp of the last update to avoid browser caching
|
||||
$theDate = is_null($this->updated_at) ? $this->created_at : $this->updated_at;
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddS3SignedUrlsColumnToStoragesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('storages', function (Blueprint $table) {
|
||||
$table->boolean('s3_signed_urls');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('storages', function (Blueprint $table) {
|
||||
$table->dropColumn('s3_signed_urls');
|
||||
});
|
||||
}
|
||||
}
|
@ -323,7 +323,10 @@ return [
|
||||
'photos' => 'photo|photos',
|
||||
'users' => 'user|users',
|
||||
],
|
||||
'storage_auth_url_label_help' => 'Leave blank to authenticate with Amazon S3. For an S3-compatible provider, enter your provider\'s authentication URL here.',
|
||||
'storage_backblaze_access_key_id_help' => 'To use your account\'s master key, enter your account ID here.',
|
||||
'storage_s3_signed_urls_help' => 'When enabled, Blue Twilight will upload your photos with a private ACL and will use signed URLs to display the photos to your visitors.',
|
||||
'storage_s3_signed_urls_tooltip' => 'This location is set to use private images with signed URLs.',
|
||||
'storage_title' => 'Storage Locations',
|
||||
'sysinfo_panel' => 'System information',
|
||||
'sysinfo_widget' => [
|
||||
|
@ -113,6 +113,7 @@ return [
|
||||
'storage_driver_label' => 'Storage driver:',
|
||||
'storage_endpoint_url_label' => 'Endpoint URL (leave blank if using Amazon):',
|
||||
'storage_location_label' => 'Physical location:',
|
||||
'storage_s3_signed_urls' => 'Upload files privately and use signed URLs',
|
||||
'storage_secret_key_label' => 'Secret key:',
|
||||
'storage_service_name_label' => 'Service name:',
|
||||
'storage_service_region_label' => 'Region:',
|
||||
|
@ -61,13 +61,13 @@
|
||||
@include(Theme::viewName('partials.admin_storages_rackspace_options'))
|
||||
@endif
|
||||
|
||||
<div v-if="storage_driver == 'BackblazeB2Source'">
|
||||
@if ($storage->source == 'BackblazeB2Source')
|
||||
<hr/>
|
||||
@include(Theme::viewName('partials.admin_storages_backblaze_b2_options'))
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="text-right">
|
||||
<a href="{{ route('storage.index') }}" class="btn btn-default">@lang('forms.cancel_action')</a>
|
||||
<a href="{{ route('storage.index') }}" class="btn btn-link">@lang('forms.cancel_action')</a>
|
||||
<button type="submit" class="btn btn-success"><i class="fa fa-fw fa-check"></i> @lang('forms.save_action')</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -39,7 +39,12 @@
|
||||
<span style="color: #888; font-style: italic;">
|
||||
@if ($storage->source == 'LocalFilesystemSource'){{ $storage->location }}@endif
|
||||
@if ($storage->source == 'OpenStackSource'){{ $storage->container_name }} - {{ $storage->service_name }}, {{ $storage->service_region }}@endif
|
||||
@if ($storage->source == 'AmazonS3Source'){{ $storage->container_name }} - {{ $storage->service_region }}@endif
|
||||
@if ($storage->source == 'AmazonS3Source')
|
||||
{{ $storage->container_name }} - {{ $storage->service_region }}
|
||||
@if ($storage->s3_signed_urls)
|
||||
<i class="fa fa-key ml-2" data-toggle="tooltip" title="@lang('admin.storage_s3_signed_urls_tooltip')"></i>
|
||||
@endif
|
||||
@endif
|
||||
@if ($storage->source == 'RackspaceSource'){{ $storage->container_name }} - {{ $storage->service_region }}@endif
|
||||
</span>
|
||||
</td>
|
||||
@ -81,3 +86,11 @@
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
});
|
||||
</script>
|
||||
@endpush
|
@ -55,6 +55,7 @@
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="auth-url">@lang('forms.storage_auth_url_label')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('auth_url') ? ' is-invalid' : '' }}" id="auth-url" name="auth_url" value="{{ old('auth_url', $storage->auth_url) }}">
|
||||
<small class="form-text text-muted">@lang('admin.storage_auth_url_label_help')</small>
|
||||
|
||||
@if ($errors->has('auth_url'))
|
||||
<div class="invalid-feedback">
|
||||
@ -62,3 +63,11 @@
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-check form-group">
|
||||
<input type="checkbox" class="form-check-input" id="s3-signed-urls" name="s3_signed_urls"@if (old('s3_signed_urls', $storage->s3_signed_urls)) checked="checked"@endif>
|
||||
<label for="s3-signed-urls" class="form-check-label">
|
||||
<strong>@lang('forms.storage_s3_signed_urls')</strong><br>
|
||||
@lang('admin.storage_s3_signed_urls_help')
|
||||
</label>
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user