Symfony2 - Gregwar/Image Bundle - resized images cache to S3 (Cloudfront) - symfony

I would like to use the Amazon Cloudfront service as a CDN.
My question is:
How can get Gregwar/ImageBundle to work with S3?
So this:
{% set img_path = asset('assets/' ~ app.request.get('product_id') ~ '/images/' ~ contents.background) %}
<img src="{{ web_image(img_path).forceResize(1000) }}" alt="{{contents.title|default('') }}">
generates this:
https://s3-cdn.com/cache/f/5/f/1/4/f5f1407eb85e38e94019a03082b10611f57b22e5.png
instead of this:
/cache/f/5/f/1/4/f5f1407eb85e38e94019a03082b10611f57b22e5.png (local fylesystem)
Some update:
I could figure out the asset dumping with this:
Dump Symfony2 assets to Amazon S3
I can not set the permission to readable for the public.
I have written a stream wrapper for S3 (protocol) in Symfony.
Also it seems that the Gregwar/ImagineBundle does not support CDN...
As you track down the upload folder config, you can see... tell me if i wrong...
Other thing:
https://github.com/symfony/symfony/issues/4014
Closing as generating the cache directly on S3 won't be supported as
there are many other ways to move files from the computer where you
generated your cache to S3.
by fabpot
Anyway it is sorted out as I can use the assetic:install in symfony command line, just could not figure out setting the public access for the uploaded/generated assets with S3 streamwrapper...
Problems remaining:
symfony assetic install/dump to S3 with the right settings so
available for the public
Gregwar/ImageBundle -> generated images (ie.: forceResize(), usually to /web/cache/...) to CDN
Another update:
symfony assetic install/dump -> I decided to use Bower and Grunt to get the same result. Still no idea how to add that public amazon ACL thingie for the command line... sorry, add a comment here if you know
image uploads -> I am on to "extend" the symfony UploadedFile so when that is triggered to move the file, than the official AWS SDK S3 take over the process and handles it... will let you know with the solution.... [update] I could not modify the move method in a "standard" or non-hacking way. So I created a helper class (using the SDK) and did refactoring with it on the right places.
the Gregwar/ImageBundle cache (after processing images based upon the Twig "function" you know .forceResize) still outstanding... any thoughts are welcome
Cheers
Greg

If https://s3-cdn.com will not change you can concatenate it for your src like this :
src="https://s3-cdn.com~{{ web_image(img_path).forceResize(1000) }}"
or make a twig extension to be cleaner or override the web_image function to build correctly your url and return the right one, overriding it would result on the bundle working only for S3.
update
This question is ambiguous, he wants to upload to S3 not read from it, the twig have nothing to do here.
for more information on the upload :
github.com/1up-lab/OneupFlysystemBundle/blob/master/Resources/… this is a nice bundle it uses the league/flysystem take a look at the page see how they handle uploads to amazon flysystem.thephpleague.com/adapter/aws-s3-v3

Related

Is there a way to access Doctrine repositories from stand-alone code?

I have a Symfony 4 app which is complete and working. Any uploaded files are put inside an upload folder outside the doc root and accessed via a separate cdn url.
Inside the upload folder I have a htaccess file that redirects any request, let’s say for example an image, to a php file which then serves the image.
What I want to be able to do is send an auth key along with the image request so that the standalone index.php file can check the user is valid from the database.
This means I need some way of accessing the symfony entity manager from outside of symfony, by including it. The other option would be a curl request to a symfony controller, but I’d rather not add additional network requests if possible. The third option is a separate pdo direct to the database and make sql queries... but again I’d prefer to use the symfony entity manager by including symfony somehow so I can use other features if needed.
I actually tried including the symfony bootstrap in the index.php but that then drags in the need for routing to work which isn’t needed in this case.
You can access EntityManager like that:
require __DIR__.'/../vendor/autoload.php';
(new Dotenv())->load(__DIR__.'/../.env');
$kernel = new Kernel('dev', true);
$kernel->boot();
$user = $kernel->getContainer()->get('doctrine.orm.entity_manager')->getRepository(Repo::class)->find(id);
dd($user->getRoles());

Symfony not found static files (images, js, txt)

How can Symfony deliver static files without bootstrapping/executing the framework?
For example: if some requests are failing by the webserver(images, js files are not found or something like this) then the framework tries to solve the route. Of course this does not exists.
Is there a way to avoid this or blacklist these extensions?
It could be a cache problem.
If it is :
If it is a cache problem, you could try to clear the cache on the symfony console with cache:clear. If it doesn't work you could try to remove the ressources in the general folder, leaving the original ones in your bundle, and running assetic:dump and assets:install.
If it isn't
Regarding the "remove-symfony-routing" thing, I don't know if it's possible, but it should not done anyways.
What you're asking is to be able to access, from the client side, any file on the server, which constitutes a major security breach.
This could allow the client to get any file on the server, meaning he could get his hands on your javascript or php files which most of the time contain valuable information (such as how your app works or even deadlier : global passwords and config values)
What you could do to access resources from the client would be a route that points to a controller function that could output to browser the file you're looking for, provided that it has an extension you'd be ok to share. For example you could allow any image file but forbid code files such as php or javascript.
EDIT: Or yeah, configure your webserver correctly. 2 simple answers while I was typing :D

symfony: how to reference images generated using LiipImagineBundle when not having web/ as index directory

I have installed LiipImagineBundle to apply filters to my images, on my localhost.
It works perfect. It generates images like my_project/web/media/cache/my_widen/images/products/image.jpg, that I show using this:
<img src="{{ ('/images/products/' ~ product.imageName) | imagine_filter('my_widen') }}">
The problem: in my remote shared server, the index directory is not my_project/web, as I defined in my local machine, but just my_project/. Since I can not change it to my_project/web, I can not see the images at web/media/cache... unless I use this:
What should I do to show them correctly in both machines (local and remote) using the same code?
It sounds like you need to change the data_root in the bundle's configuration. Read the configuration chapter of the documentation for more information.

Symfony2 - how to display content and secure access to it

I'm developing an application that displays books as interactive flash content with Symfony2. Each book has one index.html file that carries all those flash things embedded in html code and some directories with all required parts of book (images, js files, etc.) linked with this index.html file and each other by 'src' and 'href' tags etc. I'd like to display these books on my website and, at the same time, to prevent anonymous users from downloading them.
For example:
I have my books in web/Books folder and to display Book1 I have to display web/Books/Book1/index.html file. By putting those files in web directory I allow anonymous users to access them by typing for example www.example.com/Books/Book1/index.html or something similar for images, js files etc (paths can be read from content of book's index.html).
Is there any way to prevent from this?
I am an admin of the server, root directory is set on web directory, as recommended.
Thank you in advance for any answers.
EDIT. [SOLVED]
Okay, I found the solution. It's something similar to Pier-Luc's Gendreau proposal.
The idea:
All books are located in 'books' folder, path to index.html of each book is /books/{title}/index.html. In .htaccess I wrote RedirectMatch, for example: /books/book1/index.html is redirected to /bookrouter/book1/index.html. Path like this isn't path to existing file, so Symfony2 can handle it as route. Route pattern is /bookrouter/{path}.{_format} (with requirement for {path} for allowing '/' sign), so I can create accurate response with proper headers and content and serve required files with all required authentication/authorization. There are two bad sides of this:
1. I have to handle each file extension separately to create proper http headers and content.
2. More experienced programmer said that if we will have as many users as we expect, this way of handling each request will kill our server so we can't use it.
So people, thank you for your time! I hope that my solution is described clearly and maybe someone in the future will find it useful. Cheers!
you will need to setup a firewall to deny anonymous users access to certain routes.
See the documentation chapter Security.
For a quick start consider using FOSUserBundle.
Without any modifications to your current structure, I think you're looking for an answer that doesn't exist. The books are outside Symfony, thus ruling out every proper Symfony way of securing access. You're pretty much stuck with basic HTTP authentication with .htaccess.
However, you could bring the books inside Symfony.
Firstly, move your index.html books where the views are stored, renaming every book to it's slug (Book1's index.html becomes Book1.html, etc)
Secondly, create a BookController whose base route is /Books and a secureBookAction with a $slug parameter so that the book route is /Books/{slug}. It seems like you are aware how to secure a route so I'll leave that up to you.
Thirdly, render the view based on the slug parameter. You will probably want to keep a list of the books so you can react properly to a slug that doesn't correspond to a book.
Lastly, I would leave your assets where they are now, just make sure you're using absolute paths otherwise they will break. It'll be simpler that way and they are unlikely to be useful without the accompanying book.
Sorry if my answer is a light on code, I haven't touched anything Symfony in a few weeks though I think I have made the strategy clear.
To secure css, js and image files you should use Assetic, because Assetic generate new URL's for the assets.
For example, here the new URL will be /css/secure :
{% stylesheets '#AcmeFooBundle/Resources/public/css/secure-folder/*' output='css/secure/' filter='cssrewrite' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
Then you can restrict this route for anonymous users.
# app/config/security.yml
security:
# ...
access_control:
- { path: ^/css/secure, roles: ROLE_USER }

Symfony cannot find template on prod server

Should be simple enough. Everything works in my local environment, but not on my prod server (neither prod nor dev environment). I get an error that the FOS template cannot be found:
Unable to find template "FOSUserBundle::layout.html.twig".
My code is simple:
{% extends "FOSUserBundle::layout.html.twig" %}
I'm going from my local Windows machine to a Linux box. I've read case sensitivity might be the culprit, but it doesn't seem like it.
The FOS bundle is in the normal place: vendor/friendsofsymfony/user-bundle/FOS/UserBundle.
I'm having trouble diagnosing - any ideas? Did things get screwed up when I FTPd? Permissions issues? What are the common gotchas? I'm desparate!
Update: A clue. I ran assetic:dump and got
[RuntimeException]
".../app/Resources/FOSUserBundle/views/layout.html.twig" resource is hidden by a
resource from the "*******Bundle" derived bundle. Create a
".../app/Resources/*******Bundle/views/layout.html.twig" file to override the bundle
resource.
This question seems relevant.
Another update: I was using getParent() in my own bundle to override the templates. I switched to the first method in the docs but now the templates in app/resources simply aren't having an effect. It's going straight to the default form template with a white background.
Any ideas?
It was a upper/lower case/namespacing thing. I thought my local files were in sync with remotes but they were not.
Just check your whole directory & all namespaces in the FOS bundle!
I also encountered the problem and "solved" it by renaming my layout.html.twig inside my bundle's Resources/views folder to bundle-layout.html.twig and adapting my templates accordingly.
I resolved the resource is hidden by a resource error by moving the template in the good bundle extension.
Specifically from app/Resources/FOSUSerBundle/views/ChangePassword
to src/Application/Sonata/UserBundle/Resources/views/ChangePassword
I confounded FOSUser & SonataUser.

Resources