@ -30,12 +30,17 @@ class ExternalService extends Model
|
||||
|
||||
public function hasOAuthStandardOptions()
|
||||
{
|
||||
// This list must be mirrored in external_services.js
|
||||
// This logic must be mirrored in external_services.js
|
||||
return in_array($this->service_type, [
|
||||
self::DROPBOX,
|
||||
self::FACEBOOK,
|
||||
self::GOOGLE,
|
||||
self::TWITTER
|
||||
]);
|
||||
}
|
||||
|
||||
public function isDropbox()
|
||||
{
|
||||
// This logic must be mirrored in external_services.js
|
||||
return $this->service_type == self::DROPBOX;
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\StoreServiceRequest;
|
||||
use App\Services\DropboxService;
|
||||
use App\Storage;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\View;
|
||||
@ -36,6 +38,53 @@ class ServiceController extends Controller
|
||||
$this->fieldsToEncrypt = ['app_id', 'app_secret'];
|
||||
}
|
||||
|
||||
public function authoriseDropbox(Request $request)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-storage');
|
||||
|
||||
if (!$request->has('state') && !$request->has('code'))
|
||||
{
|
||||
// TODO flash an error
|
||||
return redirect('storages.index');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$storageID = decrypt($request->get('state'));
|
||||
|
||||
$storage = Storage::where('id', intval($storageID))->first();
|
||||
if (is_null($storage))
|
||||
{
|
||||
// TODO flash an error
|
||||
return redirect('storages.index');
|
||||
}
|
||||
|
||||
if (is_null($storage->externalService))
|
||||
{
|
||||
// TODO flash an error
|
||||
return redirect('storages.index');
|
||||
}
|
||||
|
||||
switch ($storage->externalService->service_type)
|
||||
{
|
||||
case ExternalService::DROPBOX:
|
||||
$dropbox = new DropboxService();
|
||||
$dropbox->handleAuthenticationResponse($request, $storage);
|
||||
// TODO flash a success message
|
||||
return redirect(route('storage.index'));
|
||||
|
||||
default:
|
||||
// TODO flash an error
|
||||
return redirect('storages.index');
|
||||
}
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
// TODO flash an error
|
||||
return redirect('storages.index');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
@ -46,6 +95,7 @@ class ServiceController extends Controller
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-services');
|
||||
|
||||
return Theme::render('admin.create_service', [
|
||||
'callbackUrls' => $this->callbackList(),
|
||||
'service' => new ExternalService(),
|
||||
'serviceTypes' => $this->serviceTypeList()
|
||||
]);
|
||||
@ -136,6 +186,7 @@ class ServiceController extends Controller
|
||||
}
|
||||
|
||||
return Theme::render('admin.edit_service', [
|
||||
'callbackUrls' => $this->callbackList(),
|
||||
'service' => $service,
|
||||
'serviceTypes' => $this->serviceTypeList()
|
||||
]);
|
||||
@ -222,6 +273,15 @@ class ServiceController extends Controller
|
||||
return redirect(route('services.index'));
|
||||
}
|
||||
|
||||
private function callbackList()
|
||||
{
|
||||
$dropboxService = new DropboxService();
|
||||
|
||||
return [
|
||||
ExternalService::DROPBOX => $dropboxService->callbackUrl()
|
||||
];
|
||||
}
|
||||
|
||||
private function isServiceInUse(ExternalService $service)
|
||||
{
|
||||
// TODO check if the service is in use anywhere else and prevent it being deleted if so
|
||||
|
@ -28,7 +28,7 @@ class StorageController extends Controller
|
||||
$this->encryptedFields = ['password', 'access_key', 'secret_key', 'access_token'];
|
||||
}
|
||||
|
||||
public function authoriseService($id)
|
||||
public function authoriseService(Request $request, $id)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-storage');
|
||||
|
||||
@ -38,47 +38,35 @@ class StorageController extends Controller
|
||||
App::abort(404);
|
||||
}
|
||||
|
||||
if (is_null($storage->externalService))
|
||||
$externalServiceType = $this->getExternalServiceType($storage);
|
||||
|
||||
if (is_null($externalServiceType))
|
||||
{
|
||||
App::abort(400, 'Storage does not support an external service');
|
||||
$request->session()->flash('error', trans('admin.storage_no_external_service_support'));
|
||||
return redirect(route('storages.index'));
|
||||
}
|
||||
|
||||
switch ($storage->externalService->service_type)
|
||||
$serviceTypeName = trans(sprintf('services.%s', $externalServiceType));
|
||||
$viewData = [
|
||||
'service' => $storage->externalService,
|
||||
'serviceName' => $serviceTypeName,
|
||||
'storage' => $storage
|
||||
];
|
||||
|
||||
switch ($externalServiceType)
|
||||
{
|
||||
case ExternalService::DROPBOX:
|
||||
$dropbox = new DropboxService();
|
||||
return redirect($dropbox->authoriseUrl($storage));
|
||||
$viewData['authoriseUrl'] = $dropbox->authoriseUrl($storage);
|
||||
$viewData['callbackUrl'] = $dropbox->callbackUrl();
|
||||
break;
|
||||
|
||||
default:
|
||||
App::abort(400, 'External service does not support authorisation');
|
||||
}
|
||||
$request->session()->flash('error', trans('admin.storage_external_service_no_authorisation', ['service_name' => $serviceTypeName]));
|
||||
return redirect(route('storages.index'));
|
||||
}
|
||||
|
||||
public function completeServiceAuthorisation(Request $request, $id)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-storage');
|
||||
|
||||
$storage = Storage::where('id', intval($id))->first();
|
||||
if (is_null($storage))
|
||||
{
|
||||
App::abort(404);
|
||||
}
|
||||
|
||||
if (is_null($storage->externalService))
|
||||
{
|
||||
App::abort(400, 'Storage does not support an external service');
|
||||
}
|
||||
|
||||
switch ($storage->externalService->service_type)
|
||||
{
|
||||
case ExternalService::DROPBOX:
|
||||
$dropbox = new DropboxService();
|
||||
$dropbox->handleAuthenticationResponse($request, $storage);
|
||||
return redirect(route('storage.index'));
|
||||
|
||||
default:
|
||||
App::abort(400, 'External service does not support authorisation');
|
||||
}
|
||||
return Theme::render('admin.authorise_external_service', $viewData);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -175,6 +163,17 @@ class StorageController extends Controller
|
||||
$this->unsetIsDefaultFromOthers($storage);
|
||||
}
|
||||
|
||||
$externalServiceType = $this->getExternalServiceType($storage);
|
||||
|
||||
if (!is_null($externalServiceType))
|
||||
{
|
||||
switch ($externalServiceType)
|
||||
{
|
||||
case ExternalService::DROPBOX:
|
||||
return redirect(route('storage.authoriseService', ['storage' => $storage->id]));
|
||||
}
|
||||
}
|
||||
|
||||
return redirect(route('storage.index'));
|
||||
}
|
||||
|
||||
@ -351,6 +350,16 @@ class StorageController extends Controller
|
||||
return redirect(route('storage.index'));
|
||||
}
|
||||
|
||||
private function getExternalServiceType(Storage $storage)
|
||||
{
|
||||
if (!is_null($storage->externalService))
|
||||
{
|
||||
return $storage->externalService->service_type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function setIsDefaultForFirstStorage()
|
||||
{
|
||||
$count = Storage::where('is_default', true)->count();
|
||||
|
@ -27,16 +27,22 @@ class DropboxService
|
||||
public function authoriseUrl(Storage $storage)
|
||||
{
|
||||
$service = $storage->externalService;
|
||||
$redirectUrl = route('storage.completeServiceAuthorisation', ['storage' => $storage->id]);
|
||||
$redirectUrl = $this->callbackUrl();
|
||||
|
||||
return sprintf(
|
||||
'%s?client_id=%s&response_type=code&redirect_uri=%s',
|
||||
'%s?client_id=%s&response_type=code&redirect_uri=%s&state=%s',
|
||||
$this->config['authorise_url'],
|
||||
urlencode(decrypt($service->app_id)),
|
||||
urlencode($redirectUrl)
|
||||
urlencode($redirectUrl),
|
||||
urlencode(encrypt($storage->id))
|
||||
);
|
||||
}
|
||||
|
||||
public function callbackUrl()
|
||||
{
|
||||
return route('services.authoriseDropbox');
|
||||
}
|
||||
|
||||
public function downloadFile($pathOnStorage)
|
||||
{
|
||||
$dropboxArgs = ['path' => $pathOnStorage];
|
||||
@ -100,7 +106,7 @@ class DropboxService
|
||||
{
|
||||
$service = $storage->externalService;
|
||||
$credentials = sprintf('%s:%s', decrypt($service->app_id), decrypt($service->app_secret));
|
||||
$redirectUrl = route('storage.completeServiceAuthorisation', ['storage' => $storage->id]);
|
||||
$redirectUrl = $this->callbackUrl();
|
||||
|
||||
$httpHeaders = [
|
||||
'Accept: application/json',
|
||||
|
@ -7,11 +7,15 @@ function ExternalServiceViewModel()
|
||||
this.computed = {
|
||||
hasOAuthStandardOptions()
|
||||
{
|
||||
// This list must be mirrored in App\ExternalService
|
||||
return this.service_type === 'dropbox' ||
|
||||
this.service_type === 'facebook' ||
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'facebook' ||
|
||||
this.service_type === 'google' ||
|
||||
this.service_type === 'twitter';
|
||||
},
|
||||
isDropbox()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'dropbox';
|
||||
}
|
||||
}
|
||||
}
|
@ -63,6 +63,10 @@ return [
|
||||
'approve_comment_confirm' => 'Are you sure you want to approve this comment by ":author_name"?',
|
||||
'approve_comments' => 'Approve :number comments',
|
||||
'approve_comments_confirm' => 'Are you sure you want to approve these :number comments?',
|
||||
'authorise_service_authorise' => 'Authorise',
|
||||
'authorise_service_authorise_intro' => 'Click the Authorise button to login to :name.',
|
||||
'authorise_service_intro' => 'Blue Twilight needs authorisation to access your :name account.',
|
||||
'authorise_service_title' => 'Authorise access to :name',
|
||||
'bulk_comments_approved' => ':number comment was approved successfully.|:number comments were approved successfully.',
|
||||
'bulk_comments_deleted' => ':number comment was deleted successfully.|:number comments were deleted successfully.',
|
||||
'bulk_photos_changed' => ':number photo was updated successfully.|:number photos were updated successfully.',
|
||||
@ -269,6 +273,7 @@ return [
|
||||
'visible_action' => 'Only those visible'
|
||||
],
|
||||
'select_none_action' => 'Clear selection',
|
||||
'service_callback_intro' => 'Please ensure you add the below URL to your :name app as a "trusted", "callback" or "redirect" URL.',
|
||||
'service_deletion_failed' => 'An error occurred while removing the :name service: :error_message',
|
||||
'service_deletion_successful' => 'The :name service was removed successfully.',
|
||||
'services_title' => 'External services',
|
||||
@ -344,6 +349,8 @@ return [
|
||||
'storage_authorise_external_service_refresh_authentication' => 'Refresh authentication',
|
||||
'storage_authorise_external_service_required' => 'Authorisation required',
|
||||
'storage_backblaze_access_key_id_help' => 'To use your account\'s master key, enter your account ID here.',
|
||||
'storage_external_service_no_authorisation' => ':service_name does not support authentication.',
|
||||
'storage_no_external_service_support' => 'This storage driver does not support an external service.',
|
||||
'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',
|
||||
|
@ -6,6 +6,7 @@ return [
|
||||
'admin' => 'Admin',
|
||||
'albums' => 'Albums',
|
||||
'approve_comment' => 'Approve comment',
|
||||
'authorise_service' => 'Authorise service',
|
||||
'comments' => 'Comments',
|
||||
'create_album' => 'Create album',
|
||||
'create_group' => 'Create group',
|
||||
|
@ -0,0 +1,27 @@
|
||||
@extends(Theme::viewName('layout'))
|
||||
@section('title', trans('admin.authorise_service_title', ['name' => $serviceName]))
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('storage.index') }}">@lang('navigation.breadcrumb.storage')</a></li>
|
||||
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.authorise_service')</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 ml-md-auto mr-md-auto">
|
||||
<div class="card bg-info">
|
||||
<div class="card-header text-white">@yield('title')</div>
|
||||
<div class="card-body bg-light">
|
||||
<p>@lang('admin.authorise_service_intro', ['name' => $serviceName])</p>
|
||||
|
||||
<p class="text-success">@lang('admin.authorise_service_authorise_intro', ['name' => $serviceName])</p>
|
||||
<p class="text-right mb-0"><a href="{{ $authoriseUrl }}" class="btn btn-primary">@lang('admin.authorise_service_authorise')</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
@ -50,6 +50,9 @@
|
||||
<div v-if="hasOAuthStandardOptions">
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'))
|
||||
</div>
|
||||
<div v-elseif="isDropbox">
|
||||
@include(Theme::viewName('partials.admin_services_dropbox_options'))
|
||||
</div>
|
||||
|
||||
<div class="text-right">
|
||||
<a href="{{ route('services.index') }}" class="btn btn-link">@lang('forms.cancel_action')</a>
|
||||
|
@ -50,6 +50,8 @@
|
||||
|
||||
@if ($service->hasOAuthStandardOptions())
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'))
|
||||
@elseif ($service->isDropbox())
|
||||
@include(Theme::viewName('partials.admin_services_dropbox_options'))
|
||||
@endif
|
||||
|
||||
<div class="text-right" style="margin-top: 20px;">
|
||||
|
@ -0,0 +1,31 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="access-key">@lang('forms.service_app_id_label')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('app_id') ? ' is-invalid' : '' }}" id="app-id" name="app_id" value="{{ old('app_id', $service->app_id) }}">
|
||||
|
||||
@if ($errors->has('app_id'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('app_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="secret-key">@lang('forms.service_app_secret_label')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('app_secret') ? ' is-invalid' : '' }}" id="app-secret" name="app_secret" value="{{ old('app_secret', $service->app_secret) }}">
|
||||
|
||||
@if ($errors->has('app_secret'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('app_secret') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<p>@lang('admin.service_callback_intro', ['name' => trans(sprintf('services.%s', \App\ExternalService::DROPBOX))])</p>
|
||||
<p class="mb-0"><b>{{ $callbackUrls[\App\ExternalService::DROPBOX] }}</b></p>
|
||||
</div>
|
@ -56,7 +56,6 @@ Route::group(['prefix' => 'admin'], function () {
|
||||
|
||||
// Storage management
|
||||
Route::get('storage/{storage}/authorise-service', 'Admin\StorageController@authoriseService')->name('storage.authoriseService');
|
||||
Route::get('storage/{storage}/complete-service-authorisation', 'Admin\StorageController@completeServiceAuthorisation')->name('storage.completeServiceAuthorisation');
|
||||
Route::get('storage/{storage}/delete', 'Admin\StorageController@delete')->name('storage.delete');
|
||||
Route::resource('storage', 'Admin\StorageController');
|
||||
|
||||
@ -83,6 +82,7 @@ Route::group(['prefix' => 'admin'], function () {
|
||||
Route::resource('comments', 'Admin\PhotoCommentController');
|
||||
|
||||
// Services management
|
||||
Route::get('services/authorise-dropbox', 'Admin\ServiceController@authoriseDropbox')->name('services.authoriseDropbox');
|
||||
Route::get('services/{service}/delete', 'Admin\ServiceController@delete')->name('services.delete');
|
||||
Route::resource('services', 'Admin\ServiceController');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user