diff --git a/resources/js/components/terms/PublishForm.vue b/resources/js/components/terms/PublishForm.vue
index 9adebbd8013..81208100f4b 100644
--- a/resources/js/components/terms/PublishForm.vue
+++ b/resources/js/components/terms/PublishForm.vue
@@ -131,45 +131,6 @@
-
-
name('taxonomies.terms.published.store');
Route::delete('/', [PublishedTermsController::class, 'destroy'])->name('taxonomies.terms.published.destroy');
- Route::resource('revisions', TermRevisionsController::class, [
- 'as' => 'taxonomies.terms',
- 'only' => ['index', 'store', 'show'],
- ]);
-
- Route::post('restore-revision', RestoreTermRevisionController::class)->name('taxonomies.terms.restore-revision');
Route::post('preview', [TermPreviewController::class, 'edit'])->name('taxonomies.terms.preview.edit');
Route::get('preview', [TermPreviewController::class, 'show'])->name('taxonomies.terms.preview.popout');
Route::patch('/', [TermsController::class, 'update'])->name('taxonomies.terms.update');
diff --git a/src/Http/Controllers/CP/Collections/EntryRevisionsController.php b/src/Http/Controllers/CP/Collections/EntryRevisionsController.php
index c1ef85e20f1..f64445f0a5d 100644
--- a/src/Http/Controllers/CP/Collections/EntryRevisionsController.php
+++ b/src/Http/Controllers/CP/Collections/EntryRevisionsController.php
@@ -12,6 +12,10 @@ class EntryRevisionsController extends CpController
{
public function index(Request $request, $collection, $entry)
{
+ if (User::current()->cant('view', $entry)) {
+ abort(403);
+ }
+
$revisions = $entry
->revisions()
->reverse()
@@ -39,6 +43,10 @@ public function index(Request $request, $collection, $entry)
public function store(Request $request, $collection, $entry)
{
+ if (User::current()->cant('edit', $entry)) {
+ abort(403);
+ }
+
$entry->createRevision([
'message' => $request->message,
'user' => User::fromUser($request->user()),
@@ -49,6 +57,10 @@ public function store(Request $request, $collection, $entry)
public function show(Request $request, $collection, $entry, $revision)
{
+ if (User::current()->cant('view', $entry)) {
+ abort(403);
+ }
+
$entry = $entry->makeFromRevision($revision);
// TODO: Most of this is duplicated with EntriesController@edit. DRY it off.
diff --git a/src/Http/Controllers/CP/Taxonomies/RestoreTermRevisionController.php b/src/Http/Controllers/CP/Taxonomies/RestoreTermRevisionController.php
deleted file mode 100644
index 35290002784..00000000000
--- a/src/Http/Controllers/CP/Taxonomies/RestoreTermRevisionController.php
+++ /dev/null
@@ -1,26 +0,0 @@
-revision($request->revision)) {
- dd('no such revision', $request->revision);
- // todo: handle invalid revision reference
- }
-
- if ($entry->published()) {
- WorkingCopy::fromRevision($target)->date(now())->save();
- } else {
- $entry->makeFromRevision($target)->published(false)->save();
- }
-
- session()->flash('success', __('Revision restored'));
- }
-}
diff --git a/src/Http/Controllers/CP/Taxonomies/TermRevisionsController.php b/src/Http/Controllers/CP/Taxonomies/TermRevisionsController.php
deleted file mode 100644
index dafc0af0488..00000000000
--- a/src/Http/Controllers/CP/Taxonomies/TermRevisionsController.php
+++ /dev/null
@@ -1,118 +0,0 @@
-revisions()
- ->reverse()
- ->prepend($this->workingCopy($term))
- ->filter();
-
- // The first non manually created revision would be considered the "current"
- // version. It's what corresponds to what's in the content directory.
- optional($revisions->first(function ($revision) {
- return $revision->action() != 'revision';
- }))->attribute('current', true);
-
- return $revisions
- ->groupBy(function ($revision) {
- return $revision->date()->clone()->startOfDay()->format('U');
- })->map(function ($revisions, $day) {
- return compact('day', 'revisions');
- })->reverse()->values();
- }
-
- public function store(Request $request, $taxonomy, $term)
- {
- $term->createRevision([
- 'message' => $request->message,
- 'user' => User::fromUser($request->user()),
- ]);
-
- return new TermResource($term);
- }
-
- public function show(Request $request, $taxonomy, $term, $site, $revision)
- {
- $term = $term->makeFromRevision($revision);
-
- // TODO: Most of this is duplicated with EntriesController@edit. DRY it off.
-
- $blueprint = $term->blueprint();
-
- $fields = $blueprint
- ->fields()
- ->addValues($term->data())
- ->preProcess();
-
- $values = array_merge($fields->values()->all(), [
- 'title' => $term->get('title'),
- 'slug' => $term->slug(),
- ]);
-
- return [
- 'title' => $term->value('title'),
- 'editing' => true,
- 'actions' => [
- 'save' => $term->updateUrl(),
- 'publish' => $term->publishUrl(),
- 'unpublish' => $term->unpublishUrl(),
- 'revisions' => $term->revisionsUrl(),
- 'restore' => $term->restoreRevisionUrl(),
- 'createRevision' => $term->createRevisionUrl(),
- ],
- 'values' => $values,
- 'meta' => $fields->meta(),
- 'taxonomy' => $this->taxonomyToArray($term->taxonomy()),
- 'blueprint' => $blueprint->toPublishArray(),
- 'readOnly' => User::fromUser($request->user())->cant('edit', $term),
- 'published' => $term->published(),
- 'locale' => $term->locale(),
- 'localizations' => $term->taxonomy()->sites()->map(function ($handle) use ($term) {
- $localized = $term->in($handle);
- $exists = $localized !== null;
-
- return [
- 'handle' => $handle,
- 'name' => Site::get($handle)->name(),
- 'active' => $handle === $term->locale(),
- 'exists' => $exists,
- 'root' => $exists ? $localized->isRoot() : false,
- 'origin' => $exists ? $localized->id() === optional($term->origin())->id() : null,
- 'published' => $exists ? $localized->published() : false,
- 'url' => $exists ? $localized->editUrl() : null,
- ];
- })->all(),
- ];
- }
-
- protected function workingCopy($term)
- {
- if ($term->published()) {
- return $term->workingCopy();
- }
-
- return $term
- ->makeWorkingCopy()
- ->date($term->lastModified())
- ->user($term->lastModifiedBy());
- }
-
- protected function taxonomyToArray($taxonomy)
- {
- return [
- 'title' => $taxonomy->title(),
- 'url' => cp_route('taxonomies.show', $taxonomy->handle()),
- ];
- }
-}
diff --git a/tests/Feature/Entries/EntryRevisionsTest.php b/tests/Feature/Entries/EntryRevisionsTest.php
index d9d032ead25..c7c66735a9e 100644
--- a/tests/Feature/Entries/EntryRevisionsTest.php
+++ b/tests/Feature/Entries/EntryRevisionsTest.php
@@ -46,7 +46,7 @@ public function it_gets_revisions()
$now = Carbon::parse('2017-02-03');
Carbon::setTestNow($now);
$this->setTestBlueprint('test', ['foo' => ['type' => 'text']]);
- $this->setTestRoles(['test' => ['access cp', 'publish blog entries']]);
+ $this->setTestRoles(['test' => ['access cp', 'view blog entries', 'publish blog entries']]);
$user = User::make()->id('user-1')->assignRole('test')->save();
$entry = EntryFactory::id('1')
@@ -97,6 +97,49 @@ public function it_gets_revisions()
->assertJsonPath('1.revisions.1.attributes.item_url', 'http://localhost/cp/collections/blog/entries/1/revisions/'.Carbon::parse('2017-02-03')->timestamp);
}
+ #[Test]
+ public function it_denies_access_to_revisions_without_permission_to_view_entry()
+ {
+ $now = Carbon::parse('2017-02-03');
+ Carbon::setTestNow($now);
+ $this->setTestBlueprint('test', ['foo' => ['type' => 'text']]);
+ $this->setTestRoles(['test' => ['access cp']]);
+ $user = User::make()->id('user-1')->assignRole('test')->save();
+
+ $entry = EntryFactory::id('1')
+ ->slug('test')
+ ->collection('blog')
+ ->published(true)
+ ->date('2010-12-25')
+ ->data([
+ 'blueprint' => 'test',
+ 'title' => 'Original title',
+ 'foo' => 'bar',
+ ])->create();
+
+ tap($entry->makeRevision(), function ($copy) {
+ $copy->message('Revision one');
+ $copy->date(Carbon::parse('2017-02-01'));
+ })->save();
+
+ tap($entry->makeRevision(), function ($copy) {
+ $copy->message('Revision two');
+ $copy->date(Carbon::parse('2017-02-03'));
+ })->save();
+
+ tap($entry->makeWorkingCopy(), function ($copy) {
+ $attrs = $copy->attributes();
+ $attrs['data']['title'] = 'Title modified in working copy';
+ $attrs['data']['foo'] = 'baz';
+ $copy->attributes($attrs);
+ })->save();
+
+ $this
+ ->actingAs($user)
+ ->get($entry->revisionsUrl())
+ ->assertForbidden();
+ }
+
#[Test]
public function it_publishes_an_entry()
{