mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-28 02:50:39 +00:00
- public sharing refactored part 1
This commit is contained in:
@@ -27,12 +27,10 @@ class BrowseShareController extends Controller
|
|||||||
* @param Share $shared
|
* @param Share $shared
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function get_public_folders($id, Share $shared)
|
public function browse_folder($id, Share $shared)
|
||||||
{
|
{
|
||||||
// Abort if folder is protected
|
// Check ability to access protected share record
|
||||||
if ($shared->is_protected) {
|
$this->helper->check_protected_share_record($shared);
|
||||||
abort(403, "Sorry, you don't have permission");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if user can get directory
|
// Check if user can get directory
|
||||||
$this->helper->check_item_access($id, $shared);
|
$this->helper->check_item_access($id, $shared);
|
||||||
@@ -57,12 +55,10 @@ class BrowseShareController extends Controller
|
|||||||
* @param Share $shared
|
* @param Share $shared
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function search_public(Request $request, Share $shared)
|
public function search(Request $request, Share $shared)
|
||||||
{
|
{
|
||||||
// Abort if folder is protected
|
// Check ability to access protected share record
|
||||||
if ($shared->is_protected) {
|
$this->helper->check_protected_share_record($shared);
|
||||||
abort(403, "Sorry, you don't have permission");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search files id db
|
// Search files id db
|
||||||
$searched_files = File::search($request->input('query'))
|
$searched_files = File::search($request->input('query'))
|
||||||
@@ -108,8 +104,11 @@ class BrowseShareController extends Controller
|
|||||||
* @param Share $shared
|
* @param Share $shared
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function get_public_navigation_tree(Share $shared)
|
public function navigation_tree(Share $shared)
|
||||||
{
|
{
|
||||||
|
// Check ability to access protected share record
|
||||||
|
$this->helper->check_protected_share_record($shared);
|
||||||
|
|
||||||
// Check if user can get directory
|
// Check if user can get directory
|
||||||
$this->helper->check_item_access($shared->item_id, $shared);
|
$this->helper->check_item_access($shared->item_id, $shared);
|
||||||
|
|
||||||
|
|||||||
@@ -54,15 +54,14 @@ class FileSharedAccessController extends Controller
|
|||||||
* Get file public
|
* Get file public
|
||||||
*
|
*
|
||||||
* @param $filename
|
* @param $filename
|
||||||
|
* @param $permission
|
||||||
* @param Share $shared
|
* @param Share $shared
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function get_file_public($filename, Share $shared)
|
public function get_file_public($filename, $permission, Share $shared)
|
||||||
{
|
{
|
||||||
// Abort if shared is protected
|
// Check ability to access protected share files
|
||||||
if ($shared->is_protected) {
|
$this->helper->check_protected_share_record($shared, $permission);
|
||||||
abort(403, "Sorry, you don't have permission");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file record
|
// Get file record
|
||||||
$file = UserFile::where('user_id', $shared->user_id)
|
$file = UserFile::where('user_id', $shared->user_id)
|
||||||
@@ -86,15 +85,14 @@ class FileSharedAccessController extends Controller
|
|||||||
* Get public image thumbnail
|
* Get public image thumbnail
|
||||||
*
|
*
|
||||||
* @param $filename
|
* @param $filename
|
||||||
|
* @param $permission
|
||||||
* @param Share $shared
|
* @param Share $shared
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function get_thumbnail_public($filename, Share $shared)
|
public function get_thumbnail_public($filename, $permission, Share $shared)
|
||||||
{
|
{
|
||||||
// Abort if thumbnail is protected
|
// Check ability to access protected share files
|
||||||
if ($shared->is_protected) {
|
$this->helper->check_protected_share_record($shared, $permission);
|
||||||
abort(403, "Sorry, you don't have permission");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file record
|
// Get file record
|
||||||
$file = UserFile::where('user_id', $shared->user_id)
|
$file = UserFile::where('user_id', $shared->user_id)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Sharing;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Share\AuthenticateShareRequest;
|
use App\Http\Requests\Share\AuthenticateShareRequest;
|
||||||
|
use App\Http\Resources\FileResource;
|
||||||
use App\Http\Resources\ShareResource;
|
use App\Http\Resources\ShareResource;
|
||||||
use App\Models\Share;
|
use App\Models\Share;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
@@ -118,20 +119,17 @@ class ServeSharedController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function file_public(Share $shared)
|
public function file_public(Share $shared)
|
||||||
{
|
{
|
||||||
// Abort if file is protected
|
// Check ability to access protected share files
|
||||||
if ($shared->is_protected) {
|
$this->helper->check_protected_share_record($shared);
|
||||||
abort(403, "Sorry, you don't have permission");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file
|
// Get file
|
||||||
$file = File::where('user_id', $shared->user_id)
|
$file = File::where('user_id', $shared->user_id)
|
||||||
->where('id', $shared->item_id)
|
->where('id', $shared->item_id)
|
||||||
->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']);
|
->firstOrFail();
|
||||||
|
|
||||||
// Set urls
|
// Set access urls
|
||||||
$file->setPublicUrl($shared->token);
|
$file->setPublicUrl($shared->token);
|
||||||
|
|
||||||
// Return record
|
return response(new FileResource($file), 200);
|
||||||
return $file;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class Kernel extends HttpKernel
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $middleware = [
|
protected $middleware = [
|
||||||
|
// \App\Http\Middleware\TrustHosts::class,
|
||||||
\App\Http\Middleware\TrustProxies::class,
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
\Fruitcake\Cors\HandleCors::class,
|
\Fruitcake\Cors\HandleCors::class,
|
||||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
|
|
||||||
class SharedAuth
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle($request, Closure $next)
|
|
||||||
{
|
|
||||||
if (!$request->bearerToken()) {
|
|
||||||
if ($request->hasCookie('shared_access_token')) {
|
|
||||||
|
|
||||||
$shared_access_token = $request->cookie('shared_access_token');
|
|
||||||
|
|
||||||
$request->headers->add(['Authorization' => 'Bearer ' . $shared_access_token]);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class FileResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'data' => [
|
||||||
|
'id' => $this->id,
|
||||||
|
'type' => 'file',
|
||||||
|
'attributes' => [
|
||||||
|
'name' => $this->name,
|
||||||
|
'basename' => $this->basename,
|
||||||
|
'mimetype' => $this->mimetype,
|
||||||
|
'filesize' => $this->filesize,
|
||||||
|
'type' => $this->type,
|
||||||
|
'file_url' => $this->file_url,
|
||||||
|
'thumbnail' => $this->thumbnail,
|
||||||
|
'created_at' => $this->created_at,
|
||||||
|
'updated_at' => $this->created_at,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
|
||||||
|
|
||||||
class GatewayCollection extends ResourceCollection
|
|
||||||
{
|
|
||||||
public $collects = GatewayResource::class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform the resource collection into an array.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function toArray($request)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'data' => $this->collection,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
|
|
||||||
class GatewayResource extends JsonResource
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Transform the resource into an array.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function toArray($request)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'data' => [
|
|
||||||
'id' => (string)$this->id,
|
|
||||||
'type' => 'gateways',
|
|
||||||
'attributes' => [
|
|
||||||
'status' => $this->status,
|
|
||||||
'sandbox' => $this->sandbox,
|
|
||||||
'name' => $this->name,
|
|
||||||
'slug' => $this->slug,
|
|
||||||
'logo' => $this->logo,
|
|
||||||
'client_id' => $this->client_id,
|
|
||||||
'secret' => $this->secret,
|
|
||||||
'webhook' => $this->webhook,
|
|
||||||
'payment_processed' => $this->payment_processed,
|
|
||||||
'optional' => $this->optional,
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+7
-7
@@ -94,9 +94,9 @@ class File extends Model
|
|||||||
public function getThumbnailAttribute()
|
public function getThumbnailAttribute()
|
||||||
{
|
{
|
||||||
// Get thumbnail from external storage
|
// Get thumbnail from external storage
|
||||||
if ($this->attributes['thumbnail'] && is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
|
if ($this->attributes['thumbnail'] && ! is_storage_driver(['local'])) {
|
||||||
|
|
||||||
return Storage::temporaryUrl('file-manager/' . $this->attributes['thumbnail'], now()->addHour());
|
return Storage::temporaryUrl('files/' . $this->attributes['thumbnail'], now()->addHour());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get thumbnail from local storage
|
// Get thumbnail from local storage
|
||||||
@@ -106,7 +106,7 @@ class File extends Model
|
|||||||
$route = route('thumbnail', ['name' => $this->attributes['thumbnail']]);
|
$route = route('thumbnail', ['name' => $this->attributes['thumbnail']]);
|
||||||
|
|
||||||
if ($this->public_access) {
|
if ($this->public_access) {
|
||||||
return $route . '/public/' . $this->public_access;
|
return "$route/$this->public_access";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $route;
|
return $route;
|
||||||
@@ -123,7 +123,7 @@ class File extends Model
|
|||||||
public function getFileUrlAttribute()
|
public function getFileUrlAttribute()
|
||||||
{
|
{
|
||||||
// Get file from external storage
|
// Get file from external storage
|
||||||
if (is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
|
if (! is_storage_driver(['local'])) {
|
||||||
|
|
||||||
$file_pretty_name = is_storage_driver('backblaze')
|
$file_pretty_name = is_storage_driver('backblaze')
|
||||||
? Str::snake(mb_strtolower($this->attributes['name']))
|
? Str::snake(mb_strtolower($this->attributes['name']))
|
||||||
@@ -144,7 +144,7 @@ class File extends Model
|
|||||||
$route = route('file', ['name' => $this->attributes['basename']]);
|
$route = route('file', ['name' => $this->attributes['basename']]);
|
||||||
|
|
||||||
if ($this->public_access) {
|
if ($this->public_access) {
|
||||||
return $route . '/public/' . $this->public_access;
|
return "$route/$this->public_access";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $route;
|
return $route;
|
||||||
@@ -198,8 +198,8 @@ class File extends Model
|
|||||||
{
|
{
|
||||||
parent::boot();
|
parent::boot();
|
||||||
|
|
||||||
static::creating(function ($model) {
|
static::creating(function ($file) {
|
||||||
$model->id = (string)Str::uuid();
|
$file->id = (string)Str::uuid();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
Schema::defaultStringLength(191);
|
|
||||||
|
|
||||||
$get_time_locale = App::getLocale() . '_' . mb_strtoupper(App::getLocale());
|
$get_time_locale = App::getLocale() . '_' . mb_strtoupper(App::getLocale());
|
||||||
|
|
||||||
// Set locale for carbon dates
|
// Set locale for carbon dates
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ namespace App\Services;
|
|||||||
|
|
||||||
use App\Models\File;
|
use App\Models\File;
|
||||||
use App\Models\Folder;
|
use App\Models\Folder;
|
||||||
|
use App\Models\Share;
|
||||||
use Aws\Exception\MultipartUploadException;
|
use Aws\Exception\MultipartUploadException;
|
||||||
use Aws\S3\MultipartUploader;
|
use Aws\S3\MultipartUploader;
|
||||||
use DB;
|
use DB;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
@@ -291,4 +293,34 @@ class HelperService
|
|||||||
|
|
||||||
return [$folders, $files];
|
return [$folders, $files];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Share $shared
|
||||||
|
*/
|
||||||
|
function check_protected_share_record(Share $shared): void
|
||||||
|
{
|
||||||
|
if ($shared->is_protected) {
|
||||||
|
|
||||||
|
$abort_message = "Sorry, you don't have permission";
|
||||||
|
|
||||||
|
if (!request()->hasCookie('share_session')) {
|
||||||
|
abort(403, $abort_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get shared session
|
||||||
|
$share_session = json_decode(
|
||||||
|
request()->cookie('share_session')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if is requested same share record
|
||||||
|
if ($share_session->token !== $shared->token) {
|
||||||
|
abort(403, $abort_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if share record was authenticated previously via ServeSharedController@authenticate
|
||||||
|
if (!$share_session->authenticated) {
|
||||||
|
abort(403, $abort_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,8 @@ class CreateFileManagerFolders extends Migration
|
|||||||
$table->text('name');
|
$table->text('name');
|
||||||
$table->string('color')->nullable();
|
$table->string('color')->nullable();
|
||||||
$table->longText('emoji')->nullable();
|
$table->longText('emoji')->nullable();
|
||||||
|
|
||||||
|
// TODO: upravit user scope
|
||||||
$table->enum('user_scope', ['master', 'editor', 'visitor'])->default('master');
|
$table->enum('user_scope', ['master', 'editor', 'visitor'])->default('master');
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ class CreateFileManagerFiles extends Migration
|
|||||||
|
|
||||||
$table->text('type')->nullable();
|
$table->text('type')->nullable();
|
||||||
$table->longText('metadata')->nullable();
|
$table->longText('metadata')->nullable();
|
||||||
|
|
||||||
|
// TODO: upravit user scope
|
||||||
$table->enum('user_scope', ['master', 'editor', 'visitor'])->default('master');
|
$table->enum('user_scope', ['master', 'editor', 'visitor'])->default('master');
|
||||||
|
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<iframe src="http://localhost:8000/sign-in" width="450" height="900" frameborder="1"></iframe>
|
||||||
|
<iframe src="https://demo.vuefilemanager.com/sign-in" width="450" height="900" frameborder="1"></iframe>
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=c6b88005b133268ed88f",
|
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=c6b88005b133268ed88f",
|
||||||
"/chunks/shared.js": "/chunks/shared.js?id=2c38f535d52e0e448846",
|
"/chunks/shared.js": "/chunks/shared.js?id=2c38f535d52e0e448846",
|
||||||
"/chunks/shared-files.js": "/chunks/shared-files.js?id=e6f7de2910d85a2dd3e4",
|
"/chunks/shared-files.js": "/chunks/shared-files.js?id=e6f7de2910d85a2dd3e4",
|
||||||
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=9024f3b0b3bed191fe8d",
|
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=f6155ac74f9bb460cf65",
|
||||||
"/chunks/shared/file-browser.js": "/chunks/shared/file-browser.js?id=3127fab4cfd3d5f00a72",
|
"/chunks/shared/file-browser.js": "/chunks/shared/file-browser.js?id=3127fab4cfd3d5f00a72",
|
||||||
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=298e41c1c453bf1fde9b",
|
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=298e41c1c453bf1fde9b",
|
||||||
"/chunks/sign-in.js": "/chunks/sign-in.js?id=af61663f3e69eae3e5ee",
|
"/chunks/sign-in.js": "/chunks/sign-in.js?id=af61663f3e69eae3e5ee",
|
||||||
@@ -88,5 +88,13 @@
|
|||||||
"/chunks/users.js": "/chunks/users.js?id=9085e0306eafce8f9fce",
|
"/chunks/users.js": "/chunks/users.js?id=9085e0306eafce8f9fce",
|
||||||
"/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~68e3c6cf.js": "/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~68e3c6cf.js?id=b490efdc8470a6c2f625",
|
"/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~68e3c6cf.js": "/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~68e3c6cf.js?id=b490efdc8470a6c2f625",
|
||||||
"/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~a4a4a595.js": "/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~a4a4a595.js?id=be99c10088b00578891b",
|
"/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~a4a4a595.js": "/vendors~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-i~a4a4a595.js?id=be99c10088b00578891b",
|
||||||
"/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3"
|
"/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3",
|
||||||
|
"/js/main.723fdf599ac2ecb35271.hot-update.js": "/js/main.723fdf599ac2ecb35271.hot-update.js",
|
||||||
|
"/js/main.4a8fc01e2ff5a4e6ad28.hot-update.js": "/js/main.4a8fc01e2ff5a4e6ad28.hot-update.js",
|
||||||
|
"/js/main.83e4a1fba24fb3ed581d.hot-update.js": "/js/main.83e4a1fba24fb3ed581d.hot-update.js",
|
||||||
|
"/js/main.4cd1727b0d5ad436dba4.hot-update.js": "/js/main.4cd1727b0d5ad436dba4.hot-update.js",
|
||||||
|
"/js/main.7e6541d1cbf9901a3e5a.hot-update.js": "/js/main.7e6541d1cbf9901a3e5a.hot-update.js",
|
||||||
|
"/js/main.51418924870a080afea3.hot-update.js": "/js/main.51418924870a080afea3.hot-update.js",
|
||||||
|
"/js/main.869d3fad73dd6fe243f9.hot-update.js": "/js/main.869d3fad73dd6fe243f9.hot-update.js",
|
||||||
|
"/js/main.d7f2bec845fc64b7d5e4.hot-update.js": "/js/main.d7f2bec845fc64b7d5e4.hot-update.js"
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-10
@@ -154,12 +154,16 @@ const actions = {
|
|||||||
// Get route
|
// Get route
|
||||||
let route = undefined
|
let route = undefined
|
||||||
|
|
||||||
if (getters.sharedDetail && getters.sharedDetail.is_protected)
|
if (getters.sharedDetail) {
|
||||||
route = '/api/browse/search/private'
|
let permission = getters.sharedDetail.is_protected
|
||||||
else if (getters.sharedDetail && !getters.sharedDetail.is_protected)
|
? 'private'
|
||||||
route = '/api/browse/search/public/' + router.currentRoute.params.token
|
: 'public'
|
||||||
else
|
|
||||||
|
route = `/api/browse/search/${permission}/${router.currentRoute.params.token}`
|
||||||
|
|
||||||
|
} else {
|
||||||
route = '/api/browse/search'
|
route = '/api/browse/search'
|
||||||
|
}
|
||||||
|
|
||||||
axios
|
axios
|
||||||
.get(route, {
|
.get(route, {
|
||||||
@@ -177,12 +181,11 @@ const actions = {
|
|||||||
// Get route
|
// Get route
|
||||||
let route = undefined
|
let route = undefined
|
||||||
|
|
||||||
if (getters.sharedDetail && getters.sharedDetail.is_protected)
|
if (getters.sharedDetail) {
|
||||||
route = '/api/browse/navigation/private'
|
route = `/api/browse/navigation/${router.currentRoute.params.token}`
|
||||||
else if (getters.sharedDetail && !getters.sharedDetail.is_protected)
|
} else {
|
||||||
route = '/api/browse/navigation/public/' + router.currentRoute.params.token
|
|
||||||
else
|
|
||||||
route = '/api/browse/navigation'
|
route = '/api/browse/navigation'
|
||||||
|
}
|
||||||
|
|
||||||
axios
|
axios
|
||||||
.get(route + getters.sorting.URI)
|
.get(route + getters.sorting.URI)
|
||||||
|
|||||||
+16
-18
@@ -22,10 +22,9 @@ const actions = {
|
|||||||
message: i18n.t('popup_zipping.message')
|
message: i18n.t('popup_zipping.message')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Get route
|
let route = getters.sharedDetail
|
||||||
let route = getters.sharedDetail && !getters.sharedDetail.is_protected
|
? `/api/zip/folder/${folder.id}/${router.currentRoute.params.token}`
|
||||||
? '/api/zip/folder/' + folder.id + '/public/' + router.currentRoute.params.token
|
: `/api/zip/folder/${folder.id}`
|
||||||
: '/api/zip/folder/' + folder.id
|
|
||||||
|
|
||||||
axios.get(route)
|
axios.get(route)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
@@ -37,7 +36,6 @@ const actions = {
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
commit('PROCESSING_POPUP', undefined)
|
commit('PROCESSING_POPUP', undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
downloadFiles: ({commit, getters}) => {
|
downloadFiles: ({commit, getters}) => {
|
||||||
let files = []
|
let files = []
|
||||||
@@ -46,8 +44,8 @@ const actions = {
|
|||||||
getters.fileInfoDetail.forEach(file => files.push(file.id))
|
getters.fileInfoDetail.forEach(file => files.push(file.id))
|
||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = getters.sharedDetail && !getters.sharedDetail.is_protected
|
let route = getters.sharedDetail
|
||||||
? '/api/zip/files/public/' + router.currentRoute.params.token
|
? `/api/zip/files/${router.currentRoute.params.token}`
|
||||||
: '/api/zip/files'
|
: '/api/zip/files'
|
||||||
|
|
||||||
commit('PROCESSING_POPUP', {
|
commit('PROCESSING_POPUP', {
|
||||||
@@ -87,8 +85,8 @@ const actions = {
|
|||||||
commit('CLEAR_FILEINFO_DETAIL')
|
commit('CLEAR_FILEINFO_DETAIL')
|
||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = getters.sharedDetail && !getters.sharedDetail.is_protected
|
let route = getters.sharedDetail
|
||||||
? '/api/editor/move/public/' + router.currentRoute.params.token
|
? `/api/editor/move/${router.currentRoute.params.token}`
|
||||||
: '/api/move'
|
: '/api/move'
|
||||||
|
|
||||||
console.log(to_item);
|
console.log(to_item);
|
||||||
@@ -114,8 +112,8 @@ const actions = {
|
|||||||
createFolder: ({commit, getters, dispatch}, folder) => {
|
createFolder: ({commit, getters, dispatch}, folder) => {
|
||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = getters.sharedDetail && !getters.sharedDetail.is_protected
|
let route = getters.sharedDetail
|
||||||
? '/api/editor/create-folder/public/' + router.currentRoute.params.token
|
? `/api/editor/create-folder/${router.currentRoute.params.token}`
|
||||||
: '/api/create-folder'
|
: '/api/create-folder'
|
||||||
|
|
||||||
axios
|
axios
|
||||||
@@ -149,9 +147,9 @@ const actions = {
|
|||||||
commit('UPDATE_NAME_IN_FAVOURITES', data)
|
commit('UPDATE_NAME_IN_FAVOURITES', data)
|
||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = getters.sharedDetail && !getters.sharedDetail.is_protected
|
let route = getters.sharedDetail
|
||||||
? '/api/editor/rename/' + data.id + '/public/' + router.currentRoute.params.token
|
? `/api/editor/rename/${data.id}/${router.currentRoute.params.token}`
|
||||||
: '/api/rename/' + data.id
|
: `/api/rename/${data.id}`
|
||||||
|
|
||||||
axios
|
axios
|
||||||
.post(route, {
|
.post(route, {
|
||||||
@@ -172,8 +170,8 @@ const actions = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = getters.sharedDetail && !getters.sharedDetail.is_protected
|
let route = getters.sharedDetail
|
||||||
? '/api/editor/upload/public/' + router.currentRoute.params.token
|
? `/api/editor/upload/${router.currentRoute.params.token}`
|
||||||
: '/api/upload'
|
: '/api/upload'
|
||||||
|
|
||||||
// Create cancel token for axios cancellation
|
// Create cancel token for axios cancellation
|
||||||
@@ -341,8 +339,8 @@ const actions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = getters.sharedDetail && !getters.sharedDetail.is_protected
|
let route = getters.sharedDetail
|
||||||
? '/api/editor/remove/public/' + router.currentRoute.params.token
|
? `/api/editor/remove/${router.currentRoute.params.token}`
|
||||||
: '/api/remove'
|
: '/api/remove'
|
||||||
|
|
||||||
axios
|
axios
|
||||||
|
|||||||
+27
-36
@@ -38,13 +38,9 @@ const actions = {
|
|||||||
|
|
||||||
payload.folder.location = 'public'
|
payload.folder.location = 'public'
|
||||||
|
|
||||||
let route = getters.sharedDetail.is_protected
|
|
||||||
? '/api/browse/folders/' + payload.folder.id + '/private'
|
|
||||||
: '/api/browse/folders/' + payload.folder.id + '/public/' + router.currentRoute.params.token
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios
|
axios
|
||||||
.get(route + getters.sorting.URI)
|
.get(`/api/browse/folders/${payload.folder.id}/${router.currentRoute.params.token}${getters.sorting.URI}`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
commit('LOADING_STATE', {loading: false, data: response.data})
|
commit('LOADING_STATE', {loading: false, data: response.data})
|
||||||
commit('STORE_CURRENT_FOLDER', payload.folder)
|
commit('STORE_CURRENT_FOLDER', payload.folder)
|
||||||
@@ -66,6 +62,32 @@ const actions = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
getSingleFile: ({commit}) => {
|
||||||
|
|
||||||
|
axios.get(`/api/browse/file/${router.currentRoute.params.token}`)
|
||||||
|
.then(response => {
|
||||||
|
commit('STORE_SHARED_FILE', response.data)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getShareDetail: ({commit, state}, token) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios
|
||||||
|
.get(`/api/browse/share/${token}`)
|
||||||
|
.then(response => {
|
||||||
|
resolve(response)
|
||||||
|
|
||||||
|
// Commit shared item options
|
||||||
|
commit('SET_SHARED_DETAIL', response.data.data.attributes)
|
||||||
|
commit('SET_PERMISSION', response.data.data.attributes.permission)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
reject(error)
|
||||||
|
|
||||||
|
if (error.response.status == 404)
|
||||||
|
router.push({name: 'NotFound'})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
shareCancel: ({commit, getters}, singleItem) => {
|
shareCancel: ({commit, getters}, singleItem) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
@@ -109,37 +131,6 @@ const actions = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getSingleFile: ({commit, state}) => {
|
|
||||||
|
|
||||||
let route = state.sharedDetail.is_protected
|
|
||||||
? '/api/browse/files/private'
|
|
||||||
: '/api/browse/files/' + router.currentRoute.params.token + '/public'
|
|
||||||
|
|
||||||
axios.get(route)
|
|
||||||
.then(response => {
|
|
||||||
commit('STORE_SHARED_FILE', response.data)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getShareDetail: ({commit, state}, token) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.get(`/api/browse/shared/${token}`)
|
|
||||||
.then(response => {
|
|
||||||
resolve(response)
|
|
||||||
|
|
||||||
// Commit shared item options
|
|
||||||
commit('SET_SHARED_DETAIL', response.data.data.attributes)
|
|
||||||
commit('SET_PERMISSION', response.data.data.attributes.permission)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(error)
|
|
||||||
|
|
||||||
if (error.response.status == 404) {
|
|
||||||
router.push({name: 'NotFound'})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
const mutations = {
|
const mutations = {
|
||||||
SET_SHARED_DETAIL(state, data) {
|
SET_SHARED_DETAIL(state, data) {
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ const actions = {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
logOut: ({getters, commit}) => {
|
logOut: ({commit}) => {
|
||||||
|
|
||||||
let popup = setTimeout(() => {
|
let popup = setTimeout(() => {
|
||||||
commit('PROCESSING_POPUP', {
|
commit('PROCESSING_POPUP', {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
password: undefined,
|
password: 'secret',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -61,9 +61,18 @@
|
|||||||
axios
|
axios
|
||||||
.post('/api/browse/authenticate/' + this.$route.params.token, {
|
.post('/api/browse/authenticate/' + this.$route.params.token, {
|
||||||
password: this.password
|
password: this.password
|
||||||
}).then(() => {
|
})
|
||||||
|
.then(response => {
|
||||||
|
|
||||||
// todo: Redirect to file browser page
|
// Show file browser
|
||||||
|
if (response.data.data.attributes.type === 'folder' && this.$router.currentRoute.name !== 'SharedFileBrowser') {
|
||||||
|
this.$router.push({name: 'SharedFileBrowser'})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show single file
|
||||||
|
if (response.data.data.attributes.type !== 'folder' && this.$router.currentRoute.name !== 'SharedSingleFile') {
|
||||||
|
this.$router.push({name: 'SharedSingleFile'})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@ Route::get('/avatars/{avatar}', [FileAccessController::class, 'get_avatar'])->na
|
|||||||
Route::get('/system/{image}', [FileAccessController::class, 'get_system_image']);
|
Route::get('/system/{image}', [FileAccessController::class, 'get_system_image']);
|
||||||
|
|
||||||
// Get public thumbnails and files
|
// Get public thumbnails and files
|
||||||
Route::get('/thumbnail/{name}/public/{shared}', [FileSharedAccessController::class, 'get_thumbnail_public']);
|
Route::get('/thumbnail/{name}/{shared}', [FileSharedAccessController::class, 'get_thumbnail_public']);
|
||||||
Route::get('/file/{name}/public/{shared}', [FileSharedAccessController::class, 'get_file_public']);
|
Route::get('/file/{name}/{shared}', [FileSharedAccessController::class, 'get_file_public']);
|
||||||
Route::get('/zip/{id}/public/{token}', [FileSharedAccessController::class, 'get_zip_public'])->name('zip_public');
|
Route::get('/zip/{id}/public/{token}', [FileSharedAccessController::class, 'get_zip_public'])->name('zip_public');
|
||||||
|
|
||||||
// User master,editor,visitor access to image thumbnails and file downloads
|
// User master,editor,visitor access to image thumbnails and file downloads
|
||||||
|
|||||||
+14
-23
@@ -6,39 +6,30 @@ use App\Http\Controllers\Sharing\EditShareItemsController;
|
|||||||
use App\Http\Controllers\FileManager\ShareController;
|
use App\Http\Controllers\FileManager\ShareController;
|
||||||
use App\Http\Controllers\Sharing\ServeSharedController;
|
use App\Http\Controllers\Sharing\ServeSharedController;
|
||||||
|
|
||||||
// Editor functions
|
// Browse functions
|
||||||
Route::group(['prefix' => 'editor'], function () {
|
Route::group(['prefix' => 'editor'], function () {
|
||||||
Route::post('/create-folder/public/{shared}', [EditShareItemsController::class, 'create_folder']);
|
Route::post('/create-folder/{shared}', [EditShareItemsController::class, 'create_folder']);
|
||||||
Route::patch('/rename/{id}/public/{shared}', [EditShareItemsController::class, 'rename_item']);
|
Route::patch('/rename/{id}/{shared}', [EditShareItemsController::class, 'rename_item']);
|
||||||
Route::post('/remove/public/{shared}', [EditShareItemsController::class, 'delete_item']);
|
Route::post('/remove/{shared}', [EditShareItemsController::class, 'delete_item']);
|
||||||
Route::post('/upload/public/{shared}', [EditShareItemsController::class, 'upload']);
|
Route::post('/upload/{shared}', [EditShareItemsController::class, 'upload']);
|
||||||
Route::post('/move/public/{shared}', [EditShareItemsController::class, 'move']);
|
Route::post('/move/{shared}', [EditShareItemsController::class, 'move']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Editor/Visitor zip functions
|
// Zip shared items
|
||||||
Route::group(['prefix' => 'zip'], function () {
|
Route::group(['prefix' => 'zip'], function () {
|
||||||
Route::post('/files/public/{shared}', [EditShareItemsController::class, 'zip_multiple_files']);
|
Route::post('/files/{shared}', [EditShareItemsController::class, 'zip_multiple_files']);
|
||||||
Route::get('/folder/{id}/public/{shared}', [EditShareItemsController::class, 'zip_folder']);
|
Route::get('/folder/{id}/{shared}', [EditShareItemsController::class, 'zip_folder']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Browse share content
|
// Browse share content
|
||||||
Route::group(['prefix' => 'browse'], function () {
|
Route::group(['prefix' => 'browse'], function () {
|
||||||
Route::get('/navigation/public/{shared}', [BrowseShareController::class, 'get_public_navigation_tree']);
|
Route::get('/navigation/{shared}', [BrowseShareController::class, 'navigation_tree']);
|
||||||
Route::get('/folders/{id}/public/{shared}', [BrowseShareController::class, 'get_public_folders']);
|
Route::get('/folders/{id}/{shared}', [BrowseShareController::class, 'browse_folder']);
|
||||||
Route::get('/search/public/{shared}', [BrowseShareController::class, 'search_public']);
|
Route::get('/search/{shared}', [BrowseShareController::class, 'search']);
|
||||||
|
|
||||||
Route::post('/authenticate/{shared}', [ServeSharedController::class, 'authenticate']);
|
Route::post('/authenticate/{shared}', [ServeSharedController::class, 'authenticate']);
|
||||||
Route::get('/files/{shared}/public', [ServeSharedController::class, 'file_public']);
|
Route::get('/file/{shared}', [ServeSharedController::class, 'file_public']);
|
||||||
Route::get('/shared/{shared}', [ShareController::class, 'show']);
|
Route::get('/share/{shared}', [ShareController::class, 'show']);
|
||||||
});
|
|
||||||
|
|
||||||
// Private sharing secured by password
|
|
||||||
// TODO: tests
|
|
||||||
Route::group(['middleware' => ['auth:api', 'auth.shared', 'scope:visitor,editor']], function () {
|
|
||||||
Route::get('/folders/{id}/private', [ServeSharedController::class, 'get_private_folders']);
|
|
||||||
Route::get('/navigation/private', [ServeSharedController::class, 'get_private_navigation_tree']);
|
|
||||||
Route::get('/search/private', [ServeSharedController::class, 'search_private']);
|
|
||||||
Route::get('/files/private', [ServeSharedController::class, 'file_private']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('/og-site/{shared}', [AppFunctionsController::class, 'og_site']);
|
Route::get('/og-site/{shared}', [AppFunctionsController::class, 'og_site']);
|
||||||
+1
-1
@@ -8,7 +8,7 @@ use App\Services\SetupService;
|
|||||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class PrivateShareContentAccessTest extends TestCase
|
class PrivateFilesAccessTest extends TestCase
|
||||||
{
|
{
|
||||||
use DatabaseMigrations;
|
use DatabaseMigrations;
|
||||||
|
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Share;
|
||||||
|
|
||||||
|
use App\Models\File;
|
||||||
|
use App\Models\Folder;
|
||||||
|
use App\Models\Share;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\SetupService;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class PrivateVisitorTest extends TestCase
|
||||||
|
{
|
||||||
|
use DatabaseMigrations;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->setup = app()->make(SetupService::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function authenticated_visitor_get_folder_content()
|
||||||
|
{
|
||||||
|
$user = User::factory(User::class)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$root = Folder::factory(Folder::class)
|
||||||
|
->create([
|
||||||
|
'name' => 'root',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$share = Share::factory(Share::class)
|
||||||
|
->create([
|
||||||
|
'item_id' => $root->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'type' => 'folder',
|
||||||
|
'is_protected' => true,
|
||||||
|
'permission' => 'editor',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$folder = Folder::factory(Folder::class)
|
||||||
|
->create([
|
||||||
|
'parent_id' => $root->id,
|
||||||
|
'name' => 'Documents',
|
||||||
|
"user_scope" => "master",
|
||||||
|
'user_id' => $user->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$file = File::factory(File::class)
|
||||||
|
->create([
|
||||||
|
'folder_id' => $root->id,
|
||||||
|
'name' => 'Document',
|
||||||
|
'basename' => 'document.pdf',
|
||||||
|
"mimetype" => "application/pdf",
|
||||||
|
"user_scope" => "master",
|
||||||
|
"type" => "file",
|
||||||
|
'user_id' => $user->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->withUnencryptedCookie('share_session', json_encode([
|
||||||
|
'token' => $share->token,
|
||||||
|
'authenticated' => true,
|
||||||
|
]))
|
||||||
|
->get("/api/browse/folders/$root->id/private/$share->token")
|
||||||
|
->assertStatus(200)
|
||||||
|
->assertExactJson([
|
||||||
|
[
|
||||||
|
"id" => $folder->id,
|
||||||
|
"user_id" => $user->id,
|
||||||
|
"parent_id" => $root->id,
|
||||||
|
"name" => "Documents",
|
||||||
|
"color" => null,
|
||||||
|
"emoji" => null,
|
||||||
|
"user_scope" => "master",
|
||||||
|
"deleted_at" => null,
|
||||||
|
"created_at" => $folder->created_at,
|
||||||
|
"updated_at" => $folder->updated_at->toJson(),
|
||||||
|
"items" => 0,
|
||||||
|
"trashed_items" => 0,
|
||||||
|
"type" => "folder",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"id" => $file->id,
|
||||||
|
"user_id" => $user->id,
|
||||||
|
"folder_id" => $root->id,
|
||||||
|
"thumbnail" => null,
|
||||||
|
"name" => "Document",
|
||||||
|
"basename" => "document.pdf",
|
||||||
|
"mimetype" => "application/pdf",
|
||||||
|
"filesize" => $file->filesize,
|
||||||
|
"type" => "file",
|
||||||
|
"metadata" => null,
|
||||||
|
"user_scope" => "master",
|
||||||
|
"deleted_at" => null,
|
||||||
|
"created_at" => $file->created_at,
|
||||||
|
"updated_at" => $file->updated_at->toJson(),
|
||||||
|
"file_url" => "http://localhost/file/document.pdf/private/$share->token",
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Share;
|
||||||
|
|
||||||
|
use App\Models\File;
|
||||||
|
use App\Models\Share;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Zip;
|
||||||
|
use App\Services\SetupService;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Illuminate\Support\Facades\Cookie;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Storage;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class PublicFilesAccessTest extends TestCase
|
||||||
|
{
|
||||||
|
use DatabaseMigrations;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->setup = app()->make(SetupService::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_get_public_file_record_and_download_file_within()
|
||||||
|
{
|
||||||
|
Storage::fake('local');
|
||||||
|
|
||||||
|
$this->setup->create_directories();
|
||||||
|
|
||||||
|
collect(['private', 'public'])
|
||||||
|
->each(function ($permission) {
|
||||||
|
|
||||||
|
$user = User::factory(User::class)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$document = UploadedFile::fake()
|
||||||
|
->create(Str::random() . '-fake-file.pdf', 1000, 'application/pdf');
|
||||||
|
|
||||||
|
Storage::putFileAs("files/$user->id", $document, $document->name);
|
||||||
|
|
||||||
|
$file = File::factory(File::class)
|
||||||
|
->create([
|
||||||
|
'filesize' => $document->getSize(),
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'basename' => $document->name,
|
||||||
|
'name' => 'fake-file.pdf',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$share = Share::factory(Share::class)
|
||||||
|
->create([
|
||||||
|
'item_id' => $file->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'type' => 'file',
|
||||||
|
'is_protected' => $permission === 'private',
|
||||||
|
'password' => \Hash::make('secret'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($permission === 'private') {
|
||||||
|
|
||||||
|
$cookie = ['share_session' => json_encode([
|
||||||
|
'token' => $share->token,
|
||||||
|
'authenticated' => true,
|
||||||
|
])];
|
||||||
|
|
||||||
|
$this->disableCookieEncryption();
|
||||||
|
$this->defaultCookies = $cookie;
|
||||||
|
|
||||||
|
$this->get("/api/browse/file/$share->token/private")
|
||||||
|
->assertStatus(200)
|
||||||
|
->assertJsonFragment([
|
||||||
|
'basename' => $document->name
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->get("/file/$document->name/private/$share->token")
|
||||||
|
->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($permission === 'public') {
|
||||||
|
|
||||||
|
$this->get("/api/browse/file/$share->token/public")
|
||||||
|
->assertStatus(200)
|
||||||
|
->assertJsonFragment([
|
||||||
|
'basename' => $document->name
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Get shared file
|
||||||
|
$this->get("/file/$document->name/public/$share->token")
|
||||||
|
->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*$this->assertDatabaseHas('traffic', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
]);*/
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_try_to_get_protected_file_record()
|
||||||
|
{
|
||||||
|
$share = Share::factory(Share::class)
|
||||||
|
->create([
|
||||||
|
'type' => 'file',
|
||||||
|
'is_protected' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Get share record
|
||||||
|
$this->get("/api/browse/file/$share->token/public")
|
||||||
|
->assertStatus(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_get_shared_image()
|
||||||
|
{
|
||||||
|
Storage::fake('local');
|
||||||
|
|
||||||
|
$this->setup->create_directories();
|
||||||
|
|
||||||
|
$user = User::factory(User::class)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$thumbnail = UploadedFile::fake()
|
||||||
|
->image(Str::random() . '-fake-image.jpg');
|
||||||
|
|
||||||
|
Storage::putFileAs("files/$user->id", $thumbnail, $thumbnail->name);
|
||||||
|
|
||||||
|
$file = File::factory(File::class)
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'thumbnail' => $thumbnail->name,
|
||||||
|
'basename' => $thumbnail->name,
|
||||||
|
'name' => 'fake-thumbnail.jpg',
|
||||||
|
'type' => 'image',
|
||||||
|
'mimetype' => 'jpg',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$share = Share::factory(Share::class)
|
||||||
|
->create([
|
||||||
|
'item_id' => $file->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'type' => 'file',
|
||||||
|
'is_protected' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->get("/shared/$share->token")
|
||||||
|
->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_get_public_thumbnail()
|
||||||
|
{
|
||||||
|
Storage::fake('local');
|
||||||
|
|
||||||
|
$this->setup->create_directories();
|
||||||
|
|
||||||
|
collect(['private', 'public'])
|
||||||
|
->each(function ($permission) {
|
||||||
|
|
||||||
|
$user = User::factory(User::class)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$thumbnail = UploadedFile::fake()
|
||||||
|
->image(Str::random() . '-fake-thumbnail.jpg');
|
||||||
|
|
||||||
|
Storage::putFileAs("files/$user->id", $thumbnail, $thumbnail->name);
|
||||||
|
|
||||||
|
$file = File::factory(File::class)
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'thumbnail' => $thumbnail->name,
|
||||||
|
'name' => 'fake-thumbnail.jpg',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$share = Share::factory(Share::class)
|
||||||
|
->create([
|
||||||
|
'item_id' => $file->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'type' => 'file',
|
||||||
|
'is_protected' => $permission === 'private',
|
||||||
|
'password' => \Hash::make('secret'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Get thumbnail file
|
||||||
|
if ($permission === 'private') {
|
||||||
|
$this->withCookie('share_session', json_encode([
|
||||||
|
'token' => $share->token,
|
||||||
|
'authenticated' => true,
|
||||||
|
]))
|
||||||
|
->get("/thumbnail/$thumbnail->name/private/$share->token")
|
||||||
|
->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($permission === 'public') {
|
||||||
|
$this->get("/thumbnail/$thumbnail->name/public/$share->token")
|
||||||
|
->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertDatabaseMissing('traffic', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'download' => null,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_download_publicly_zipped_files()
|
||||||
|
{
|
||||||
|
Storage::fake('local');
|
||||||
|
|
||||||
|
$this->setup->create_directories();
|
||||||
|
|
||||||
|
$user = User::factory(User::class)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$share = Share::factory(Share::class)
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'type' => 'folder',
|
||||||
|
'is_protected' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$zip = Zip::factory(Zip::class)->create([
|
||||||
|
'basename' => 'EHWKcuvKzA4Gv29v-archive.zip',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'shared_token' => $share->token,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()
|
||||||
|
->create($zip->basename, 1000, 'application/zip');
|
||||||
|
|
||||||
|
Storage::putFileAs("zip", $file, $file->name);
|
||||||
|
|
||||||
|
$this->get("/zip/$zip->id/public/$share->token")
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
$this->assertDatabaseMissing('traffic', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'download' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Feature\Share;
|
|
||||||
|
|
||||||
use App\Models\File;
|
|
||||||
use App\Models\Share;
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Zip;
|
|
||||||
use App\Services\SetupService;
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
|
||||||
use Illuminate\Http\UploadedFile;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Storage;
|
|
||||||
use Tests\TestCase;
|
|
||||||
|
|
||||||
class PublicShareContentAccessTest extends TestCase
|
|
||||||
{
|
|
||||||
use DatabaseMigrations;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->setup = app()->make(SetupService::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function it_get_public_file_record_and_download_file_within()
|
|
||||||
{
|
|
||||||
Storage::fake('local');
|
|
||||||
|
|
||||||
$this->setup->create_directories();
|
|
||||||
|
|
||||||
$user = User::factory(User::class)
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$document = UploadedFile::fake()
|
|
||||||
->create(Str::random() . '-fake-file.pdf', 1000, 'application/pdf');
|
|
||||||
|
|
||||||
Storage::putFileAs("files/$user->id", $document, $document->name);
|
|
||||||
|
|
||||||
$file = File::factory(File::class)
|
|
||||||
->create([
|
|
||||||
'filesize' => $document->getSize(),
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'basename' => $document->name,
|
|
||||||
'name' => 'fake-file.pdf',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$share = Share::factory(Share::class)
|
|
||||||
->create([
|
|
||||||
'item_id' => $file->id,
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'type' => 'file',
|
|
||||||
'is_protected' => false,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Get share record
|
|
||||||
$this->get("/api/browse/files/$share->token/public")
|
|
||||||
->assertStatus(200)
|
|
||||||
->assertJsonFragment([
|
|
||||||
'basename' => $document->name
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Get shared file
|
|
||||||
$this->get("/file/$document->name/public/$share->token")
|
|
||||||
->assertStatus(200);
|
|
||||||
|
|
||||||
$this->assertDatabaseHas('traffic', [
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'download' => '1024000',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function it_try_to_get_protected_file_record()
|
|
||||||
{
|
|
||||||
$share = Share::factory(Share::class)
|
|
||||||
->create([
|
|
||||||
'type' => 'file',
|
|
||||||
'is_protected' => true,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Get share record
|
|
||||||
$this->get("/api/browse/files/$share->token/public")
|
|
||||||
->assertStatus(403);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function it_get_shared_image()
|
|
||||||
{
|
|
||||||
Storage::fake('local');
|
|
||||||
|
|
||||||
$this->setup->create_directories();
|
|
||||||
|
|
||||||
$user = User::factory(User::class)
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$thumbnail = UploadedFile::fake()
|
|
||||||
->image(Str::random() . '-fake-image.jpg');
|
|
||||||
|
|
||||||
Storage::putFileAs("files/$user->id", $thumbnail, $thumbnail->name);
|
|
||||||
|
|
||||||
$file = File::factory(File::class)
|
|
||||||
->create([
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'thumbnail' => $thumbnail->name,
|
|
||||||
'basename' => $thumbnail->name,
|
|
||||||
'name' => 'fake-thumbnail.jpg',
|
|
||||||
'type' => 'image',
|
|
||||||
'mimetype' => 'jpg',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$share = Share::factory(Share::class)
|
|
||||||
->create([
|
|
||||||
'item_id' => $file->id,
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'type' => 'file',
|
|
||||||
'is_protected' => false,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->get("/shared/$share->token")
|
|
||||||
->assertStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function it_download_public_thumbnail()
|
|
||||||
{
|
|
||||||
Storage::fake('local');
|
|
||||||
|
|
||||||
$this->setup->create_directories();
|
|
||||||
|
|
||||||
$user = User::factory(User::class)
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$thumbnail = UploadedFile::fake()
|
|
||||||
->image(Str::random() . '-fake-thumbnail.jpg');
|
|
||||||
|
|
||||||
Storage::putFileAs("files/$user->id", $thumbnail, $thumbnail->name);
|
|
||||||
|
|
||||||
$file = File::factory(File::class)
|
|
||||||
->create([
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'thumbnail' => $thumbnail->name,
|
|
||||||
'name' => 'fake-thumbnail.jpg',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$share = Share::factory(Share::class)
|
|
||||||
->create([
|
|
||||||
'item_id' => $file->id,
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'type' => 'file',
|
|
||||||
'is_protected' => false,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Get thumbnail file
|
|
||||||
$this->get("/thumbnail/$thumbnail->name/public/$share->token")
|
|
||||||
->assertStatus(200);
|
|
||||||
|
|
||||||
$this->assertDatabaseMissing('traffic', [
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'download' => null,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function it_download_publicly_zipped_files()
|
|
||||||
{
|
|
||||||
Storage::fake('local');
|
|
||||||
|
|
||||||
$this->setup->create_directories();
|
|
||||||
|
|
||||||
$user = User::factory(User::class)
|
|
||||||
->create();
|
|
||||||
|
|
||||||
$share = Share::factory(Share::class)
|
|
||||||
->create([
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'type' => 'folder',
|
|
||||||
'is_protected' => false,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$zip = Zip::factory(Zip::class)->create([
|
|
||||||
'basename' => 'EHWKcuvKzA4Gv29v-archive.zip',
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'shared_token' => $share->token,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$file = UploadedFile::fake()
|
|
||||||
->create($zip->basename, 1000, 'application/zip');
|
|
||||||
|
|
||||||
Storage::putFileAs("zip", $file, $file->name);
|
|
||||||
|
|
||||||
$this->get("/zip/$zip->id/public/$share->token")
|
|
||||||
->assertStatus(200);
|
|
||||||
|
|
||||||
$this->assertDatabaseMissing('traffic', [
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'download' => null,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,7 @@ use Laravel\Sanctum\Sanctum;
|
|||||||
use Storage;
|
use Storage;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ShareEditorTest extends TestCase
|
class PrivateVisitorTest extends TestCase
|
||||||
{
|
{
|
||||||
use DatabaseMigrations;
|
use DatabaseMigrations;
|
||||||
|
|
||||||
@@ -775,7 +775,7 @@ class ShareEditorTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
$this->getJson("/api/browse/files/$share->token/public")
|
$this->getJson("/api/browse/file/$share->token/public")
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'name' => 'Document'
|
'name' => 'Document'
|
||||||
Reference in New Issue
Block a user