How to move slug to subdomain in Symfony3 - symfony

I have a web-app where every User has his own personalized link
https://app.myapp.com/{uuid}/frontpage
Where uuid indicates User resource loaded from the database.
And now, the idea is to move /{uuid}/ to subdomain, so it should look as follows:
https://{uuid}.myapp.com/frontpage
While I have created wildcard DNS and can extract subdomain in Symfony's Controllers easily, the problem is now how to tell Symfony that uuid should be taken from subdomain now.
In Controllers I have routing defined as follows
/**
* #Route("/{uuid}/frontpage", name="frontpage")
* #ParamConverter("user", class="AppBundle:User", converter="converter.user")
* #Template("FrontPage.html.twig")
*/
public function indexAction(Request $request, User $user)
{
}
I would like to avoid rewriting all Controllers and strip out /{uuid}/ part because I have hundreds of Controllers defined like that.
Is there a way to manage this maybe via Listeners?

With Symfony 3, you can match a route based on the host. And basically you can also "placeholderize" your subdomain and get the related value in your HttpFoundation\Request object (in your controller for instance).
Ex. :
mobile_homepage:
path: /
host: "{subdomain}.example.com"
defaults:
_controller: AppBundle:Main:mobileHomepage
subdomain: m
https://symfony.com/doc/current/routing/hostname_pattern.html

Related

Security firewall logout path redirects to http instead of https protocol

Security firewall logout path redirects to http instead of https protocol.
I've tried adding annotation parameters, like: schemes={"https"}
Also I added in security.yaml, the path to the logout route.
- { path: /api/v1/user/logout-result, requires_channel: https }
Still to no luck. Is there anything else I could do?
I managed to fix my issue.
I removed the target property from logout and added success_handler, which points to my custom service class.
The custom service class auto-injects the RouterInterface and its function
public function onLogoutSuccess(Request $request)
returns new RedirectResponse object which points to the /api/v1/user/logout-result route.

Symfony2 and WebRTC, routing issue

So I use Pubnub for WebRTC in my Symfony 2 application, and all works well, apart from the showing of videos of other users. What happens is that when a user connects, an url gets generated like this one:
mediastream:http://www.domain.com/cd024a62-02fa-42eb-8f52-621074ea887e
These url's are temporary, and the only purpose is to serve as a way to connect video streams. After the WebRTC session the do not exist anymore and they are impossible to predict.
Since the Symfony router cannot find a route to 'http://www.domain.com/cd024a62-02fa-42eb-8f52-621074ea887e', the stream is never showed (www.domain.com is the url to the symfony application in this example).
What I could do is adapt the exisiting scripts so that all video streams look like 'http://www.domain.com/video/cd024a62-02fa-42eb-8f52-621074ea887e', but in that case any route with prefix /video/ should be left alone by Symfony.
Any ideas?
In the end I found a solution. As a last routing rule I added:
display_blob:
defaults: { _controller: Bundlename:Main:blob }
path: /{blob}
Then I created a function in the Main controller:
public function blobAction(Request $request)
{
$path = $request->getUri();
return $this->render($path);
}
Of course I need to do some filtering of the URL itself and check if it really is a stream, but for now I am happy it works.

Conflicts in routing in symfony between bundles

Playing around with symfony. I have two bundles and each bundle has a controller within it. Just to see how routing works I gave the same path to functions within both controllers. Bundle B was the newly created bundle and when the URL app/simple was hit I got a response from bundle B always. Just curious as to whether there is any logic behind this.
PS: I know this is bad practice but just wanted to see how the guts of routing in works.
/**
* #Route("/app/simple", name="homepage")
*/
public function indexAction()
{
return new Response('Hello From bundle A!');
}
In bundle B
/**
* #Route("/app/simple", name="homepage")
*/
public function indexAction()
{
return new Response('Hello From bundle B!');
}
Your app has a single routing configuration which can include other configurations. Probably app/config/routing.yml.
That configuration file will include the routes for your bundles by using the resource key that can import routes from another routing.yml file or from annotations in a PHP controller.
The order of those will determine which route gets chosen since Symfony2 always uses the first matching route.

find user by username from multiple providers [symfony2]

I need to find a user object in symfony2 based on the username or emailadres. This is not for loggin in, but for other actions on a user.
I can simply request the (Doctrine2) repository and call the method loadByUsername from the UserProviderInterface that is on my repository-class.
But the code that needs to do this will be used in multiple projects and I need it to be a bit more generic. The user class/table might be different or the users might come from a completely different type of provider.
Is there a way to find a user by username just like Symfony2 itself uses when logging in?
This way it will work no matter how the user providers are configured in security.yml.
Is there some service in Symfony2 I can use for this?
Is there a "user provider service" where I can call a method something like "loadUserByUsername" that will try each configured provider?
After some poking into the SecurityBundle of Symfony itself, I figured out the following:
Given this is in your security.yml:
providers:
AdministrationUser:
entity:
class: AdministrationBundle\Entity\User
Symfony will create a service with the following name:
security.user.provider.concrete.administrationuser
This service uses the UserProviderInterface and when you fetch this service you can simply call the method loadUserByName and find your user.
So all you need to know is the name of the provider you configured yourself and you can determine the service-name and fetch it.
I'm in a more generic situation, so I added an alias to that service in the Extension-class of my bundle:
// alias the user_provider mentioned
$container->setAlias('my_security_bundle.user.provider', new Alias('security.user.provider.concrete.' . strtolower($config['user']['provider'])));
Where $config['user']['provider'] comes from config.yml (and needs to be configured in your Configuration class, but that is a different story.
Now I can simply use that new alias and I will get the correct service to find my user in a Controller like so:
/** #var UserProviderInterface $userProvider */
$userProvider = $this->get('my_security_bundle.user.provider');
$user = $userProvider->loadUserByUsername('someone#somewhere.tld');

Admin area across various bundles

I'm relatively new to Symfony 2 and I'm working on an application which has an admin only login area located under domain.com/admin/home/ (which itself is a separate bundle called AdminBundle) allowing the admin to manage products
However the same application is also going to have a BlogBundle which will require an admin area to manage blog posts.
What is the best way to tackle this, is there a best practice for multiple admin areas?
It makes sense to keep the blog admin section within the BlogBundle for better re-usability/portability, however all of the login settings will be in the AdminBundle which seems wrong.
One way to do this is to use your security.yml file to secure a set of routes. For example;
access_control:
...
- { path: ^/admin, roles: [ROLE_ADMIN] }
Then when you create your actions you simply need to give them a route with an admin prefix to secure them against all users other than admin. My examples use annotation for routing but you can do the same with yml.
/**
* Edit a Blog entity.
*
* #Route("/admin/blog/{id}/edit", name="blog_edit")
* #Template()
*/
public function editAction()
{
...
Or you could secure every action in the controller by prefixing the class:
/**
* AdminBlog controller.
*
* #Route("/admin/blog")
*/
class AdminBlogController extends Controller
{
...
Then create another controller which handles displaying the blog posts to the end user and give them unsecured routes.
If you want to secure other areas in seperate bundles your can do it in the same way by have secure and unsecure controllers/ methods.actions

Resources