diff --git a/app/Http/Controllers/Sharing/ServeSharedController.php b/app/Http/Controllers/Sharing/ServeSharedController.php index 3b18cc13..af1843ef 100644 --- a/app/Http/Controllers/Sharing/ServeSharedController.php +++ b/app/Http/Controllers/Sharing/ServeSharedController.php @@ -35,14 +35,9 @@ class ServeSharedController extends Controller */ public function index(Share $shared) { - // Delete old access_token if exist - Cookie::queue('shared_access_token', '', -1); - - // Set cookies + // Delete share_session if exist if ($shared->is_protected) { - - // Set shared token - Cookie::queue('shared_token', $shared->token, 43200); + cookie()->queue('share_session', '', -1); } // Check if shared is image file and then show it @@ -63,11 +58,32 @@ class ServeSharedController extends Controller return $this->show_image($image, $shared->user_id); } - return view("index") ->with('settings', get_settings_in_json() ?? null); } + /** + * Check Password for protected item + * + * @param AuthenticateShareRequest $request + * @param Share $shared + * @return array|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response + */ + public function authenticate(AuthenticateShareRequest $request, Share $shared) + { + // Check password + if (!Hash::check($request->password, $shared->password)) { + abort(401, __('vuefilemanager.incorrect_password')); + } + + // Return authorize token with shared options + return response(new ShareResource($shared), 200) + ->cookie('share_session', json_encode([ + 'token' => $shared->token, + 'authenticated' => true, + ]), 43200); + } + /** * Get image from storage and show it * @@ -94,57 +110,6 @@ class ServeSharedController extends Controller ]); } - /** - * Check Password for protected item - * - * @param AuthenticateShareRequest $request - * @param Share $shared - * @return array - */ - public function authenticate(AuthenticateShareRequest $request, Share $shared) - { - // Check password - if (!Hash::check($request->password, $shared->password)) { - - abort(401, __('vuefilemanager.incorrect_password')); - } - - // Get owner of shared content - $user = User::find($shared->user_id); - - // Define scope - $scope = !is_null($shared->permission) ? $shared->permission : 'visitor'; - - // Generate token for visitor/editor - $access_token = $user->createToken('shared_access_token', [$scope])->accessToken; - - // Return authorize token with shared options - return response(new ShareResource($shared), 200) - ->cookie('shared_token', $shared->token, 43200) - ->cookie('shared_access_token', $access_token, 43200); - } - - /** - * Browse private folders - * - * @param Request $request - * @param $id - * @return Collection - */ - public function get_private_folders(Request $request, $id) - { - // Get sharing record - $shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail(); - - // Check if user can get directory - $this->helper->check_item_access($id, $shared); - - // Collect folders and files to single array - return collect( - $this->helper->get_items_under_shared_by_folder_id($id, $shared) - )->collapse(); - } - /** * Get shared public file record * @@ -169,97 +134,4 @@ class ServeSharedController extends Controller // Return record return $file; } - - /** - * Get shared private file record - * - * @return mixed - */ - public function file_private(Request $request) - { - // Get sharing record - $shared = Share::where('token', $request->cookie('shared_token')) - ->firstOrFail(); - - // Return record - return File::where('user_id', $shared->user_id) - ->where('id', $shared->item_id) - ->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']); - } - - /** - * Get navigation tree - * - * @param Request $request - * @return array - */ - public function get_private_navigation_tree(Request $request) - { - // Get sharing record - $shared = get_shared($request->cookie('shared_token')); - - // Check if user can get directory - $this->helper->check_item_access($shared->item_id, $shared); - - // Get folders - $folders = Folder::with('folders:id,parent_id,id,name') - ->where('parent_id', $shared->item_id) - ->where('user_id', $shared->user_id) - ->sortable() - ->get(['id', 'parent_id', 'id', 'name']); - - // Return folder tree - return [ - [ - 'id' => $shared->item_id, - 'name' => __('vuefilemanager.home'), - 'location' => 'public', - 'folders' => $folders, - ] - ]; - } - - /** - * Search private files - * - * @param Request $request - * @param $token - * @return Collection - */ - public function search_private(Request $request) - { - // Get shared - $shared = get_shared($request->cookie('shared_token')); - - // Search files id db - $searched_files = File::search($request->input('query')) - ->where('user_id', $shared->user_id) - ->get(); - - $searched_folders = Folder::search($request->input('query')) - ->where('user_id', $shared->user_id) - ->get(); - - // Get all children content - $foldersIds = Folder::with('folders:id,parent_id,id,name') - ->where('user_id', $shared->user_id) - ->where('parent_id', $shared->item_id) - ->get(); - - // Get accessible folders - $accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]); - - // Filter files to only accessible files - $files = $searched_files->filter(function ($file) use ($accessible_folder_ids) { - return in_array($file->folder_id, $accessible_folder_ids); - }); - - // Filter folders to only accessible folders - $folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) { - return in_array($folder->id, $accessible_folder_ids); - }); - - // Collect folders and files to single array - return collect([$folders, $files])->collapse(); - } } diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index 3f4dc718..0e3a4854 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -12,6 +12,6 @@ class EncryptCookies extends Middleware * @var array */ protected $except = [ - 'token' + ]; } diff --git a/config/auth.php b/config/auth.php index 28573ac2..ba1a4d8c 100644 --- a/config/auth.php +++ b/config/auth.php @@ -42,8 +42,9 @@ return [ ], 'api' => [ - 'driver' => 'passport', + 'driver' => 'token', 'provider' => 'users', + 'hash' => false, ], ], diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 3775696e..f8a09113 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -66,7 +66,7 @@ "/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=c6b88005b133268ed88f", "/chunks/shared.js": "/chunks/shared.js?id=2c38f535d52e0e448846", "/chunks/shared-files.js": "/chunks/shared-files.js?id=e6f7de2910d85a2dd3e4", - "/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=60e8f0fdb35d2c8552dc", + "/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=9024f3b0b3bed191fe8d", "/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/sign-in.js": "/chunks/sign-in.js?id=af61663f3e69eae3e5ee", diff --git a/resources/js/views/Shared/SharedAuthentication.vue b/resources/js/views/Shared/SharedAuthentication.vue index 91a88792..e666920c 100644 --- a/resources/js/views/Shared/SharedAuthentication.vue +++ b/resources/js/views/Shared/SharedAuthentication.vue @@ -59,12 +59,11 @@ // Send request to get verify account axios - .post('/api/browse/shared/authenticate/' + this.$route.params.token, { + .post('/api/browse/authenticate/' + this.$route.params.token, { password: this.password }).then(() => { // todo: Redirect to file browser page - }) .catch(error => { diff --git a/routes/share.php b/routes/share.php index d9a0e753..76864197 100644 --- a/routes/share.php +++ b/routes/share.php @@ -27,7 +27,7 @@ Route::group(['prefix' => 'browse'], function () { Route::get('/folders/{id}/public/{shared}', [BrowseShareController::class, 'get_public_folders']); Route::get('/search/public/{shared}', [BrowseShareController::class, 'search_public']); - Route::post('/shared/authenticate/{shared}', [ServeSharedController::class, 'authenticate']); + Route::post('/authenticate/{shared}', [ServeSharedController::class, 'authenticate']); Route::get('/files/{shared}/public', [ServeSharedController::class, 'file_public']); Route::get('/shared/{shared}', [ShareController::class, 'show']); }); diff --git a/tests/Feature/Accounts/AuthTest.php b/tests/Feature/Accounts/AuthTest.php index ad58c5a6..0e2876b7 100644 --- a/tests/Feature/Accounts/AuthTest.php +++ b/tests/Feature/Accounts/AuthTest.php @@ -113,8 +113,6 @@ class AuthTest extends TestCase 'email' => $user->email, 'password' => 'secret', ])->assertStatus(200); - - dd($user->tokenCan('test')); } /** diff --git a/tests/Feature/External/SubscriptionTest.php b/tests/Feature/External/SubscriptionTest.php index 98aa370e..26cc2648 100644 --- a/tests/Feature/External/SubscriptionTest.php +++ b/tests/Feature/External/SubscriptionTest.php @@ -477,10 +477,8 @@ class SubscriptionTest extends TestCase */ public function it_get_all_plans_for_index_page() { - $response = $this->getJson('/api/pricing') + $this->getJson('/api/pricing') ->assertStatus(200); - - dd(json_decode($response->content(), true)); } /** diff --git a/tests/Feature/Share/PrivateShareContentAccessTest.php b/tests/Feature/Share/PrivateShareContentAccessTest.php new file mode 100644 index 00000000..6c1df057 --- /dev/null +++ b/tests/Feature/Share/PrivateShareContentAccessTest.php @@ -0,0 +1,71 @@ +setup = app()->make(SetupService::class); + } + + /** + * @test + */ + public function it_authenticate_protected_file_with_correct_password() + { + $file = File::factory(File::class) + ->create(); + + $share = Share::factory(Share::class) + ->create([ + 'item_id' => $file->id, + 'user_id' => $file->user_id, + 'type' => 'file', + 'is_protected' => true, + 'password' => \Hash::make('secret'), + ]); + + $this->postJson("/api/browse/authenticate/$share->token", [ + 'password' => 'secret' + ]) + ->assertStatus(200) + ->assertCookie('share_session', json_encode([ + 'token' => $share->token, + 'authenticated' => true, + ]), false); + } + + /** + * @test + */ + public function it_authenticate_protected_file_with_incorrect_password() + { + $file = File::factory(File::class) + ->create(); + + $share = Share::factory(Share::class) + ->create([ + 'item_id' => $file->id, + 'user_id' => $file->user_id, + 'type' => 'file', + 'is_protected' => true, + 'password' => \Hash::make('secret'), + ]); + + $this->postJson("/api/browse/authenticate/$share->token", [ + 'password' => 'bad-password' + ]) + ->assertStatus(401) + ->assertCookieMissing('share_session'); + } +} diff --git a/tests/Feature/Share/ShareContentAccessTest.php b/tests/Feature/Share/PublicShareContentAccessTest.php similarity index 99% rename from tests/Feature/Share/ShareContentAccessTest.php rename to tests/Feature/Share/PublicShareContentAccessTest.php index d2d9cdf8..f90e443e 100644 --- a/tests/Feature/Share/ShareContentAccessTest.php +++ b/tests/Feature/Share/PublicShareContentAccessTest.php @@ -13,7 +13,7 @@ use Illuminate\Support\Str; use Storage; use Tests\TestCase; -class ShareContentAccessTest extends TestCase +class PublicShareContentAccessTest extends TestCase { use DatabaseMigrations; diff --git a/tests/Feature/Share/ShareEditorTest.php b/tests/Feature/Share/ShareEditorTest.php index a88b7cd0..c7e151ab 100644 --- a/tests/Feature/Share/ShareEditorTest.php +++ b/tests/Feature/Share/ShareEditorTest.php @@ -113,13 +113,18 @@ class ShareEditorTest extends TestCase */ public function editor_create_new_folder_in_shared_folder() { - $folder = Folder::factory(Folder::class) + $user = User::factory(User::class) ->create(); + $folder = Folder::factory(Folder::class) + ->create([ + 'user_id' => $user->id, + ]); + $share = Share::factory(Share::class) ->create([ 'item_id' => $folder->id, - 'user_id' => $folder->user_id, + 'user_id' => $user->id, 'type' => 'folder', 'is_protected' => false, 'permission' => 'editor', @@ -146,13 +151,18 @@ class ShareEditorTest extends TestCase */ public function editor_delete_multiple_files_in_shared_folder() { - $folder = Folder::factory(Folder::class) + $user = User::factory(User::class) ->create(); + $folder = Folder::factory(Folder::class) + ->create([ + 'user_id' => $user->id, + ]); + $share = Share::factory(Share::class) ->create([ 'item_id' => $folder->id, - 'user_id' => $folder->user_id, + 'user_id' => $user->id, 'type' => 'folder', 'is_protected' => false, 'permission' => 'editor',