View files inside storage folder for authenticated User - php

I am using spatie library to upload some files which will be saved to the storage folder. What I want to accomplished at the moment, is to view those files or images when I am an authenticated user. I've tried creating a symlink using this command ,
php artisan storage:link
But this makes those file to be seen publicly. What I only want is to view those file, only when the user is an authenticated user. So far this is what I did but it seems like I miss something.
ROUTE :
Route::get('/storage/{filePath}', 'ComplaintsController#fileStorageServe')->where(['filePath' => '.*'])->name('complaints.viewfile');
CONTROLLER :
public function fileStorageServe($file) {
// know you can have a mapping so you dont keep the sme names as in local (you can not precsise the same structor as the storage, you can do anything)
// any permission handling or anything else
// we check for the existing of the file
if (!Storage::disk('local')->exists($filePath)){ // note that disk()->exists() expect a relative path, from your disk root path. so in our example we pass directly the path (/.../laravelProject/storage/app) is the default one (referenced with the helper storage_path('app')
abort('404'); // we redirect to 404 page if it doesn't exist
}
//file exist let serve it
// if there is parameters [you can change the files, depending on them. ex serving different content to different regions, or to mobile and desktop ...etc] // repetitive things can be handled through helpers [make helpers]
return response()->file(storage_path('app'.DIRECTORY_SEPARATOR.($filePath))); // the response()->file() will add the necessary headers in our place (no headers are needed to be provided for images (it's done automatically) expected hearder is of form => ['Content-Type' => 'image/png'];
// big note here don't use Storage::url() // it's not working correctly.
}
VIEW :
#foreach($complaint->attachments as $attachment)
{{ $attachment->file_name }}
#endforeach
When I click the link it will give me something like this.
http://127.0.0.1:8000/complaints.viewfile/http%3A%2F%2F127.0.0.1%3A8000%2Fstorage%2F3%2F60580fdeadc55_worship.jpg
Please help. Thank you...

You need to understand how files are served by a web server and how that interacts with a laravel application.
You likely have nginx or apache set up to serve files from the public folder of your laravel app. ie: /var/www/sites/laravel-site/public.
When an HTTP request is sent to your server, if your nginx or apache is configured to serve files like laravel-site.com/storage/documents/secrets.pdf statically, then your laravel application code will never even be run, and you cannot control access to these files at the application level.
If you want to setup access control to files, you will need to first ensure the requests are not going to be served statically, and second setup a route to serve the files after checking if the user/request has permission to access the file(s) you want to serve.
There are lots of other great answers and resources on how to do this.

Correct me if im wrong but isn't the easiest way to do that via system-settings ? Like you have different Users and you just put them in different groups that have different rights for folders/files.

Related

Laravel 8 – create route alias for image folder inside public directory

I’m in the middle of the process of replicating a framework that I developed in node / react to laravel. Right now, I’m adjusting the main architecture and currently working on a blade master page.
My original idea (Laravel 8 – use blade asset to display image, but loading from resources subfolder) didn’t work, so I’m trying a new approach to set up how I want my asset files to be served.
The assets in question is basically images for layout purposes. I organized the directory like so:
public/app_files_layout
Inside it, I have a bunch of image files that I want to access. The thing is that I don’t want to access like http://localhost:8000/app_files_layout/image-name.jpg. My intention is to access like: http://localhost:8000/images/image-name.jpg, but I want to maintain the directory names I created intact, so it can have a high fidelity architectural organization similar to my framework that I built in other languages.
I figured that I would set up a simple routing logic for it in Laravel web.php file. I followed the suggestion from this stackoverflow question:
https://stackoverflow.com/a/38736973/2510785
However, when I try to access via browser through the following address http://localhost:8000/files-layout-test/image-name.jpg, returned me an error like so:
The requested resource /files-layout-test/image-name.jpg was not found on this server.
I stripped the code just to try to find out what could be wrong, and this is what I did to debug it:
Route::get('/files-layout-test/{filename}', function($filename){
echo 'debug';
});
The strange behavior is that, when I try to access without the file extension (ex: http://localhost:8000/files-layout-test/image-name), it goes through, but I need the file extension to be there.
Any ideas on how I could get this done?
Note: I’m new to Laravel, so the answer may be simple.
Basically for simple stuff like creating a symlink for public/images and public/app_files_layout you can use the built-in storage:link command.
In your config/filesystems.php file, you can define the symlinks you want to create
'links' => [
public_path('storage') => storage_path('app/public'),
public_path('images') => public_path('app_files_layout'),
],
Then you can run php artisan storage:link and it will create all the symlinks defined the links array in config/filesystems.php. No need to create any custom Artisan command. You can read more at Laravel Docs
With the above symlink created you can use the asset() helper to generate the urls for assets which are actually in public/app_files_layout using asset('images/filename.ext').
You can also access public/app_files_layout/image-name.ext at http://localhost:8000/images/image-name.ext once the symlink is created.
However if you want to add some other logic or say you want to get user input for creating symlinks then you can define your own custom Artisan command using the storage:link command as starting point

Where should my users folder be in a Slim 3 project?

I'm currently building a simply file hosting script using Slim 3. Currently I have my users folder on the same level as my public directory. Now that I'm attempting to access the files inside the user folder I'm getting errors caused by my document root not being able to access my users folder. Would it be a better idea to put my users folder inside my public folder because technically that would be public info to the logged in user?
It depends on what these files are - If they are only for the specific user or if they are available to all users.
When the files has to be private you can not put them into public, simple because everyone could hack url and get access to them. So you should put them in any data directory and make them available using an endpoint like /file/{username}/{name}.
In such endpoint you can easily append Header about filetype or if it should download or try to show in the browser window.
Whatever you make publicly available to the web server will be handled by default as any other asset:
Its URL is based upon the actual file name
If you know the URL you can download it
If it's a .php file it will be executed
You can certainly address all this concerns (and some of them may not even be concerns for your use case) but I don't think this is the ideal layout for a typical user-managed directory tree. Your current approach makes more sense to me.
To access such files you need to create a proper download script that makes all the appropriate checks (e.g. access checks), matches file system stuff from URLs and serves the assets as static files. In Slim that means creating a route with parameters and writing a handler function that does all this stuff.

apache/php multiple users mapped to multiple versions of app

(updated file structure)
I've got this situation:
a general database with several users (unique_name, database_name, user, password, version)
a release folder with different versions of the app. (releases/version/...)
each user has his own database, from which the info is found in the general database.
if a user navigates to "http://www.app.com/unique_name/", I want the server to:
load the correct user info from the general database
load the correct version of the app (and the correct assets)
use the correct user database in the app.
The users can only see "http://www.app.com/unique_name/" in it's browser, and there will be API calls to "http://www.app.com/unique_name/api/...".
file structure:
/
data/
unique_name/ (files for unique_name)
unique_name2/ (files for unique_name2)
...
releases/
v1.5/
index.php
api/
v2.0/
index.php
api/
What would be a correct way to approach this using apache and php?
Your question need more details from your side but what i could understand, In this case you have to be very decisive on project structure,
Make url looks like -> www.app.com/index.php?/unique_name
Create a bootstrap file which handle all request(landing) and pass unique_name as a parameter, you can use .htaccess file for this
Parse the url and get the first segment, Gets the Database and version details from general database based on argument and cache or store it in session(user data + version folder mapping) it.
Loads the correct version of file-system using php(may be need to write a router class)
www.app.com/api/index.php?/unique_name
src\
api\
index.php
releases\
xxx.xxx\
xxx.xxx\
index.php
As far as api code, i would advise to place all api related code at top level.
You need to write some router(mapper) which will make the absolute path of assets or files, can be used for loading.

Need use PHP to read directory directly not layer by layer

I need to access a remote URL like \\filesystem\XXX\YYY.
And the remote URL manager allows me to access \\filesystem and \\filesystem\XXX\YYY, while \\filesystem\XXX does not.
so opendir("\\filesystem") works fine, and opendir("\\filesystem\XXX\YYY") return false.
I guess opendir() read its path layer by layer, so it returns false when it goes to \\filesystem\XXX.
Is there any way to access the URL directly?
Here is my situation.
I'm in Department A and there is another department called XXX. They put their documents in \\filesystem\XXX and make a directory YYY to share some files with other departments.
That's why I have permission to access \\filesystem and \\filesystem\XXX\YYY ,but not \\filesystem\XXX.
Thanks for helping me to solve this problem. I called system("whoami") to find out that apache is running by a system account without permission to access \\filesystem\XXX\YYY.

serving images from a filespool using zend framework

I have a quick question about how to serve data from a repository in a application that I am writing using the Zend Framework.
My current structure is:
/application
/filespool
/library
/public
In the filespool are a number of user identifiable folders that contain user content that is uploaded via forms, mainly jpg/png and pdf. This causes issues when trying to display an image back to the user as the path in my db to reference the file is:
../filespool/0/0/1/image.jpg
which I can't display in the view script as it can't reference the image.
What would be the best way of adding the image to the view script when trying to display it back to the user? I thought about adding the filespool folder to under public but would rather leave it where it is, as that move would require a lot of work to refactor the changes.
Thanks in advance...
i guess you could try 2 diferent things ( actually just one )...
use htacces to make a virtual directory for the file pool using rewrite ( not working )
make a php file in the public directorry that takes a parameter with the path and serves the files
EDIT
Spoke to soon ... you cant use htaccess ... and that is because its outside your document root so the server cant serve files from there.

Categories