mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Merge branch 'v21.04.x'
This commit is contained in:
commit
7d94da10fb
@ -19,10 +19,37 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
|
|||||||
|
|
||||||
class SocialAuthService
|
class SocialAuthService
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The core socialite library used.
|
||||||
|
* @var Socialite
|
||||||
|
*/
|
||||||
protected $socialite;
|
protected $socialite;
|
||||||
protected $socialAccount;
|
|
||||||
|
|
||||||
protected $validSocialDrivers = ['google', 'github', 'facebook', 'slack', 'twitter', 'azure', 'okta', 'gitlab', 'twitch', 'discord'];
|
/**
|
||||||
|
* The default built-in social drivers we support.
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
protected $validSocialDrivers = [
|
||||||
|
'google',
|
||||||
|
'github',
|
||||||
|
'facebook',
|
||||||
|
'slack',
|
||||||
|
'twitter',
|
||||||
|
'azure',
|
||||||
|
'okta',
|
||||||
|
'gitlab',
|
||||||
|
'twitch',
|
||||||
|
'discord'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callbacks to run when configuring a social driver
|
||||||
|
* for an initial redirect action.
|
||||||
|
* Array is keyed by social driver name.
|
||||||
|
* Callbacks are passed an instance of the driver.
|
||||||
|
* @var array<string, callable>
|
||||||
|
*/
|
||||||
|
protected $configureForRedirectCallbacks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SocialAuthService constructor.
|
* SocialAuthService constructor.
|
||||||
@ -39,7 +66,7 @@ class SocialAuthService
|
|||||||
public function startLogIn(string $socialDriver): RedirectResponse
|
public function startLogIn(string $socialDriver): RedirectResponse
|
||||||
{
|
{
|
||||||
$driver = $this->validateDriver($socialDriver);
|
$driver = $this->validateDriver($socialDriver);
|
||||||
return $this->getSocialDriver($driver)->redirect();
|
return $this->getDriverForRedirect($driver)->redirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +76,7 @@ class SocialAuthService
|
|||||||
public function startRegister(string $socialDriver): RedirectResponse
|
public function startRegister(string $socialDriver): RedirectResponse
|
||||||
{
|
{
|
||||||
$driver = $this->validateDriver($socialDriver);
|
$driver = $this->validateDriver($socialDriver);
|
||||||
return $this->getSocialDriver($driver)->redirect();
|
return $this->getDriverForRedirect($driver)->redirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,7 +254,7 @@ class SocialAuthService
|
|||||||
/**
|
/**
|
||||||
* Provide redirect options per service for the Laravel Socialite driver
|
* Provide redirect options per service for the Laravel Socialite driver
|
||||||
*/
|
*/
|
||||||
public function getSocialDriver(string $driverName): Provider
|
protected function getDriverForRedirect(string $driverName): Provider
|
||||||
{
|
{
|
||||||
$driver = $this->socialite->driver($driverName);
|
$driver = $this->socialite->driver($driverName);
|
||||||
|
|
||||||
@ -238,6 +265,10 @@ class SocialAuthService
|
|||||||
$driver->with(['resource' => 'https://graph.windows.net']);
|
$driver->with(['resource' => 'https://graph.windows.net']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($this->configureForRedirectCallbacks[$driverName])) {
|
||||||
|
$this->configureForRedirectCallbacks[$driverName]($driver);
|
||||||
|
}
|
||||||
|
|
||||||
return $driver;
|
return $driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,12 +279,19 @@ class SocialAuthService
|
|||||||
* within the `Config/services.php` file.
|
* within the `Config/services.php` file.
|
||||||
* Handler should be a Class@method handler to the SocialiteWasCalled event.
|
* Handler should be a Class@method handler to the SocialiteWasCalled event.
|
||||||
*/
|
*/
|
||||||
public function addSocialDriver(string $driverName, array $config, string $socialiteHandler)
|
public function addSocialDriver(
|
||||||
{
|
string $driverName,
|
||||||
|
array $config,
|
||||||
|
string $socialiteHandler,
|
||||||
|
callable $configureForRedirect = null
|
||||||
|
) {
|
||||||
$this->validSocialDrivers[] = $driverName;
|
$this->validSocialDrivers[] = $driverName;
|
||||||
config()->set('services.' . $driverName, $config);
|
config()->set('services.' . $driverName, $config);
|
||||||
config()->set('services.' . $driverName . '.redirect', url('/login/service/' . $driverName . '/callback'));
|
config()->set('services.' . $driverName . '.redirect', url('/login/service/' . $driverName . '/callback'));
|
||||||
config()->set('services.' . $driverName . '.name', $config['name'] ?? $driverName);
|
config()->set('services.' . $driverName . '.name', $config['name'] ?? $driverName);
|
||||||
Event::listen(SocialiteWasCalled::class, $socialiteHandler);
|
Event::listen(SocialiteWasCalled::class, $socialiteHandler);
|
||||||
|
if (!is_null($configureForRedirect)) {
|
||||||
|
$this->configureForRedirectCallbacks[$driverName] = $configureForRedirect;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,9 @@ class ThemeService
|
|||||||
/**
|
/**
|
||||||
* @see SocialAuthService::addSocialDriver
|
* @see SocialAuthService::addSocialDriver
|
||||||
*/
|
*/
|
||||||
public function addSocialDriver(string $driverName, array $config, string $socialiteHandler)
|
public function addSocialDriver(string $driverName, array $config, string $socialiteHandler, callable $configureForRedirect = null)
|
||||||
{
|
{
|
||||||
$socialAuthService = app()->make(SocialAuthService::class);
|
$socialAuthService = app()->make(SocialAuthService::class);
|
||||||
$socialAuthService->addSocialDriver($driverName, $config, $socialiteHandler);
|
$socialAuthService->addSocialDriver($driverName, $config, $socialiteHandler, $configureForRedirect);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -140,12 +140,13 @@ class ImageService
|
|||||||
{
|
{
|
||||||
$storage->put($path, $data);
|
$storage->put($path, $data);
|
||||||
|
|
||||||
// Set visibility if using s3 without an endpoint set.
|
// Set visibility when a non-AWS-s3, s3-like storage option is in use.
|
||||||
// Done since this call can break s3-like services but desired for actual
|
// Done since this call can break s3-like services but desired for other image stores.
|
||||||
// AWS s3 usage. Attempting to set ACL during above put request requires
|
// Attempting to set ACL during above put request requires different permissions
|
||||||
// different permissions hence would technically be a breaking change.
|
// hence would technically be a breaking change for actual s3 usage.
|
||||||
$usingS3 = strtolower(config('filesystems.images')) === 's3';
|
$usingS3 = strtolower(config('filesystems.images')) === 's3';
|
||||||
if ($usingS3 && is_null(config('filesystems.disks.s3.endpoint'))) {
|
$usingS3Like = $usingS3 && !is_null(config('filesystems.disks.s3.endpoint'));
|
||||||
|
if (!$usingS3Like) {
|
||||||
$storage->setVisibility($path, 'public');
|
$storage->setVisibility($path, 'public');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,3 +96,17 @@ Theme::listen(ThemeEvents::APP_BOOT, function($app) {
|
|||||||
], '\SocialiteProviders\Reddit\RedditExtendSocialite@handle');
|
], '\SocialiteProviders\Reddit\RedditExtendSocialite@handle');
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In some cases you may need to customize the driver before it performs a redirect.
|
||||||
|
This can be done by providing a callback as a fourth parameter like so:
|
||||||
|
|
||||||
|
```php
|
||||||
|
Theme::addSocialDriver('reddit', [
|
||||||
|
'client_id' => 'abc123',
|
||||||
|
'client_secret' => 'def456789',
|
||||||
|
'name' => 'Reddit',
|
||||||
|
], '\SocialiteProviders\Reddit\RedditExtendSocialite@handle', function($driver) {
|
||||||
|
$driver->with(['prompt' => 'select_account']);
|
||||||
|
$driver->scopes(['open_id']);
|
||||||
|
});
|
||||||
|
```
|
@ -1,6 +1,5 @@
|
|||||||
<?php namespace Tests;
|
<?php namespace Tests;
|
||||||
|
|
||||||
use BookStack\Auth\Access\SocialAuthService;
|
|
||||||
use BookStack\Auth\User;
|
use BookStack\Auth\User;
|
||||||
use BookStack\Entities\Models\Page;
|
use BookStack\Entities\Models\Page;
|
||||||
use BookStack\Entities\Tools\PageContent;
|
use BookStack\Entities\Tools\PageContent;
|
||||||
@ -184,6 +183,28 @@ class ThemeTest extends TestCase
|
|||||||
$loginResp->assertSee('Super Cat Name');
|
$loginResp->assertSee('Super Cat Name');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function test_add_social_driver_allows_a_configure_for_redirect_callback_to_be_passed()
|
||||||
|
{
|
||||||
|
Theme::addSocialDriver(
|
||||||
|
'discord',
|
||||||
|
[
|
||||||
|
'client_id' => 'abc123',
|
||||||
|
'client_secret' => 'def456',
|
||||||
|
'name' => 'Super Cat Name',
|
||||||
|
],
|
||||||
|
'SocialiteProviders\Discord\DiscordExtendSocialite@handle',
|
||||||
|
function ($driver) {
|
||||||
|
$driver->with(['donkey' => 'donut']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$loginResp = $this->get('/login/service/discord');
|
||||||
|
$redirect = $loginResp->headers->get('location');
|
||||||
|
$this->assertStringContainsString('donkey=donut', $redirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function usingThemeFolder(callable $callback)
|
protected function usingThemeFolder(callable $callback)
|
||||||
{
|
{
|
||||||
// Create a folder and configure a theme
|
// Create a folder and configure a theme
|
||||||
|
@ -14,7 +14,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_image_upload()
|
public function test_image_upload()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$admin = $this->getAdmin();
|
$admin = $this->getAdmin();
|
||||||
$this->actingAs($admin);
|
$this->actingAs($admin);
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_image_display_thumbnail_generation_does_not_increase_image_size()
|
public function test_image_display_thumbnail_generation_does_not_increase_image_size()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$admin = $this->getAdmin();
|
$admin = $this->getAdmin();
|
||||||
$this->actingAs($admin);
|
$this->actingAs($admin);
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_image_usage()
|
public function test_image_usage()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$editor = $this->getEditor();
|
$editor = $this->getEditor();
|
||||||
$this->actingAs($editor);
|
$this->actingAs($editor);
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_php_files_cannot_be_uploaded()
|
public function test_php_files_cannot_be_uploaded()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$admin = $this->getAdmin();
|
$admin = $this->getAdmin();
|
||||||
$this->actingAs($admin);
|
$this->actingAs($admin);
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_php_like_files_cannot_be_uploaded()
|
public function test_php_like_files_cannot_be_uploaded()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$admin = $this->getAdmin();
|
$admin = $this->getAdmin();
|
||||||
$this->actingAs($admin);
|
$this->actingAs($admin);
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ class ImageTest extends TestCase
|
|||||||
];
|
];
|
||||||
foreach ($badNames as $name) {
|
foreach ($badNames as $name) {
|
||||||
$galleryFile = $this->getTestImage($name);
|
$galleryFile = $this->getTestImage($name);
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$badPath = $this->getTestImagePath('gallery', $name);
|
$badPath = $this->getTestImagePath('gallery', $name);
|
||||||
$this->deleteImage($badPath);
|
$this->deleteImage($badPath);
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ class ImageTest extends TestCase
|
|||||||
config()->set('filesystems.images', 'local_secure');
|
config()->set('filesystems.images', 'local_secure');
|
||||||
$this->asEditor();
|
$this->asEditor();
|
||||||
$galleryFile = $this->getTestImage('my-secure-test-upload.png');
|
$galleryFile = $this->getTestImage('my-secure-test-upload.png');
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$expectedPath = storage_path('uploads/images/gallery/' . Date('Y-m') . '/my-secure-test-upload.png');
|
$expectedPath = storage_path('uploads/images/gallery/' . Date('Y-m') . '/my-secure-test-upload.png');
|
||||||
|
|
||||||
$upload = $this->call('POST', '/images/gallery', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
|
$upload = $this->call('POST', '/images/gallery', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
|
||||||
@ -245,7 +245,7 @@ class ImageTest extends TestCase
|
|||||||
config()->set('filesystems.images', 'local_secure');
|
config()->set('filesystems.images', 'local_secure');
|
||||||
$this->asEditor();
|
$this->asEditor();
|
||||||
$galleryFile = $this->getTestImage('my-secure-test-upload.png');
|
$galleryFile = $this->getTestImage('my-secure-test-upload.png');
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$expectedPath = storage_path('uploads/images/gallery/' . Date('Y-m') . '/my-secure-test-upload.png');
|
$expectedPath = storage_path('uploads/images/gallery/' . Date('Y-m') . '/my-secure-test-upload.png');
|
||||||
|
|
||||||
$upload = $this->call('POST', '/images/gallery', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
|
$upload = $this->call('POST', '/images/gallery', ['uploaded_to' => $page->id], [], ['file' => $galleryFile], []);
|
||||||
@ -282,7 +282,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_image_delete()
|
public function test_image_delete()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$this->asAdmin();
|
$this->asAdmin();
|
||||||
$imageName = 'first-image.png';
|
$imageName = 'first-image.png';
|
||||||
$relPath = $this->getTestImagePath('gallery', $imageName);
|
$relPath = $this->getTestImagePath('gallery', $imageName);
|
||||||
@ -304,7 +304,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_image_delete_does_not_delete_similar_images()
|
public function test_image_delete_does_not_delete_similar_images()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$this->asAdmin();
|
$this->asAdmin();
|
||||||
$imageName = 'first-image.png';
|
$imageName = 'first-image.png';
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ class ImageTest extends TestCase
|
|||||||
|
|
||||||
public function test_deleted_unused_images()
|
public function test_deleted_unused_images()
|
||||||
{
|
{
|
||||||
$page = Page::first();
|
$page = Page::query()->first();
|
||||||
$admin = $this->getAdmin();
|
$admin = $this->getAdmin();
|
||||||
$this->actingAs($admin);
|
$this->actingAs($admin);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user