LAPS

How to allow guests to access protected page's assets just for some occasions?

Recommended Posts

I've set the template protected-pages so that only certain, non-guest user roles have access to view pages. I've also set $config->pagefileSecure = true in the config.php file so to prevents http access to file assets of access protected pages.

In the protected-pages template file I use the following sample code (note use of check_access=0):

$protected_pages = $pages->find("template=protected-pages, check_access=0, title~=somewords");

foreach($protected_pages as $protected_page) {
  echo $protected_page->title . "<br>";
  echo "<img src='$protected_page->image->url' alt='$protected_page->image->description' />";
}

The above code shows to guests the page title (as expected) but not the image.

I would like to allow guests to access not only page titles but also image files of protected pages, and just for this occasion. Is it possible (maybe just switching pagefileSecure settings on/off at runtime)? If so, how can I make that?

 

  • Like 1

Share this post


Link to post
Share on other sites

Hi LAPS,

Sorry if I'm not following here, but have you tried:

$protected_pages = $pages->find("template=protected-pages, title~=somewords");

foreach($protected_pages as $protected_page) {
  echo $protected_page->title . "<br>";
  echo "<img src='{$protected_page->image->url}' alt='{$protected_page->image->description}' />";
}

Instead? 

Share this post


Link to post
Share on other sites

@Tom. it works the same by using and not using '{' and '}' in the img tag.

As you guessed, the problem still remains. Thanks anyway.

Share this post


Link to post
Share on other sites

Hi @LAPS

Can you copy some of the HTML that is being output to the users? Mainly what the img tag is outputting

Share this post


Link to post
Share on other sites

@Tom. certainly! Here it is when rendering one image:

somewords<br>
<img src="/site/assets/files/1258/image.jpg" alt="img description">

The problem is that the image is not accessible probably because it is protected by PW even if I use check_access=0.

Note: I edited the original post adding the check_access=0 in the selector for finding protected pages.

Share this post


Link to post
Share on other sites

I've never used pagefileSecure, but you could try temporarily to add permission with $permissions->add("name") or similar.

  • Like 1

Share this post


Link to post
Share on other sites
4 minutes ago, dragan said:

I've never used pagefileSecure, but you could try temporarily to add permission with $permissions->add("name") or similar.

How can I make that (even though I think it's not the best solution since the check_access=0 should work also for accessing files 😉)?

Share this post


Link to post
Share on other sites
1 hour ago, LAPS said:

How can I make that (even though I think it's not the best solution since the check_access=0 should work also for accessing files 😉)?

That's likely not going to be trivial. Adding check_access=0 in a selector to display the link is quite another thing as serving the secure file to a guest user. When you have pageFileSecure enabled, the following happens:

  • PW prefixes the file directory site/assets/files/[PAGEID] with $config->pagefileSecurePathPrefix ("-" by default so it will be site/assets/files/-[PAGEID])
  • When the browsers tries to show the image (i.e. open the URL /path/to/pw/site/assets/files/1258/image.jpg in a separate request), the file isn't found by .htaccess
  • .htaccess hands off the request to index.php
  • index.php calls PageRender::execute with the request URL
  • PageRender::execute checks if the request is to a file, then checks if the page it belongs to is published and viewable by the current user
  • Since $user->hasPermission('page-view', $page) returns false (the guest user doesn't have view permissions) that fails (otherwise, PW would prefix the path now and output the file)
  • PW outputs the 404 page

Since the method where the check is are done is not hookable (and some necessary properties and methods are protected, i.e. not reachable from a hook) you'd probably have to

  • hook before ProcessPageView::execute and duplicate a lot of code from ProcessPageView
  • or hook after User::hasPagePermission and at least duplicate ProcessPageView::checkRequestFile
  • in both cases, match the file URL to $page->image to prevent handing out a access to other file/image fields on the page

Another approach (if the images aren't too big and the protected pages aren't too many) would be to include the real image data as data URIs:

<?php

foreach($protected_pages as $protected_page) {
  echo $protected_page->title . "<br>";
  $fn = $protected_page->image->filename;
  $imgdata = "data:" . mime_content_type($fn) . ";base64," . base64_encode(file_get_contents($fn));
  echo "<img src='$imgdata' alt='{$protected_page->image->description}' />";
}

If the images are small enough but you have many pages, using PW's pagination might be an option too.

  • Like 2

Share this post


Link to post
Share on other sites
38 minutes ago, BitPoet said:

Another approach (if the images aren't too big and the protected pages aren't too many) would be to include the real image data as data URIs:


<?php

foreach($protected_pages as $protected_page) {
  echo $protected_page->title . "<br>";
  $fn = $protected_page->image->filename;
  $imgdata = "data:" . mime_content_type($fn) . ";base64," . base64_encode(file_get_contents($fn));
  echo "<img src='$imgdata' alt='{$protected_page->image->description}' />";
}

If the images are small enough but you have many pages, using PW's pagination might be an option too.

Very nice solution – i had the same issue with user profile pictures … this could work…

On one of my pages I have a similar setup, I provide protected files using the page and the filename and then manually serving it using the render hook… Would need to look into the code… Something like > pathtothepage/?f=filename.jpg – because you know the page, you can access the file with PageFilesManager ($page->filesManager) and then send it using http://processwire.com/api/ref/wire-http/send-file/

  • Like 2

Share this post


Link to post
Share on other sites
2 minutes ago, Noel Boss said:

On one of my pages I have a similar setup, I provide protected files using the page and the filename and then manually serving it using the render hook… Would need to look into the code… Something like > pathtothepage/?f=filename.jpg

Actually, you wouldn't even have to pass the filename. If you assemble the image URL like this, you could just as well use a unique parameter that tells your hook to output the image contained in whatever field you want and can stop worrying about exposing the wrong file. Like {$page->url}?showprofileimage=1.

Share this post


Link to post
Share on other sites

Thanks for the replies.

@BitPoet your code works.

 

It'd be correct if the check_access=0 handles/supports access to files too. What do you think about? Could it be an inbuilt PW feature? @ryan

Share this post


Link to post
Share on other sites
14 hours ago, BitPoet said:

Actually, you wouldn't even have to pass the filename. If you assemble the image URL like this, you could just as well use a unique parameter that tells your hook to output the image contained in whatever field you want and can stop worrying about exposing the wrong file. Like {$page->url}?showprofileimage=1.

I have multiple files on said page and inside repeaters, so this does not work…

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.