From c726d9e0e9150b60ab462d77ddaecd222fb2003b Mon Sep 17 00:00:00 2001 From: "Vinnie.Watson" Date: Fri, 16 Aug 2024 07:31:16 +1200 Subject: [PATCH] Allow users to share draft files to non members --- _config/config.yml | 3 + src/Controllers/ShareDraftController.php | 79 ++++++++++++++++++++++-- src/Models/ShareToken.php | 4 +- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/_config/config.yml b/_config/config.yml index 8ebfeb1..824d274 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -2,6 +2,9 @@ Name: sharedraftcontent After: framework/routes#coreroutes --- +SilverStripe\Assets\File: + extensions: + - SilverStripe\ShareDraftContent\Extensions\ShareDraftContentSiteTreeExtension SilverStripe\CMS\Model\SiteTree: extensions: - SilverStripe\ShareDraftContent\Extensions\ShareDraftContentSiteTreeExtension diff --git a/src/Controllers/ShareDraftController.php b/src/Controllers/ShareDraftController.php index 2753417..28c6536 100644 --- a/src/Controllers/ShareDraftController.php +++ b/src/Controllers/ShareDraftController.php @@ -4,6 +4,7 @@ use BadMethodCallException; use PageController; +use SilverStripe\Assets\File; use SilverStripe\Core\Environment; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Control\Controller; @@ -11,6 +12,7 @@ use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequestBuilder; use SilverStripe\Control\HTTPResponse; +use SilverStripe\Control\HTTPStreamResponse; use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware; use SilverStripe\Control\Session; use SilverStripe\Core\Injector\Injector; @@ -70,9 +72,27 @@ public function preview(HTTPRequest $request) { // Ensure this URL doesn't get picked up by HTTP caches HTTPCacheControlMiddleware::singleton()->disableCache(); - - $key = $request->param('Key'); $token = $request->param('Token'); + + $shareToken = ShareToken::get()->filter('Token', $token)->first(); + + if (!$shareToken) { + return $this->errorPage(); + } + + if ($shareToken->PageID) { + return $this->previewPage($shareToken); + } + + if ($shareToken->FileID) { + return $this->previewFile($shareToken); + } + } + + public function previewFile($shareToken) + { + $key = $this->request->param('Key'); + try { $session = $this->getRequest()->getSession(); } catch (BadMethodCallException $e) { @@ -81,12 +101,63 @@ public function preview(HTTPRequest $request) ->setSession(Injector::inst()->create(Session::class, [])) ->getSession(); } - $shareToken = ShareToken::get()->filter('Token', $token)->first(); - if (!$shareToken) { + /** @var File|ShareDraftContentSiteTreeExtension $dataObject */ + $dataObject = Versioned::get_by_stage(File::class, Versioned::DRAFT) + ->byID($shareToken->FileID); + + $this->extend('updatePage', $dataObject); + + $latest = Versioned::get_latest_version(File::class, $shareToken->FileID); + + if (!$shareToken->isExpired() && $dataObject->generateKey($shareToken->Token) === $key) { + Requirements::css('silverstripe/sharedraftcontent: client/dist/styles/bundle-frontend.css'); + // Temporarily un-secure the draft site and switch to draft + $oldSecured = $this->getIsDraftSecured($session); + $oldMode = Versioned::get_default_reading_mode(); + static::$isViewingPreview = true; + + // Process page inside an unsecured draft container + try { + $this->setIsDraftSecured($session, false); + Versioned::set_default_reading_mode('Stage.Stage'); + + } finally { + $this->setIsDraftSecured($session, $oldSecured); + // Use set_default_reading_mode() instead of set_reading_mode() because that's + // what's used in Versioned::choose_site_stage() + Versioned::set_default_reading_mode($oldMode); + static::$isViewingPreview = false; + } + + $stream = $dataObject->getStream(); + $size = $dataObject->getSize(); + $mime = $dataObject->getMimeType(); + $response = HTTPStreamResponse::create($stream, $size) + ->addHeader('Content-Type', $mime); + + $response->addHeader('Cache-Control', 'private'); + + return $response; + } else { return $this->errorPage(); } + } + + public function previewPage($shareToken) + { + $key = $this->request->param('Key'); + + try { + $session = $this->getRequest()->getSession(); + } catch (BadMethodCallException $e) { + // Create a new session + $session = $this->getRequest() + ->setSession(Injector::inst()->create(Session::class, [])) + ->getSession(); + } + /** @var SiteTree|ShareDraftContentSiteTreeExtension $page */ $page = Versioned::get_by_stage(SiteTree::class, Versioned::DRAFT) ->byID($shareToken->PageID); diff --git a/src/Models/ShareToken.php b/src/Models/ShareToken.php index dd3f518..69addd1 100644 --- a/src/Models/ShareToken.php +++ b/src/Models/ShareToken.php @@ -3,6 +3,7 @@ namespace SilverStripe\ShareDraftContent\Models; use Page; +use SilverStripe\Assets\File; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\FieldType\DBDatetime; @@ -26,7 +27,8 @@ class ShareToken extends DataObject * @var array */ private static $has_one = array( - 'Page' => Page::class + 'Page' => Page::class, + 'File' => File::class, ); /**