User generated files storage in Symfony2 - symfony

I have a Symfony2 project with user management (FOsUserbundle & Sonata bundles). In some case of my application, i need to create files for users, and i want to store them. The files might be big so i exclude storing them in sessions/local storage.
First question :
Is there a symfony2 pattern to handle user generated files and storage ?
Where does these files should be placed ? Which directory ?
Second question :
I have a big file that my app need to use. Users shouldn't have access to this file but mainly my app controllers have to. What is the best secured way to store this file and restrain access ?

First Question:
depending on the number of files each user has, I would use some kind of naming convention. e.g. temp/[username]/file1.dat or temp/[username].dat
You can implement this strategy by following the symfony2 cookbock for file uploads on entities and check the function:
public function preUpload()
{
if (null !== $this->file) {
// do whatever you want to generate a unique name
$this->path = uniqid().'.'.$this->file->guessExtension();
}
}
Here is the filename generated, and you can easily set the username instead of some random "uniqueid()".
Second Question
Securing files is in my opinion best implemented via a folder that is not accesible through the web.
For example if you have the following structure:
myproject
app
src
vendor
web <-- your domain points to this folder
save_files
then you can store your files in the save_folder that it is not accesible via direct web access. In your application / controller you can access it via the filesystem or use some abstraction like the KnpGaufretteBundle

Related

Where to upload non-public user files in Symfony

I am working on a Symfony 2.8 project, and I would like to ask users to upload files via a form. These files are not public (like a profile avatar or something), so I don't want to place them under web/, after uploading them only the admins are allowed to know the location of them and to open them via the admin interface of the site. Moving uploaded files near the source code in the actual bundle sounds wrong to me...so is there any official or recommended path to move the uploaded files which is still under the root of the project?
If your requirement is that uploaded files should be downloadable by authorized people only then you must keep them outside the web root obviously. Any directory outside would be fine however they should be kept outside your codebase as well.
You could create data directory in the project root for instance. You can event mount a NFS/S3 share, that choice is yours to make.
To allow files to be downloaded you can create a controller which would serve files to authorized requests only. Example controller (PHP7 based):
final class DownloadController extends Controller
{
/**
* #Route("/download/{path}", requirements={"path"=".+"}, name="download")
* #Method("GET")
* #Security("is_granted('FILE_DOWNLOAD', path)")
*/
public function __invoke(string $path): Response
{
return $this->file($yourUploadBasePath . $path);
}
}
You can either create a data or uploads directory in your project root or if your server is nginx and you have control over web server configuration, you could use http_auth_request module:
https://nginx.org/en/docs/http/ngx_http_auth_request_module.html
Then if you try to access the file, nginx performs a subrequest to your application and if your app returns anything else than 2xx status code, access to the file is denied.
The downside of this approach is that if you replace the webserver or have some error in the configuration, those files would be publicly exposed.

How to manage access permission in alfresco

Hello Everyone thank's in advance for your help.
I am trying to configure access permission in alfresco and now stuck in a scenario
It would be great help if someone defines proper way to achieve this functionality
now my problem is
I want to create a site (which will be accessible by all user)
then will create folder and sub folder in that site (i am ready to customize content type of those folder if required)
now i want to configure alfresco in such a way that specific set of user can access specific folder and it's content
for example
This is list of user
user1,user2,user3,user4,user5
And this is folder structure
Project
Data
Test
Exam
Design
art
practice
Work
W1
W2
Now how to configure it in such a way that
user1 can access Data->Exam
user2 can access work and all it's child folder
user3 can access Data and all it's child folder
user4 can access Design and all it's child folder and
user5 can access Data->Work, Design->art,Work->W1 folder
Note that i am using CMIS api to generate this folder structure
so is there any way to achieve this by java code only ?
i have read about managing permission but not sure about using it just because when i have tried to provide permission to folder it allow to add only single user
but in my case i want to make group of user and want to make the folder accessible by that particulate group.
Thank you so much for you time :)
If you want to use a group, you'll need to create the group in Alfresco using either the admin console or the Alfresco API. CMIS cannot manage users or groups.
Once your users and groups are in place, you can use CMIS to assign them to ACLs. However, the challenge is that you may need to disable or "break" ACL inheritance to do exactly what you want. You cannot disable ACL inheritance with the CMIS API. You'll have to do it in the UI or through the Alfresco API.
With your users and groups in place and with your folders configured to inherit or not inherit parent permissions as needed, you can now add users and groups to your folders. With CMIS, you can add as many users or groups as you need to a given folder. It is not limited to a single user or group. This page has some examples on using Access Control Entries (ACEs) which make up Access Control Lists (ACLs).
I think that Jeff Potts answer is great i will only add few thing's you can look to this post it will give you an answer how to work with ACL How to get Acls of a document.
You can also use the allowable action in any Folder (or document) it will look like this :
Action a = Action.CAN_DELETE_OBJECT;
object = session.getObjectByPath(idObject); // In case it's a folder
if (object.getAllowableActions().getAllowableActions().contains(a)) {
return Boolean.TRUE;// You can do it
}
Only remember that you can get the allowable action from String (In case you want work with few of them)
String canCreateFolder= Action.CAN_CREATE_FOLDER.value();
the most importante Action that you have to use :
can_create_folder = Action.CAN_CREATE_FOLDER.value();
can_create_document = Action.CAN_CREATE_DOCUMENT.value();
can_update_folder = Action.CAN_UPDATE_PROPERTIES.value();
can_update_document = Action.CAN_UPDATE_PROPERTIES.value();
can_delete_folder = Action.CAN_DELETE_OBJECT.value();
can_delete_document = Action.CAN_DELETE_OBJECT.value();
Hope that helped you.

Symfony2: How restrict files in publicly accessible directory

I have XML files in a publicly accessible directory. I want to restrict them to accessible only to logged in users. So when I go to http://example.com/web/file.xml only AUTHENTICATED members can access the file. I'm using PHP & Symfony2.
Files in web are all public so don't put it into that folder.
You can create a folder into Ressources and put your xml into it.
Then create an action witch read and display your file. In this way you will be able to secure your action.
For exemple you can access as http://monsite.com/xml/get
How to secure : http://symfony.com/doc/current/cookbook/security/securing_services.html
I solve the problem with this
$filename = $this->get('kernel')->locateResource("#SomeBundle/Resources/folder/‌file.xml");
(Accessing Files Relative to Bundle in Symfony2)

Where should I save files dynamically generated by the ASP.NET Web API?

My ASP.NET Web API service dynamically generates files for users to download.
The remote application sends a request to the API which:
Generates the file and saves it ----> where?? <-----
Returns the URL of the file location so it can be downloaded.
Nothing fancy there, but my question is what are the best practices for where to save these files?
Some digging around suggests that App_Data might be the appropriate place but I haven't seen anything definitive.
Some considerations:
This all happens on a company intranet so security isn't really a big deal.
The files are essentially temporary. Is there a simple way to delete the file once it's downloaded? Not a big deal - I can set up a scheduled task to clean out whatever the destination folder is.
Thanks!
You can write to any location your application stores data in.
I recommend using the system Temp directory, that's what it's there for (System.IO.Path.GetTempPath()) or if your have write access, a subdirectory of your application:
String path = Server.MapPath("~/Temp");
if( !Directory.Exists( path ) ) Directory.CreateDirectory( path );
using(FileStream fs = File.OpenWrite( Path.Combine( path, "TempFileName.dat" ) )) {
fs.Write( new Byte[1024] );
}
If you have access to your web server, you could also create a virtual directory under your web application and configure it to point to whatever file location you want. Then you can have your application save the files into that virtual directory using System.IO. That's what I've done in the past.

ASP.NET Image Upload Architecture

What would be the best method to implement the following scenario:
The web site calls for a image gallery that has both private and public images to be stored. I've heard that you can either store them in a file hierarchy or a database. In a file hierarchy setup how would prevent direct access to the image. In a database setup access to the images would only be possible via the web page view. What would be a effective solution to pursue?
[Edit] Thanks all for the responses. I decided that the database route is the best option for this application since I do not have direct access to the server. Confined to a webroot folder. All the responses were most appreciated.
Having used both methods I'd say go with the database. If you store them on the filestore and they need protecting then you'd have to store them outside the web-root and then use a handler (like John mentions) to retrieve them, anyway. It's as easy to write a handler to stream them direct from database and you get a few advantages:
With database you don't need to worry about filestore permissions or generating unique filenames or folder hierarchies etc.
With database you can easily apply permissions and protection directly - no trying to work out who can view what based on paths etc.
With a database you can store the image and metadata all together - when you delete the metadata you delete the image - no possibility of orphaned records where you delete from database but not from filestore
Easier to back-up database and images and then restore
The disadvantage is that of performance, but you can use caching etc. to help with that. You can also use FILESTREAM storeage in SQL Server 2008 (and 05?) which means you get filesystem performance but via the DB:
"FILESTREAM integrates the SQL Server
Database Engine with an NTFS file
system by storing varbinary(max)
binary large object (BLOB) data as
files on the file system. Transact-SQL
statements can insert, update, query,
search, and back up FILESTREAM data.
Win32 file system interfaces provide
streaming access to the data.
FILESTREAM uses the NT system cache
for caching file data. This helps
reduce any effect that FILESTREAM data
might have on Database Engine
performance. The SQL Server buffer
pool is not used; therefore, this
memory is available for query
processing."
Using file hierarchy, you can put the files out of the website file folder, for example, suppose the web folder is c:/inetpub/wwwroot/somesite, put the file under c:/images/, so that the web users won't be able to access the image files. but you cannot use the direct link in your website neither, you need to create some procedure to read the file, return the stream.
personally I think it's better to put the file in the database, still create some procedure to retrieve the binary image data and return to wherever it needed.
In reality both scenarios are very similar, so it's up to you... Databases weren't designed to serve files, but if the size isn't really a concern for you, I don't see a problem with doing it.
To answer your question about direct access, you'd setup the file images the same way you would for the database: You'd use some sort of page (probably a .ashx handler) that serves the images, allowing you a layer of logic between the user and image to determine whether or not they should have access to it. The actual directory the images are located in would then need to either a) not be part of the directory structure in IIS or b) if it is part of IIS, only allow windows authenticated access, and only allow the account the application process is running under access to the directory.
If you're using IIS7, since .net jumps in the pipeline early I believe you can protect jpg files as well, just by using a role manager and applying roles to file system folders. If you're using IIS6, I've done something similar to the answer by John, where I store the actual file outside of the wwwroot, and use a handler to decide if the user has the correct credentials to view the image.
I would avoid the database unless you have a strong reason to do this - and I don't think a photo gallery is one of them.
Neither. Amazon S3 offers a very simple API for accepting uploads. You can use SimpleDB or your SQL database to track the URLs and permissions. Set the entire S3 bucket to private, and authenticate to it using your AWS key on the ASP.NET server.
Very little code is required to upload to S3, and very little more would be required to perform bookeeping in SQL.
Once they're in S3, grab the image resizer library and the S3 Reader plugin and you can have your entire system running in under an hour. And - it will scale properly. No disk or database space limits. Ever.
You can implement authorization using the AuthorizeImage event of the Image Resizer library. Just throw an AccessDeniedException if access isn't allowed for the current user.
If you want to tune performance a bit mare, add both the DiskCache and CloudFront plugins. CloudFront can edge-cache the public images (inexpensively), and DiskCache will handle the private images, serving them at static-file speeds.

Resources