when a custom URL under "Link display" is used for a given display, there is not anything in views to check user access to these links.

@dawehner suggested using the access system provided by the routing system.

this was discovered in #2020393-11: Convert "Recent content" block to a View, when a "More" link was being added.

Instructions to reproduce the issue:

  1. Install fresh D8 (standard profile)
  2. Go to /admin/structure/views/add, to add new view
    1. Name the view as "Admin only"
    2. Select "Create a page"
    3. Click "Save and edit"
    4. Under "Page Settings" choose a link after "Access: Permissions". By default it's "View published content".
    5. Choose "Administer blocks"
    6. Save the view
  3. Go to /admin/structure/views/add, to add new view.
    1. Name the view as "Public"
    2. Select "Create a block"
    3. Click "Save and edit"
    4. Under "Pager" choose link after "More link:". By default it's no.
    5. Select "Create more link" and "Always display the more link"
    6. Click "Apply"
    7. Under "Pager" choose link after "Link display:". By default it's "none".
    8. Select "Custom URL" and enter "admin-only" to the field
    9. Click "Apply"
    10. Click "No Results Behavior" -> Add
    11. Choose "Global: Text area"
    12. Click "Apply"
    13. Write "This is a public view" to the textfield
    14. Click "Apply"
    15. Save the view
  4. Go to /admin/structure/block/add/views_block%3Apublic-block_1/bartik
    1. Select "Sidebar first" from the "Region" dropdown menu
    2. Click "Save Block"
  5. Log out
  6. Go to the front page
  7. Link "more" is showing on a public block.

Comments

This is just a rough outline, what to do.

By general idea here is to use Drupal::service('router.route_provider')->getRoutesByPattern in DisplayPluginBase::renderMoreLink().

Once you have the route you can use menu_item_route_access (or its successor, once its exists) to check the actual access.

Assigned:Unassigned» jiv_e

Hi!

I'll try to take this one. dawehner introduced this on IRC. This is my first D8 issue so I hope you can bare with me.

dawehner said on IRC:
- have a look at core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php::renderMoreLink()
- there is simply no access check going on at all

He also gave me instructions to reproducing the issue:
- for exampe create two views, of which one is restricted to admins
- the second one uses a more link with a custom URL
- which has the URL of the first view

I tried to write a more detailed description:

Instructions to reproduce the issue:

  1. Install fresh D8 (standard profile)
  2. Go to /admin/structure/views/add, to add new view
    1. Name the view as "Admin only"
    2. Select "Create a page"
    3. Click "Save and edit"
    4. Wait for the form to reload
    5. Under "Page Settings" choose the link after "Access: Permissions". By default it's "View published content".
    6. Choose "Administer blocks" and save the view.
  3. Go to /admin/structure/views/add, to add new view.
    1. Name the view as "Public"
    2. Select "Create a page"
    3. Click "Save and edit"
    4. Wait for the form to reload
    5. ...

I realize that now I have to provide the custom more link to the "Public" view. I don't know how. I couldn't find a way to do that in the UI. I found the code you were talking about here. It's not about the view, but the old code your are trying to get rid of, right? I found it from the node.module's function theme_node_recent_block. It's about the more link though.

I also checked the views config file (views.view.public.yml). I found no pointers there.

Thanks for writing this down, that is quite helpful!
If you do have a block display for example you can configure under Link display which display to link to or specify a custom path.

I had time to look at the code in DisplayPluginBase::renderMoreLink().

I'm probably able to solve the issue on this level. But I'm thinking is there already some general solution to this problem? I would presume this kind of checking for links is needed in many occasions. So it seems that this checking should be centralized. Do you agree?

I'm also wondering why views is rendering the link tag in a template file.

view-more.html.twig:

<div class="more-link">
  <a href="{{ more_url }}">
    {{ link_text }}
  </a>
</div>

Shouldn't we use LinkGenerator::generate to create the link tag?

Could we add the access check to LinkGenerator?

EDIT: I discussed this on IRC. Timplunkett and webchick thought it would be slow to implement this in LinkGenerator. I suggested adding a parameter to generate function if the check is needed.

webchick: jiv_e: Hm. Mmmmaybe. But that just makes the function harder to parse, since it'd have this whole branch of code that'd only execute for some links. It's probably still better to handle in the caller.

I suggested a separate helper function for doing this kind of general access check. I haven't seen any counter arguments yet. I would say this would be good because this is a general task and may be needed elsewhere. So it would reduce duplicate code.

I'm also thinking:

jiv_e:...it's also strange that a site builder decides to make a view on some content as a block and let's somebody see that even if that user doesn't have access to the more page. So in this case we could blame the site builder, right?

If we accept this then this issue shouldn't be fixed.

Status:Active» Closed (won't fix)

After discussing with dawehner in IRC we decided that we should not fix this.

Reason is that it's seems to be an exotic edge case if someone needs to build a views block without restricted access and then restrict the access to the "more page". This functionality needs not to be in core.

Also... this is not a security issue because after clicking the link user gets "Access denied" page. It would just be a small annoyance for the user and the site builder could fix it in different ways if it's really needed.

Issue summary:View changes

Add instructions to reproduce the issue