mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 05:36:00 +00:00
do some cleanup and add doc
This commit is contained in:
parent
f14e6e8f2d
commit
14bccae6bd
@ -2,14 +2,16 @@
|
|||||||
|
|
||||||
namespace BookStack\Http\Controllers\Api;
|
namespace BookStack\Http\Controllers\Api;
|
||||||
|
|
||||||
use BookStack\Entities\Models\Book;
|
|
||||||
use BookStack\Entities\Models\Chapter;
|
|
||||||
use BookStack\Entities\Models\Deletion;
|
use BookStack\Entities\Models\Deletion;
|
||||||
use BookStack\Entities\Repos\DeletionRepo;
|
use BookStack\Entities\Repos\DeletionRepo;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
|
||||||
class RecycleBinApiController extends ApiController
|
class RecycleBinApiController extends ApiController
|
||||||
{
|
{
|
||||||
|
protected $fieldsToExpose = [
|
||||||
|
'id', 'deleted_by', 'created_at', 'updated_at', 'deletable_type', 'deletable_id',
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware(function ($request, $next) {
|
$this->middleware(function ($request, $next) {
|
||||||
@ -20,9 +22,13 @@ class RecycleBinApiController extends ApiController
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a top-level listing of the items in the recycle bin.
|
||||||
|
* Requires the permission to manage settings and restrictions.
|
||||||
|
*/
|
||||||
public function list()
|
public function list()
|
||||||
{
|
{
|
||||||
return $this->apiListingResponse(Deletion::query(), [
|
return $this->apiListingResponse(Deletion::query()->with('deletable'), [
|
||||||
'id',
|
'id',
|
||||||
'deleted_by',
|
'deleted_by',
|
||||||
'created_at',
|
'created_at',
|
||||||
@ -32,6 +38,10 @@ class RecycleBinApiController extends ApiController
|
|||||||
], [Closure::fromCallable([$this, 'listFormatter'])]);
|
], [Closure::fromCallable([$this, 'listFormatter'])]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore a single deletion from the recycle bin.
|
||||||
|
* You must provide the deletion id, not the id of the corresponding deleted item.
|
||||||
|
*/
|
||||||
public function restore(DeletionRepo $deletionRepo, string $id)
|
public function restore(DeletionRepo $deletionRepo, string $id)
|
||||||
{
|
{
|
||||||
$restoreCount = $deletionRepo->restore((int) $id);
|
$restoreCount = $deletionRepo->restore((int) $id);
|
||||||
@ -39,6 +49,11 @@ class RecycleBinApiController extends ApiController
|
|||||||
return response()->json(['restore_count' => $restoreCount]);
|
return response()->json(['restore_count' => $restoreCount]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a single deletion from the recycle bin.
|
||||||
|
* Use this endpoint carefully as it will entirely remove the underlying deleted items from the system.
|
||||||
|
* You must provide the deletion id, not the id of the corresponding deleted item.
|
||||||
|
*/
|
||||||
public function destroy(DeletionRepo $deletionRepo, string $id)
|
public function destroy(DeletionRepo $deletionRepo, string $id)
|
||||||
{
|
{
|
||||||
$deleteCount = $deletionRepo->destroy((int) $id);
|
$deleteCount = $deletionRepo->destroy((int) $id);
|
||||||
@ -48,23 +63,26 @@ class RecycleBinApiController extends ApiController
|
|||||||
|
|
||||||
protected function listFormatter(Deletion $deletion)
|
protected function listFormatter(Deletion $deletion)
|
||||||
{
|
{
|
||||||
|
$deletion->makeVisible($this->fieldsToExpose);
|
||||||
|
$deletion->makeHidden('deletable');
|
||||||
|
|
||||||
$deletable = $deletion->deletable;
|
$deletable = $deletion->deletable;
|
||||||
$isBook = $deletable instanceof Book;
|
$isBook = $deletion->deletable_type === "BookStack\Book";
|
||||||
$parent = null;
|
$parent = null;
|
||||||
$children = null;
|
$children = null;
|
||||||
|
|
||||||
if ($isBook) {
|
if ($isBook) {
|
||||||
$chapterCount = $deletable->chapters()->withTrashed()->count();
|
$chapterCount = $deletable->chapters()->withTrashed()->count();
|
||||||
$children['Bookstack\Chapter'] = $chapterCount;
|
$children['BookStack\Chapter'] = $chapterCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($isBook || $deletion->deletable instanceof Chapter) {
|
if ($isBook || $deletion->deletable_type === "BookStack\Chapter") {
|
||||||
$pageCount = $deletable->pages()->withTrashed()->count();
|
$pageCount = $deletable->pages()->withTrashed()->count();
|
||||||
$children['Bookstack\Page'] = $pageCount;
|
$children['BookStack\Page'] = $pageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
$parentEntity = $deletable->getParent();
|
$parentEntity = $deletable->getParent();
|
||||||
$parent = [];
|
$parent = null;
|
||||||
|
|
||||||
if ($parentEntity) {
|
if ($parentEntity) {
|
||||||
$parent['type'] = $parentEntity->getMorphClass();
|
$parent['type'] = $parentEntity->getMorphClass();
|
||||||
|
3
dev/api/responses/recycle_bin-destroy.json
Normal file
3
dev/api/responses/recycle_bin-destroy.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"delete_count": 2
|
||||||
|
}
|
34
dev/api/responses/recycle_bin-list.json
Normal file
34
dev/api/responses/recycle_bin-list.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": 25,
|
||||||
|
"deleted_by": 1,
|
||||||
|
"created_at": "2022-04-24T07:59:34.000000Z",
|
||||||
|
"updated_at": "2022-04-24T07:59:34.000000Z",
|
||||||
|
"deletable_type": "BookStack\\Book",
|
||||||
|
"deletable_id": 4,
|
||||||
|
"parent": {
|
||||||
|
"type": "BookStack\\Book",
|
||||||
|
"id": 25
|
||||||
|
},
|
||||||
|
"children": {
|
||||||
|
"BookStack\\Chapter": 0,
|
||||||
|
"BookStack\\Page": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 26,
|
||||||
|
"deleted_by": 1,
|
||||||
|
"created_at": "2022-04-24T07:59:35.000000Z",
|
||||||
|
"updated_at": "2022-04-24T07:59:35.000000Z",
|
||||||
|
"deletable_type": "BookStack\\Book",
|
||||||
|
"deletable_id": 3,
|
||||||
|
"parent": [],
|
||||||
|
"children": {
|
||||||
|
"BookStack\\Chapter": 1,
|
||||||
|
"BookStack\\Page": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2
|
||||||
|
}
|
3
dev/api/responses/recycle_bin-restore.json
Normal file
3
dev/api/responses/recycle_bin-restore.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"restore_count": 2
|
||||||
|
}
|
@ -33,12 +33,12 @@ class RecycleBinApiTest extends TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_restrictions_manage_all_permission_neeed_for_all_endpoints()
|
public function test_restrictions_manage_all_permission_needed_for_all_endpoints()
|
||||||
{
|
{
|
||||||
$editor = $this->getEditor();
|
$editor = $this->getEditor();
|
||||||
$this->giveUserPermissions($editor, ['restrictions-manage-all']);
|
$this->giveUserPermissions($editor, ['restrictions-manage-all']);
|
||||||
$this->actingAs($editor);
|
$this->actingAs($editor);
|
||||||
|
|
||||||
foreach ($this->endpointMap as [$method, $uri]) {
|
foreach ($this->endpointMap as [$method, $uri]) {
|
||||||
$resp = $this->json($method, $uri);
|
$resp = $this->json($method, $uri);
|
||||||
$resp->assertStatus(403);
|
$resp->assertStatus(403);
|
||||||
@ -74,7 +74,7 @@ class RecycleBinApiTest extends TestCase
|
|||||||
});
|
});
|
||||||
|
|
||||||
$resp->assertJson([
|
$resp->assertJson([
|
||||||
'data' => $expectedData->values()->all(),
|
'data' => $expectedData->values()->all(),
|
||||||
'total' => 2,
|
'total' => 2,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ class RecycleBinApiTest extends TestCase
|
|||||||
public function test_index_endpoint_returns_children()
|
public function test_index_endpoint_returns_children()
|
||||||
{
|
{
|
||||||
$this->actingAsAuthorizedUser();
|
$this->actingAsAuthorizedUser();
|
||||||
|
|
||||||
$book = Book::query()->whereHas('pages')->whereHas('chapters')->withCount(['pages', 'chapters'])->first();
|
$book = Book::query()->whereHas('pages')->whereHas('chapters')->withCount(['pages', 'chapters'])->first();
|
||||||
$editor = $this->getEditor();
|
$editor = $this->getEditor();
|
||||||
$this->actingAs($editor)->delete($book->getUrl());
|
$this->actingAs($editor)->delete($book->getUrl());
|
||||||
@ -100,15 +100,15 @@ class RecycleBinApiTest extends TestCase
|
|||||||
'deletable_type' => $book->getMorphClass(),
|
'deletable_type' => $book->getMorphClass(),
|
||||||
'deletable_id' => $book->getKey(),
|
'deletable_id' => $book->getKey(),
|
||||||
'children' => [
|
'children' => [
|
||||||
'Bookstack\Page' => $book->pages_count,
|
'BookStack\Page' => $book->pages_count,
|
||||||
'Bookstack\Chapter' => $book->chapters_count,
|
'BookStack\Chapter' => $book->chapters_count,
|
||||||
],
|
],
|
||||||
'parent' => null,
|
'parent' => null,
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$resp->assertJson([
|
$resp->assertJson([
|
||||||
'data' => $expectedData,
|
'data' => $expectedData,
|
||||||
'total' => 1,
|
'total' => 1,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -136,22 +136,22 @@ class RecycleBinApiTest extends TestCase
|
|||||||
'deletable_id' => $page->getKey(),
|
'deletable_id' => $page->getKey(),
|
||||||
'parent' => [
|
'parent' => [
|
||||||
'type' => 'BookStack\Chapter',
|
'type' => 'BookStack\Chapter',
|
||||||
'id' => $page->chapter->getKey()
|
'id' => $page->chapter->getKey(),
|
||||||
],
|
],
|
||||||
'children' => null,
|
'children' => null,
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$resp->assertJson([
|
$resp->assertJson([
|
||||||
'data' => $expectedData,
|
'data' => $expectedData,
|
||||||
'total' => 1
|
'total' => 1,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_restore_endpoint()
|
public function test_restore_endpoint()
|
||||||
{
|
{
|
||||||
$this->actingAsAuthorizedUser();
|
$this->actingAsAuthorizedUser();
|
||||||
|
|
||||||
$page = Page::query()->first();
|
$page = Page::query()->first();
|
||||||
$editor = $this->getEditor();
|
$editor = $this->getEditor();
|
||||||
$this->actingAs($editor)->delete($page->getUrl());
|
$this->actingAs($editor)->delete($page->getUrl());
|
||||||
@ -160,22 +160,22 @@ class RecycleBinApiTest extends TestCase
|
|||||||
$deletion = Deletion::query()->orderBy('id')->first();
|
$deletion = Deletion::query()->orderBy('id')->first();
|
||||||
|
|
||||||
$this->assertDatabaseHas('pages', [
|
$this->assertDatabaseHas('pages', [
|
||||||
'id' => $page->getKey(),
|
'id' => $page->getKey(),
|
||||||
'deleted_at' => $page->deleted_at,
|
'deleted_at' => $page->deleted_at,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->putJson($this->baseEndpoint . '/' . $deletion->getKey());
|
$this->putJson($this->baseEndpoint . '/' . $deletion->getKey());
|
||||||
|
|
||||||
$this->assertDatabaseHas('pages', [
|
$this->assertDatabaseHas('pages', [
|
||||||
'id' => $page->getKey(),
|
'id' => $page->getKey(),
|
||||||
'deleted_at' => null,
|
'deleted_at' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_destroy_endpoint()
|
public function test_destroy_endpoint()
|
||||||
{
|
{
|
||||||
$this->actingAsAuthorizedUser();
|
$this->actingAsAuthorizedUser();
|
||||||
|
|
||||||
$page = Page::query()->first();
|
$page = Page::query()->first();
|
||||||
$editor = $this->getEditor();
|
$editor = $this->getEditor();
|
||||||
$this->actingAs($editor)->delete($page->getUrl());
|
$this->actingAs($editor)->delete($page->getUrl());
|
||||||
@ -184,8 +184,8 @@ class RecycleBinApiTest extends TestCase
|
|||||||
$deletion = Deletion::query()->orderBy('id')->first();
|
$deletion = Deletion::query()->orderBy('id')->first();
|
||||||
|
|
||||||
$this->assertDatabaseHas('pages', [
|
$this->assertDatabaseHas('pages', [
|
||||||
'id' => $page->getKey(),
|
'id' => $page->getKey(),
|
||||||
'deleted_at' => $page->deleted_at,
|
'deleted_at' => $page->deleted_at,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->deleteJson($this->baseEndpoint . '/' . $deletion->getKey());
|
$this->deleteJson($this->baseEndpoint . '/' . $deletion->getKey());
|
||||||
|
Loading…
Reference in New Issue
Block a user