How to prevent the file access from public in Laravel? - laravel

I still a newbie in Laravel. Please help me to solve my issue. I stuck on to prevent the file from the public. I trying to make the file access from public to private in Laravel 7.
I put all of the links in the auth it made all of the links required access before using it. I was tried to access some links to create a record. I can't do it and the system required the auth but when I use the URL http://127.0.0.1:8000/storage/actions/filename.something without log-in to access the image file. I still can see the file.
This is my route
Route::group(['prefix' => 'admin', 'middleware'=> ['auth', 'administrator']], function () {
//Action
Route::get('/addAction', 'admin\ActionController#create');
Route::get('/deleteAction/{id}', 'admin\ActionController#delete');
Route::get('editAction/{id}', 'admin\ActionController#edit');
Route::post('/addAction', 'admin\ActionController#store');
Route::post('/updateAction/{id}', 'admin\ActionController#update');
Route::get('/allAction', 'admin\ActionController#index');
Route::get('/delete/actionImage/{id}', 'admin\ActionController#deleteimages');
});
This is the controller that I use to store the data to the database and the image to the file path.
public function index(){
return view('admin.allAction')
->with('actions',Action::all())
->with('challenges',Challenge::all())
->with('users',User::all())
->with('status',Status::all())
->with('images',Images::all());
}
public function create(){
$users = DB::table('users')
->where('role','2')
->get();
return view('admin.addAction')
->with('users', $users)
->with('status',Status::all());
public function store(Request $request){
$request->validate([
'name' => 'required|string|max:188',
'objective' => 'string|max:888',
'images' => 'required',
'images.*' => 'file|image|mimes:jpeg,png,jpg|max:8000',
]);
// Insert Data to Table
$action=new Action();
$action->name=$request->name;
$action->objective=$request->objective;
$action->status_id=$request->status_id;
$action->owner_id=$request->owner_id;
$action->challenge_id=$request->challenge_id;
/*dd($action);*/
$action->save();
if ($request->hasfile('images')) {
$images = $request->file('images');
foreach($images as $image) {
$name = time().'-'.$image->getClientOriginalName();
$name = str_replace(' ','-',$name);
/*$path =*/ $image->storeAs('actions', $name, 'public');
Images::insert([ /*OrUpdate*/
'name' => $name,
'action_id' => $action->id,
]);
}
}
Session()->flash("success", "Success!");
return redirect('/admin/addAction');
My filesystem.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'private' => 0700,
],
],
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
],
I never do private file before I don't know how to do it. I tried to search how to on the internet but I still can't make it possible.
Thank you for all of the comments in advance and sorry for my English.

Related

laravel : symlink storage in public not working " 404 (not found)"

when I try to visualise my picture with this basic url on google :
domain.com/storage/transports/picture.png
I get (404) not found.
(I don't have this error for a file outside the storage symlink in my tree picture and I can totaly see it without any problems, exemple :
domain.com/logo.svg
I have used php artisan storage:link to create the symlink, so far I'm abble to store the pictures exactly where I want to with that controller :
public function storeTransports(Request $request)
{
try{
session(['content'=>'content_transports']);
$request->validate([
'name' => [ 'string', 'max:255'],
'picture' => [ 'required','image','mimes:jpeg,png,jpg,gif,svg', 'max:2048']
]);
if(Transport::where('name', $request->name)->first()){
return redirect(RouteServiceProvider::HOME)->with('error_transports', 'Transport already exists');
}
else{
if($request->hasFile('picture')){
$sanitized_image_name = strtolower(preg_replace("([^A-Za-z0-9])", "", $request->name)).'_'.time();
$image_name = $sanitized_image_name.'.'.$request->picture->extension();
Transport::create([
'name' => $request->name,
'path_picture' => $image_name
]);
$request->picture->storeAs('public/transports',$image_name);
}
}
return redirect(RouteServiceProvider::HOME)->with('success_transports', 'Transport saved successfully');
} catch (\Illuminate\Database\QueryException $e){
return redirect(RouteServiceProvider::HOME)->with('error_transports',$e->errorInfo);
}
}
I can also visualize my pictures in my public folder :
i've rm rf public/storage many times already
here is my configfiles.php :
<?php
return [
'default' => env('FILESYSTEM_DISK', 'public'),
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'throw' => false,
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
],
],
'links' => [
public_path('storage') => storage_path('app/public'),
],
];
I appreciate your help, I've been looking at all the stackoverflow talking about that for the past hour.
PS: I don't use vagrant.
EDIT:
i finally fixed my issue, as Matty10209 mentoned here,
"[...]When running "php artisan storage:link", Laravel creates an absolute path for the image to your local directory. Docker does not like this and wants a relative one, so it breaks the image link and you get a 404. You have to create the symlink manually[...]"
"[...] Go to docker and the CLI of your project container (should be at the bottom). Delete the current symlink you have created with Laravel, then navigate to the path you wish to create a new one. and run
ln -s ../storage/app/public storage
[...]"

cant store the file using storeAs in laravel

iam using a laravel site and in my file i have a directory in path
/var/www/site/admin.site.com/public/storage/salescall
i need to upload a file to this salescall folder i have used the following code.
$filenameWithExt = $request->file('sales_call')->getClientOriginalName();
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
$extension = $request->file('sales_call')->getClientOriginalExtension();
$filenameToStore = $filename . '-' . time() . '.' . $extension;
$request->file('sales_call')
->storeAs('', $filenameToStore, 'sales');
and my filesystems.php is as follows
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_KEY'),
'secret' => env('AWS_SECRET'),
'region' => env('AWS_REGION'),
'bucket' => env('AWS_BUCKET'),
],
'sales' => [
'driver' => 'local',
'root' => public_path('salescall'),
'visibility' => 'public',
],
],
file is not uploaded to folder.please help me to solve this. Thank you in advance.
You can easily do this:
$request->file('sales_call')-> storeAs('salescall/',$filenameToStore);
FOR BETTER UNDERSTANDING, SEE BELOW
The configuration of your filesystem seems to be incorrect.
Use the below sample as a guide and I hope it helps you.
If you use this code, it will upload your file in storage/app folder
Storage::disk('local')->put('file.txt', 'Contents');
Now, if you need to change the directory and store into the storage folder directly, you need to change something in the filesystems.php file.
Go to config/filesystems.php file and change the following code-
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
Here, this line of code 'root' => storage_path('app'), responsible to define where to store. You just adjust according to your demands.
Alternatively, In your controller, You could do something like this:
<?php
namespace App\Http\Controllers\Api;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
class UserAvatarController extends Controller
{
/**
* Handle the incoming request.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
$request->validate([
'avatar'=> ['required','max:200']
]);
$user = User::findOrFail(auth()->user()->id);
// Handle file Upload
if($request->hasFile('avatar')){
//Storage::delete('/public/avatars/'.$user->avatar);
// Get filename with the extension
$filenameWithExt = $request->file('avatar')->getClientOriginalName();
//Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('avatar')->getClientOriginalExtension();
// Filename to store
$fileNameToStore = $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('avatar')->storeAs('public/avatars',$fileNameToStore);
$user->avatar = $fileNameToStore ;
$user->save();
}
return $user;
}
}
But in your own case, I believe:
In your config, set the root key to storage_path('salescall')
Yours should be $path = $request->file('sales_call')->storeAs('public/salescall',$fileNameToStore);
Just let me know if this works.. Cheers!
You have to use like this
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'private' => 0700,
],
],
],
$request->file('sales_call')-> storeAs('salescall/',$filenameToStore);

Disk [google-drive] does not have a configured driver

Hi i am trying to link google drive api to the laravel system for what i have used google drive api in laravel and configured the filesystem and env setting. But when executed it returns DISK not configured error.
Tried solution of clearing config cache and dump-autoload still the isuue persist same.
filesystem.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
'google-drive' => [
'driver' => 'google',
'clientId' => env('GOOGLE_DRIVE_CLIENT_ID'),
'clientSecret' => env('GOOGLE_DRIVE_CLIENT_SECRET'),
'refreshToken' => env('GOOGLE_DRIVE_REFRESH_TOKEN'),
'folderId' => env('GOOGLE_DRIVE_FOLDER_ID'),
],
],
googledriveserviceprovider.php
public function boot()
{
Storage::extend('google-drive', function($app, $config) {
$client = new \Google_Client();
$client->setClientId($config['clientId']);
$client->setClientSecret($config['clientSecret']);
$client->refreshToken($config['refreshToken']);
$client->fetchAccessTokenWithRefreshToken($config['refreshToken']);
$service = new \Google_Service_Drive($client);
$adapter = new \Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter($service, $config['folderId']);
return new \League\Flysystem\Filesystem($adapter);
});
}
Route to put file.
Route::get('put', function() {
Storage::disk('google-drive')->put('test.txt', 'Hello World');
return 'File was saved to Google Drive';
});
Any help is deeply appreciated.
I think this line:
Storage::extend('google-drive', function($app, $config) {
should just be
Storage::extend('google', function($app, $config) {
I think this useful for you
filesystem.php
'disks' => [
'google' => [
'driver' => 'google',
'clientId' => env('GOOGLE_DRIVE_CLIENT_ID'),
'clientSecret' => env('GOOGLE_DRIVE_CLIENT_SECRET'),
'refreshToken' => env('GOOGLE_DRIVE_REFRESH_TOKEN'),
'folderId' => env('GOOGLE_DRIVE_FOLDER_ID'),
],
],
googledriveserviceprovider.php
public function boot()
{
Storage::extend('google', function($app, $config) {
$client = new \Google_Client();
$client->setClientId($config['clientId']);
$client->setClientSecret($config['clientSecret']);
$client->refreshToken($config['refreshToken']);
$client->fetchAccessTokenWithRefreshToken($config['refreshToken']);
$service = new \Google_Service_Drive($client);
$adapter = new \Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter($service, $config['folderId']);
return new \League\Flysystem\Filesystem($adapter);
});
}
Route file
Route::get('put', function() {
Storage::disk('google')->put('test.txt', 'Hello World');
return 'File was saved to Google Drive';
});

Not delete image from laravel backpack 4.0

I'm using image field in laravel backpack 4.0 and it uploads the images without any problems. When I delete the image by using the delete button, it deletes the register (E.N. Probably means "it deletes the image from the database"), but not the image file from my local folder. I've checked the answer from backpack for laravel deleting image , but it did not help to fix my issue.
My config/filesystem:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
],
My Model code:
public function setImageAttribute($value)
{
$attribute_name = "image";
$disk = config('backpack.base.root_disk_name'); // or use your own disk, defined in config/filesystems.php
$destination_path = env('FOLDER_PUBLIC')."/uploads/medias"; // path relative to the disk above
// if the image was erased
if ($value==null) {
// delete the image from disk
\Storage::disk($disk)->delete($this->{$attribute_name});
// set null in the database column
$this->attributes[$attribute_name] = null;
}
// if a base64 was sent, store it in the db
if (starts_with($value, 'data:image'))
{
// 0. Make the image
$image = \Image::make($value)->encode('jpg', 90);
// 1. Generate a filename.
$filename = rand ( 10000 , 99999 ).'-'.strtolower(trim(preg_replace('/[\s-]+/', '-', preg_replace('/[^A-Za-z0-9-]+/', '-', preg_replace('/[&]/', 'and', preg_replace('/[\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $this->title))))), '-')).'.jpg';
// 2. Store the image on disk.
\Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
// 3. Save the public path to the database
// but first, remove "public/" from the path, since we're pointing to it from the root folder
// that way, what gets saved in the database is the user-accesible URL
$public_destination_path = Str::replaceFirst(env('FOLDER_PUBLIC').'/', '', $destination_path);
$this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;
}
}
public static function boot()
{
parent::boot();
static::deleting(function($obj) {
\Storage::disk('public')->delete($obj->image);
});
}
I have tried to change:
\Storage::disk('public')->delete($obj->image);
With:
\Storage::disk(config('backpack.base.root_disk_name'))->delete($obj->image);
But it is not working either,
Can anyone help me?
Sorry for my english
You're on the right track. Looks like something is misconfigured if code in boot() doesn't affect any changes. My guess is that that the $obj->image path to the file you're trying to delete is NOT the exact path to the file. You might need to add the destination folder there too.
public static function boot()
{
parent::boot();
static::deleting(function($obj) {
$disk = config('backpack.base.root_disk_name');
$destination_path = env('FOLDER_PUBLIC')."/uploads/medias";
\Storage::disk($disk)->delete($destination_path.'/'.$this->image);
});
}
If this works, to further improve the code, I recommend you turn the $disk and $destination_path variables into properties on the PHP class itself (the Laravel model). That way, you only define them in one place, and you can then use them in both methods, with something like $this->imageDisk and $this->imagePath.
Thanks for your reply, At the end I have fixed it, making this change:
public static function boot()
{
parent::boot();
static::deleting(function($obj) {
\Storage::disk('uploads')->delete($obj->image);
});
}
And in config/filesystem:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
'uploads' => [
'driver' => 'local',
/* 'root' => base_path().'/web/storage',*/
'root' => base_path().'/'.env('FOLDER_PUBLIC'),
],
],
Regards

How to change the storage path of files?

I want to change the storage path of my data (files) from the default storage/app/public to public/files.
Controller
public function store(Request $request)
{
request()->validate([
'filename' => 'required',
]);
$files = $request->file('filename');
foreach ($files as $file) {
File::create([
'filename' => $file->getClientOriginalName(),
]);
}
return redirect('/file')->with('success', 'File Uploaded Successfully');
}
go to config folder -> filesystems.php
'public' => [
'driver' => 'local',
'root' => public_path(),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
public function upload(Request $request)
{
$uploadedFile = $request->file('filename');
$filename = time().$uploadedFile->getClientOriginalName();
Storage::disk('local')->putFileAs(
'files/'.$filename,
$uploadedFile,
$filename
);
$upload = new Upload;
$upload->filename = $filename;
$upload->save();
}
$fileFullName=$request->file('cover_image')->getClientOriginalName();
$fileName=pathinfo($fileFullName,PATHINFO_FILENAME);
$ext=$request->file('cover_image')->getClientOriginalExtension();
$fileToSave=$fileName.'_'.time().'.'.$ext;
$store=$request->file('cover_image')->storeAs('/public/cover_images',$fileToSave);
in your config/config/filesystems.php you can do this like:
'disks' => [
'uploads' => [
'driver' => 'local',
'root' => public_path() . '/uploads',
'url' => env('APP_URL').'/public',
'visibility' => 'public',
],
]
and then store like this:
Storage::disk('uploads')->put('filename', $file_content);

Resources