diff --git a/public/mix-manifest.json b/public/mix-manifest.json
index 4b7c5fd0..ac72b62c 100644
--- a/public/mix-manifest.json
+++ b/public/mix-manifest.json
@@ -40,7 +40,7 @@
"/chunks/files~chunks/platform~chunks/shared~chunks/shared/file-browser.js": "/chunks/files~chunks/platform~chunks/shared~chunks/shared/file-browser.js?id=8a06b7d864acff647f8c",
"/chunks/files~chunks/platform~chunks/shared~chunks/shared/file-browser~chunks/shared/single-file.js": "/chunks/files~chunks/platform~chunks/shared~chunks/shared/file-browser~chunks/shared/single-file.js?id=0de0b81edf0bb5d4617d",
"/chunks/files~chunks/settings-subscription~chunks/shared/file-browser~chunks/user-subscription.js": "/chunks/files~chunks/settings-subscription~chunks/shared/file-browser~chunks/user-subscription.js?id=c5ec9502bcfad35c502e",
- "/chunks/files~chunks/shared/file-browser.js": "/chunks/files~chunks/shared/file-browser.js?id=1b19035df0776555ab90",
+ "/chunks/files~chunks/shared/file-browser.js": "/chunks/files~chunks/shared/file-browser.js?id=89464ac77e762367486b",
"/chunks/files~chunks/shared/file-browser~chunks/shared/single-file.js": "/chunks/files~chunks/shared/file-browser~chunks/shared/single-file.js?id=ad09e3f973e4db0411f1",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=8871529af0da8193d3a3",
"/chunks/homepage.js": "/chunks/homepage.js?id=d29b9f09d08d673dff75",
@@ -126,5 +126,7 @@
"/chunks/platform~chunks/shared.c0f59c4d5f95687a84ad.hot-update.js": "/chunks/platform~chunks/shared.c0f59c4d5f95687a84ad.hot-update.js",
"/chunks/platform~chunks/shared.6db75d5fc148ae19b0b8.hot-update.js": "/chunks/platform~chunks/shared.6db75d5fc148ae19b0b8.hot-update.js",
"/chunks/platform~chunks/shared.a9aa2769c5345e07f90c.hot-update.js": "/chunks/platform~chunks/shared.a9aa2769c5345e07f90c.hot-update.js",
- "/chunks/platform~chunks/shared.8a25cb105761d2e120e8.hot-update.js": "/chunks/platform~chunks/shared.8a25cb105761d2e120e8.hot-update.js"
+ "/chunks/platform~chunks/shared.8a25cb105761d2e120e8.hot-update.js": "/chunks/platform~chunks/shared.8a25cb105761d2e120e8.hot-update.js",
+ "/chunks/files~chunks/shared/file-browser.795bed5a6b8dd1d5f361.hot-update.js": "/chunks/files~chunks/shared/file-browser.795bed5a6b8dd1d5f361.hot-update.js",
+ "/chunks/files~chunks/shared/file-browser.da183dcc2f390b01a554.hot-update.js": "/chunks/files~chunks/shared/file-browser.da183dcc2f390b01a554.hot-update.js"
}
diff --git a/resources/js/components/FilesView/ContextMenu.vue b/resources/js/components/FilesView/ContextMenu.vue
index 4a795f59..3984381d 100644
--- a/resources/js/components/FilesView/ContextMenu.vue
+++ b/resources/js/components/FilesView/ContextMenu.vue
@@ -13,7 +13,7 @@
-
+
@@ -132,7 +132,7 @@
-
+
diff --git a/routes/share.php b/routes/share.php
index 6b21f0d6..44370e6b 100644
--- a/routes/share.php
+++ b/routes/share.php
@@ -1,8 +1,7 @@
'editor'], function () {
});
// Zip shared items
-Route::group(['prefix' => 'zip'], function () {
- Route::get('/folder/{id}/{shared}', VisitorZipFolderController::class);
- Route::post('/files/{shared}', VisitorZipFilesController::class);
-});
+Route::get('/zip/{shared}', VisitorZipController::class);
// Browse share content
Route::group(['prefix' => 'browse'], function () {
- Route::post('/authenticate/{shared}', VisitorUnlockLockedShareController::class);
Route::get('/folders/{id}/{shared}', VisitorBrowseFolderContentController::class);
+ Route::post('/authenticate/{shared}', VisitorUnlockLockedShareController::class);
Route::get('/navigation/{shared}', VisitorNavigationFolderTreeController::class);
Route::get('/search/{shared}', VisitorSearchFilesAndFoldersController::class);
Route::get('/file/{shared}', VisitorShowFileController::class);
diff --git a/src/Domain/Sharing/Actions/ProtectShareRecordAction.php b/src/Domain/Sharing/Actions/ProtectShareRecordAction.php
index c5cd79e6..e9f375ea 100644
--- a/src/Domain/Sharing/Actions/ProtectShareRecordAction.php
+++ b/src/Domain/Sharing/Actions/ProtectShareRecordAction.php
@@ -5,14 +5,15 @@ use Domain\Sharing\Models\Share;
class ProtectShareRecordAction
{
+ private string $message = "Sorry, you don't have permission";
+
public function __invoke(
Share $shared
): void {
if ($shared->is_protected) {
- $abort_message = "Sorry, you don't have permission";
if (! request()->hasCookie('share_session')) {
- abort(403, $abort_message);
+ abort(403, $this->message);
}
// Get shared session
@@ -22,12 +23,12 @@ class ProtectShareRecordAction
// Check if is requested same share record
if ($share_session->token !== $shared->token) {
- abort(403, $abort_message);
+ abort(403, $this->message);
}
// Check if share record was authenticated previously via ShareController@authenticate
if (! $share_session->authenticated) {
- abort(403, $abort_message);
+ abort(403, $this->message);
}
}
}
diff --git a/src/Domain/Sharing/Controllers/SharePublicIndexController.php b/src/Domain/Sharing/Controllers/SharePublicIndexController.php
index 7edd6360..a1ceeddc 100644
--- a/src/Domain/Sharing/Controllers/SharePublicIndexController.php
+++ b/src/Domain/Sharing/Controllers/SharePublicIndexController.php
@@ -46,6 +46,7 @@ class SharePublicIndexController extends Controller
}
return view('index')
+ ->with('status_check', [])
->with('installation', 'setup-done')
->with('settings', get_settings_in_json() ?? null);
}
diff --git a/src/Domain/Zip/Actions/GetItemsListFromUrlParamAction.php b/src/Domain/Zip/Actions/GetItemsListFromUrlParamAction.php
new file mode 100644
index 00000000..97842330
--- /dev/null
+++ b/src/Domain/Zip/Actions/GetItemsListFromUrlParamAction.php
@@ -0,0 +1,45 @@
+get('items'));
+
+ $itemList = collect($list)
+ ->map(function ($chunk) {
+ $items = explode('|', $chunk);
+
+ return [
+ 'id' => $items[0],
+ 'type' => $items[1],
+ ];
+ });
+
+ $folderIds = $itemList
+ ->where('type', 'folder')
+ ->pluck('id');
+
+ $fileIds = $itemList
+ ->where('type', 'file')
+ ->pluck('id');
+
+ $folders = Folder::whereUserId($user_id)
+ ->whereIn('id', $folderIds)
+ ->get();
+
+ $files = File::whereUserId($user_id)
+ ->whereIn('id', $fileIds)
+ ->get();
+
+ return [$folders, $files];
+ }
+}
\ No newline at end of file
diff --git a/src/Domain/Zip/Controllers/VisitorZipController.php b/src/Domain/Zip/Controllers/VisitorZipController.php
new file mode 100644
index 00000000..27a89944
--- /dev/null
+++ b/src/Domain/Zip/Controllers/VisitorZipController.php
@@ -0,0 +1,68 @@
+protectShareRecord)($shared);
+
+ list($folders, $files) = ($this->getItemsListFromUrlParam)($shared->user_id);
+
+ // Check access to requested folders
+ if ($folders->isNotEmpty()) {
+ $folders->each(
+ fn ($folder) => ($this->verifyAccessToItem)($folder->id, $shared)
+ );
+ }
+
+ // Check access to requested files
+ if ($files->isNotEmpty()) {
+
+ $file_parent_folders = File::whereUserId($shared->user_id)
+ ->whereIn('id', $files->pluck('id'))
+ ->get()
+ ->pluck('folder_id')
+ ->toArray();
+
+ // Check access to requested directory
+ ($this->verifyAccessToItem)($file_parent_folders, $shared);
+ }
+
+ // Zip items
+ $zip = ($this->zip)($folders, $files, $shared);
+
+ ($this->recordDownload)(
+ file_size: $zip->predictZipSize(),
+ user_id: $shared->user_id,
+ );
+
+ return $zip;
+ }
+}
\ No newline at end of file
diff --git a/src/Domain/Zip/Controllers/VisitorZipFilesController.php b/src/Domain/Zip/Controllers/VisitorZipFilesController.php
deleted file mode 100644
index 58c577c6..00000000
--- a/src/Domain/Zip/Controllers/VisitorZipFilesController.php
+++ /dev/null
@@ -1,58 +0,0 @@
-protectShareRecord)($shared);
-
- $file_parent_folders = File::whereUserId($shared->user_id)
- ->whereIn('id', $request->items)
- ->get()
- ->pluck('folder_id')
- ->toArray();
-
- // Check access to requested directory
- ($this->verifyAccessToItem)($file_parent_folders, $shared);
-
- // Get requested files
- $files = File::whereUserId($shared->user_id)
- ->whereIn('id', $request->items)
- ->get();
-
- // Create zip
- $zip = ($this->zipFiles)($files, $shared);
-
- ($this->recordDownload)(
- file_size: $zip->predictZipSize(),
- user_id: $shared->user_id,
- );
-
- return $zip;
- }
-}
diff --git a/src/Domain/Zip/Controllers/VisitorZipFolderController.php b/src/Domain/Zip/Controllers/VisitorZipFolderController.php
deleted file mode 100644
index e588e415..00000000
--- a/src/Domain/Zip/Controllers/VisitorZipFolderController.php
+++ /dev/null
@@ -1,54 +0,0 @@
-protectShareRecord)($shared);
-
- // Check access to requested folder
- ($this->verifyAccessToItem)($id, $shared);
-
- // Get folder
- $folder = Folder::whereUserId($shared->user_id)
- ->where('id', $id);
-
- if (! $folder->exists()) {
- abort(404, "Requested folder doesn't exists.");
- }
-
- // Create zip
- $zip = ($this->zipFolder)($id, $shared);
-
- ($this->recordDownload)(
- file_size: $zip->predictZipSize(),
- user_id: $shared->user_id,
- );
-
- return $zip;
- }
-}
diff --git a/src/Domain/Zip/Controllers/ZipController.php b/src/Domain/Zip/Controllers/ZipController.php
index 0a83818d..7c5917c7 100644
--- a/src/Domain/Zip/Controllers/ZipController.php
+++ b/src/Domain/Zip/Controllers/ZipController.php
@@ -5,9 +5,8 @@ namespace Domain\Zip\Controllers;
use App\Http\Controllers\Controller;
-use Domain\Files\Models\File;
-use Domain\Folders\Models\Folder;
use Domain\Traffic\Actions\RecordDownloadAction;
+use Domain\Zip\Actions\GetItemsListFromUrlParamAction;
use Domain\Zip\Actions\ZipAction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@@ -18,40 +17,15 @@ class ZipController extends Controller
public function __construct(
public ZipAction $zip,
public RecordDownloadAction $recordDownload,
+ public GetItemsListFromUrlParamAction $getItemsListFromUrlParam,
) {}
public function __invoke(
Request $request,
): ZipStream {
-
$user_id = Auth::id();
- $items = explode(',', $request->get('items'));
- $itemList = collect($items)
- ->map(function ($chunk) {
- $items = explode('|', $chunk);
-
- return [
- 'id' => $items[0],
- 'type' => $items[1],
- ];
- });
-
- $folderIds = $itemList
- ->where('type', 'folder')
- ->pluck('id');
-
- $fileIds = $itemList
- ->where('type', 'file')
- ->pluck('id');
-
- $folders = Folder::whereUserId($user_id)
- ->whereIn('id', $folderIds)
- ->get();
-
- $files = File::whereUserId($user_id)
- ->whereIn('id', $fileIds)
- ->get();
+ list($folders, $files) = ($this->getItemsListFromUrlParam)($user_id);
$zip = ($this->zip)($folders, $files);
diff --git a/tests/Domain/Zip/SharedZippingTest.php b/tests/Domain/Zip/SharedZippingTest.php
index 17ef09bb..4cb0e4fd 100644
--- a/tests/Domain/Zip/SharedZippingTest.php
+++ b/tests/Domain/Zip/SharedZippingTest.php
@@ -1,10 +1,10 @@
create();
- $folder = Folder::factory(Folder::class)
+ $sharedFolder = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
]);
+ $folder = Folder::factory(Folder::class)
+ ->create([
+ 'user_id' => $user->id,
+ 'parent_id' => $sharedFolder->id,
+ ]);
+
collect([0, 1])
->each(function ($index) use ($folder, $user) {
$file = UploadedFile::fake()
- ->create(Str::random() . "-fake-file-$index.pdf", 1000, 'application/pdf');
+ ->create("fake-inner-file-$index.pdf", 1200, 'application/pdf');
Storage::putFileAs("files/$user->id", $file, $file->name);
@@ -46,14 +52,35 @@ class SharedZippingTest extends TestCase
]);
});
+ collect([0, 1])
+ ->each(function ($index) use ($sharedFolder, $user) {
+ $file = UploadedFile::fake()
+ ->create(Str::random() . "-fake-file-$index.pdf", 1000, 'application/pdf');
+
+ Storage::putFileAs("files/$user->id", $file, $file->name);
+
+ File::factory(File::class)
+ ->create([
+ 'filesize' => $file->getSize(),
+ 'folder_id' => $sharedFolder->id,
+ 'user_id' => $user->id,
+ 'basename' => $file->name,
+ 'name' => "fake-file-$index.pdf",
+ ]);
+ });
+
$share = Share::factory(Share::class)
->create([
- 'item_id' => $folder->id,
+ 'item_id' => $sharedFolder->id,
'user_id' => $user->id,
'type' => 'folder',
'is_protected' => $is_protected,
]);
+ $files = File::all()
+ ->pluck('id')
+ ->toArray();
+
// Check shared item protected by password
if ($is_protected) {
$cookie = ['share_session' => json_encode([
@@ -63,24 +90,18 @@ class SharedZippingTest extends TestCase
$this
->withUnencryptedCookies($cookie)
- ->post("/api/zip/files/$share->token", [
- 'items' => File::all()->pluck('id'),
- ])->assertStatus(201);
+ ->get("/api/zip/{$share->token}?items=$files[0]|file,$files[1]|file,$folder->id|folder")
+ ->assertStatus(200)
+ ->assertHeader('content-type', 'application/x-zip');
}
// Check public shared item
- if (! $is_protected) {
- $this->postJson("/api/zip/files/$share->token", [
- 'items' => File::all()->pluck('id'),
- ])->assertStatus(201);
+ if (!$is_protected) {
+ $this
+ ->get("/api/zip/{$share->token}?items=$files[0]|file,$files[1]|file,$folder->id|folder")
+ ->assertStatus(200)
+ ->assertHeader('content-type', 'application/x-zip');
}
-
- $this->assertDatabaseHas('zips', [
- 'user_id' => $user->id,
- 'shared_token' => $share->token,
- ]);
-
- Storage::assertExists('zip/' . Zip::first()->basename);
});
}
@@ -119,6 +140,10 @@ class SharedZippingTest extends TestCase
'is_protected' => $is_protected,
]);
+ $files = File::all()
+ ->pluck('id')
+ ->toArray();
+
// Check shared item protected by password
if ($is_protected) {
$cookie = ['share_session' => json_encode([
@@ -128,17 +153,18 @@ class SharedZippingTest extends TestCase
$this
->withUnencryptedCookies($cookie)
- ->post("/api/zip/files/$share->token", [
- 'items' => File::all()->pluck('id'),
- ])->assertStatus(403);
+ ->get("/api/zip/$share->token?items=$files[0]|file,$files[1]|file")
+ ->assertStatus(403);
}
// Check public shared item
- if (! $is_protected) {
- $this->postJson("/api/zip/files/$share->token", [
- 'items' => File::all()->pluck('id'),
- ])->assertStatus(403);
+ if (!$is_protected) {
+ $this
+ ->get("/api/zip/$share->token?items=$files[0]|file,$files[1]|file")
+ ->assertStatus(403);
}
+
+ File::all()->each(fn ($file) => $file->delete());
});
}
@@ -198,25 +224,15 @@ class SharedZippingTest extends TestCase
$this
->withUnencryptedCookies($cookie)
- ->get("/api/zip/folder/$children->id/$share->token")
- ->assertStatus(201);
+ ->get("/api/zip/$share->token?items=$children->id|folder")
+ ->assertStatus(200);
}
// Check public shared item
- if (! $is_protected) {
- $this->getJson("/api/zip/folder/$children->id/$share->token")
- ->assertStatus(201);
+ if (!$is_protected) {
+ $this->getJson("/api/zip/$share->token?items=$children->id|folder")
+ ->assertStatus(200);
}
-
- $this->assertDatabaseHas('zips', [
- 'user_id' => $user->id,
- 'shared_token' => $share->token,
- ]);
-
- Zip::all()
- ->each(function ($zip) {
- Storage::assertExists("zip/$zip->basename");
- });
});
}
@@ -252,13 +268,13 @@ class SharedZippingTest extends TestCase
$this
->withUnencryptedCookies($cookie)
- ->get("/api/zip/folder/$folder->id/$share->token")
+ ->get("/api/zip/$share->token?items=$folder->id|folder")
->assertStatus(403);
}
// Check public shared item
- if (! $is_protected) {
- $this->getJson("/api/zip/folder/$folder->id/$share->token")
+ if (!$is_protected) {
+ $this->getJson("/api/zip/$share->token?items=$folder->id|folder")
->assertStatus(403);
}
});