Jump to content

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


LAPS
 Share

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
Link to comment
Share on other sites

  • LAPS changed the title to How to allow guests to access protected page's field values and assets just for some occasions?

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? 

Link to comment
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.

Link to comment
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 ?)?

Link to comment
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 7
  • Thanks 1
Link to comment
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
Link to comment
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.

Link to comment
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…

Link to comment
Share on other sites

  • 6 months later...
On 6/13/2018 at 5:22 PM, dragan said:

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

On 6/13/2018 at 5:23 PM, 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 ?)?

Any news on the @dragan approach? I also created a dedicated topic.

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...