Symfony2: How to hide link in Twig based on permissions - security

My application shows a list of projects, project detail pages and forms to edit these projects. These are the routes:
/ - list of projects
/project/42 - view project (project detail page)
/project/42/edit - edit project
Only its owner may edit a project.
I have implemented a Voter to prevent access to /project/42/edit for non-owners.
Now, I also want to hide the link "edit project" from the project detail page. What would be the way to do this? Ideally, in Twig, I would like to do something like
{% if may_access(path('project_edit', { 'id': project.id })) %}
edit project
{% endif %}
I can implement this function as a Twig extension, but maybe a similar functionality already exists.

The function is_granted() actually has a second parameter that allows me to do just what I need:
{% if is_granted("MAY_EDIT", project) %}
edit project
{% endif %}
I use this in combination with a check in the controller action:
public function editAction(Project $project)
{
if (!$this->get('security.context')->isGranted('MAY_EDIT', $project)) {
$this->flash('You are not allowed to edit this project');
return $this->show($project);
}
// ...
}
This is actually very similar to the approach that nifr used in his answer to Sonata User - Security on custom field. I was hoping to find a way to have the voter be called automatically and avoid the call to isGranted().
If you want to have a look at the complete code, it is in the tutorial project I have published in github.

Related

Which twig template to extend for a custom theme?

I apologise before for a long explanation - I have a hard time explaining it to myself.
I run Shopware 6 locally and using the development template. I needed to remove the product number from the product detail page. So, I override the twig template "buy-widget.html.twig":
{% sw_extends '#Storefront/storefront/page/product-detail/buy-widget.html.twig' %}
{% block page_product_detail_ordernumber_container %}
{% endblock %}
Works as expected - if I have not change the layout template for the product, but using the Shopware default.
But, when I change the layout to a custom layout (the only difference is that the image thumbs is bellow the main image) the product number is back?!
Checking with the Symfony Profiler, I can see that it's now another twig template (from a folder "component/.." responsible for displaying the product number.
Question: Am I correct to assume that I should extend the twig template from this component folder if I'm using a custom layout? I have not find anything in the docs about these "small" details. And if one need to be sure that a custom theme works in every case, you must make the changes (using sw_extends) in two files?
/ Magnus

How override a template?

Following the documentation to override catalog.html.twig, I see that the "Hello World!" display does not work.
I cleared the cache.
I also tried to override view.html.twig with the following logic:
file path :
/modules/foo/views/PrestaShop/Admin/Sell/Order/Cart/view.html.twig
the content :
{% extends 'PrestaShopBundle:Admin/Sell/Order/Cart:view.html.twig' %}
{% block cart_summary %}
Hello world!
{% endblock %}
But unfortunately nothing works.
Do you have any ideas ?
overriding the admin templates require installed module.
Simply create and install your module via 'module manager' in admin panel, then inside of the module create this path "views/PrestaShop/Admin/Sell/Order/Cart/view.html.twig".
It should work now.
You have to create a module, I think that I have to put the file inside the override folder, but no.
You have to create a module whit that tools of prestashop and the create the path in views like the other answer say.
The module can be generic and doesn't matter the hook.

Drupal 8 Twig User ID?

I'm new to Drupal & Twig and all I need is in my custom theme a twig expression to output the current user's ID. I can't find anything in the template comments, only if a user is logged in true / false.
Is there a simple way to get the ID of the current user? I'm not sure how to implement custom methods in a theme.
thanks!
Hello bobomoreno,
I would suggest you use the module Bamboo Twig.
The Bamboo Twig module provides some Twig extensions with some useful functions and filters aimed to improve the development experience.
You could then enable the sub-module Bamboo Twig - Loaders:
drush en bamboo_twig_loader -y
Finally, you will be able to use the Twig function bamboo_load_currentuser:
<!-- Get Current User -->
{% set user = bamboo_load_currentuser() %}
<div>{{ user.name.value }}</div>
<div>{{ user.uid.value }}</div>
You can find the complete official documentation there.
In your theme find file yourthemename.theme and add following code:
function yourthemename_preprocess(&$vars, $hook)
{
$vars['uid'] = \Drupal::currentUser()->id();
}
now if you edit your twig template for html, page, region, block, field, form element... you can use 'uid' token in your twig. It works for all hooks
If you only need the ID in user.html.twig, it's {{ user.id }}
Here's how D8 now works, in two lines of executable code:
<?php
// This code returns the current user ID.
$account = \Drupal::currentUser();
return $account->id();
The display name is not a field you can configure in {{ content }}. You can get it directly from the user entity:
{{ user.displayname }}
Reference for the php method: AccountInterface::getDisplayName
The Twig Tweak module is very small and yet very powerful. You can get the current user id with drupal_token('current-user:uid') I am using it to pass the current user id to a view like this:
{{ drupal_view('view_name', 'embed_1', drupal_token('current-user:uid')) }}

Grav CMS: how to show/hide parts of the page depending on conditions?

The Grav's documentation clearly describes how a whole page or a folder could be hidden from unregistered users. It also describes how a whole page could be seen only by particular user groups.
But what about pieces of a page, let's say, some links or a private info I want to show on some conditions?
Ok, for registered users I found a snippet at Login plugin docs:
{% if grav.user.authenticated %}
content for registered users goes here
{% endif %}
But going wider - how can I show/hide pieces of a particular page depending on some custom logic in PHP code, i.e. not necessarily user related?
I'm thinking about a twig/shortcode plugin, something like:
{% if some.custom.condition.or.PHP.function %}
hidden content goes here
{% endif %}
or
[hidden_if_something] hidden content goes here [/hidden_if_something]
But not sure how exactly this should be implemented. So working examples would be appreciated. Thanks.
There is a recipe in the Grav documentation here. This provides an example of how to render the output of a PHP code result in a twig template.
In the example they create a plugin, and implement a twig extension providing access to a php function. They can then simply call that php function like in a twig template.
{{ example() }}
Following that example, you can implement whatever logic you would like in php, and call the function in a twig if statement.
{% if example() == true %}
your conditional output
{% endif %

Symfony Server crashes when extending FOSUserBundle's default template layout.html.twig

I am trying to get the basic user login running from the FOSUserBundle.
I am using Symfony 3.0.6.
I followed the description to setup everything from the FOSUserBundle:
https://symfony.com/doc/master/bundles/FOSUserBundle/index.html
DB is up and running everything seems fine except I cant figure out how to override the layout.html.twig from the FOSUserBundle.
I followed this description for achieving that:
https://symfony.com/doc/master/bundles/FOSUserBundle/overriding_templates.html
I now have a file "layout.html.twig" in the folder "Resources/FOSUserBundle/views" with the content being the same as in the last link provided above.
This leads to the following error:
Unable to find template "layout.html.twig" (looked into:
[somePathInfo]) in FOSUserBundle::layout.html.twig at line 1.
Now I changed the first line in the "layout.html.twig" Template to be
{% extends 'FOSUserBundle::layout.html.twig' %}
And this then leads to the symfony server to crash stating
>php bin/console server:run -v
[OK] Server running on http://127.0.0.1:8000
// Quit the server with CONTROL-C.
RUN "C:\xampp\php\php.exe" "-S" "127.0.0.1:8000" "[PATH]\myProject\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Resources\config\router_dev.php"
RES -1073741571 Command did not run successfully
[ERROR] Built-in server terminated unexpectedly.
I am stuck here...
Any ideas are very welcome.
EDIT: The FOSUserBundle installed by the composer (which I use through the current PHP-Storm plugin) is installed at the path:
[projectPath]\vendor\friendsofsymfony\user-bundle\Resources\views\layout.html.twig
In the docu however allways "FOSUserBundle" only is mentioned and I don't know how to figure out if that mapping fits to the path in my project.
Any hints for this issue are very wellcome as well.
When you override standart FOSUser layout you need to place your layout into app/Resources/FOSUserBundle/views/layout.html.twig. great, you did this. it's just a layout, it should not extend standart FOSUser layout, so remove line {% extends 'FOSUserBundle::layout.html.twig' %}. But usually developers make one base layout, in my case it is \app\Resources\views\base.html.twig, so if I want to override fosuser layout I will have in app/Resources/FOSUserBundle/views/layout.html.twig something like this
{% extends 'base.html.twig' %}
{% block title %}User Management{% endblock %}
{% block content %}
{% block fos_user_content %}{% endblock %}
{% endblock %}
In first line you extend your base layout not FOSUser. You may not extend something, maybe you have separate complete layout for this template.
The crash does make sense.
When you write:
{% extends 'FOSUserBundle::layout.html.twig' %}
The Symfony will first try to load app/Resources/FOSUserBundle/views/layout.html.twig. Failing to find the file will revert to similar path but inside the vendor directory. And if you are trying to extend FOS's template from within your FOS overriden template, that would create recursive loop:
app/Resource/FOSUserBundle/views/layout.html.twig
^^ extends
app/Resource/FOSUserBundle/views/layout.html.twig
^^ extends
app/Resource/FOSUserBundle/views/layout.html.twig
....
and so on...
So, this is not a way to solve the problem.
Make sure that your template is well placed in your app directory and not your bundle, as Denis Alimov suggested in a comment.

Resources