Skip to content

Commit

Permalink
Securing Exported Files By Hiding Behind Cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Blair2004 committed Sep 30, 2021
1 parent 0a75a2d commit 0138f96
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
31 changes: 29 additions & 2 deletions app/Http/Controllers/Dashboard/CrudController.php
Expand Up @@ -4,6 +4,7 @@
*/
namespace App\Http\Controllers\Dashboard;

use App\Exceptions\NotFoundException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str;
Expand All @@ -15,6 +16,8 @@
use App\Services\CrudService;
use TorMorten\Eventy\Facades\Events as Hook;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
Expand Down Expand Up @@ -561,7 +564,13 @@ public function exportCrud( $namespace, Request $request )
* let's define what will be the output name
* of the exported file.
*/
$fileName = 'export/' . Str::slug( $resource->getLabels()[ 'list_title' ] ) . '.csv';
if ( ! is_dir( storage_path( 'app/public/exports' ) ) ) {
mkdir( storage_path( 'app/public/exports' ) );
}

$dateFormat = Str::slug( ns()->date->toDateTimeString() );
$relativePath = 'exports/' . Str::slug( $resource->getLabels()[ 'list_title' ] ) . '-' . $dateFormat . '.csv';
$fileName = storage_path( 'app/public/' . $relativePath );

/**
* We'll prepare the writer
Expand All @@ -570,8 +579,15 @@ public function exportCrud( $namespace, Request $request )
$writer = new Csv($spreadsheet);
$writer->save( $fileName );

/**
* We'll hide the asset URL behind random lettes
*/
$hash = Str::random(20);

Cache::put( $hash, $relativePath, now()->addMinutes(5) );

return [
'url' => asset( $fileName )
'url' => route( 'ns.dashboard.crud-download', compact( 'hash' ) )
];
}

Expand Down Expand Up @@ -609,4 +625,15 @@ public function canAccess( $namespace, Request $request )
'message' => __( 'This resource is not protected. The access is granted.' )
]);
}

public function downloadSavedFile( $hash )
{
$relativePath = Cache::pull( $hash );

if ( Storage::disk( 'public' )->exists( $relativePath ) ) {
return Storage::disk( 'public' )->download( $relativePath );
}

throw new NotFoundException( __( 'The requested file cannot be downloaded or has already been downloaded.' ) );
}
}
3 changes: 3 additions & 0 deletions routes/web.php
Expand Up @@ -3,6 +3,7 @@
use App\Http\Controllers\AuthController;
use App\Http\Middleware\CheckMigrationStatus;
use App\Events\WebRoutesLoadedEvent;
use App\Http\Controllers\Dashboard\CrudController;
use App\Http\Controllers\Dashboard\ModulesController;
use App\Http\Controllers\Dashboard\UsersController;
use App\Http\Middleware\Authenticate;
Expand Down Expand Up @@ -83,6 +84,8 @@
Route::get( '/users/roles', [ UsersController::class, 'rolesList' ]);
Route::get( '/users/roles/create', [ UsersController::class, 'createRole' ]);
Route::get( '/users/roles/edit/{role}', [ UsersController::class, 'editRole' ]);

Route::get( '/crud/download/{hash}', [ CrudController::class, 'downloadSavedFile' ])->name( 'ns.dashboard.crud-download' );
});
});
});
Expand Down

0 comments on commit 0138f96

Please sign in to comment.