Jump to content

Unique Private Photo Gallery With User Login


NooseLadder
 Share

Recommended Posts

Hi,

My client has asked for a private photo gallery for each of her clients so that they can login independently and access only their photos. The photos must be hidden from public access. I am quite new to Processwire. I already have it set up on my clients site with access to a limited few pages. The site is a basic php/css site with PW bolted on and copies of the php pages requiring access having been put into PW.

Can anyone suggest the best way to implement this. Would it be to create a unique page for each user and only give that user access to that page? I'd rather get some feedback from some of the more experienced PW users before attempting this. Thanks.

Link to comment
Share on other sites

As a brief answer before getting perhaps a more complete one from one of the more advanced PW crew :)

If each user had a login and also their own page under say a template "client", you could make sure that only they can see their general client page by checking if their $user->name and the $page->name are the same, if it is, you are safe to output their content as only they will get to see the page content.

Something like:

if ($user->name === $page->name) {
// show all the pictures and other member stuff
} else {
throw new Wire404Exception();
}

This is all quite basic and you could turn on urlSegments so that you could have gallery on an additional page. Again only those who have the credentials to get to the client page will see the pages beneath it. I've used this method to create whole member areas, if you're interested I'll share with you what I did.

In terms of the actual images that will be stored somewhere in assets/files/... you'll want to protect them somehow (unless protecting through obscurity is enough for your purposes) but will have to let one of the more advanced users advise on this.

EDIT:

To sum up, you could have the following page tree:

Home

About

Clients (clients template)

-- Joe Bloggs (client template)

-- Jane Bloggs (client template)

One thing that can get annoying is having to make sure you're creating both the user and the page and that they share the same name. As my editor was the person adding clients, I made a simple front end template for them to add clients through which created the user and the page at the same time.

You could also just extend the built-in user template to add images and use that but I've found that in the long run having non user pages is more flexible for outputting data.

  • Like 4
Link to comment
Share on other sites

One thing that can get annoying is having to make sure you're creating both the user and the page and that they share the same name

A module hooking on user page save would make this easier, but I don't know how to help there :)

Link to comment
Share on other sites

I've used this method to create whole member areas, if you're interested I'll share with you what I did.

Thanks for your replies. Yes I would be interested in seeing that thanks.

This is all quite basic and you could turn on urlSegments so that you could have gallery on an additional page.

I don't know what you mean. Can you please explain further.

My client will need to create the user and associated gallery pages herself. Can this process be made reasonably bullet proof for a non-techie end user?

I would like to add that I really do not know how to get this started so any help is much appreciated.

Link to comment
Share on other sites

Thinking a bit further.

I could have a main page with public access.

On this page are the links to the pages that need to be password protected.

Each user has been given their login details to their page.

When that link is clicked the user is asked to login with their details.

Maybe that is what onjegolders is implying above. Can individual pages be set up for user login?

Link to comment
Share on other sites

Hi Noose, will your client have access to the admin? I'm guessing yes.

Essentially once you've done it once you will find it simpler.

You will create pages of type "member" which will sit under "members".

You will also create users.

You want the username to match the name of their corresponding "member" page.

In your templates you will check to see if user->name is equal to $page->name.

If so, they can see the page.

The easiest way is to get the member to login (I can show you all my templates if you like)

If their login is successful, they will be redirected to their profile page which will be at /members/john-doe/

And this will contain any information which has been stored on their page, including images, files, anything relating to just them.

  • Like 1
Link to comment
Share on other sites

<!-- Members Template -->

<?php if ($user->isSuperuser() OR $user->hasRole("editor")) {

$members = $page->children();

if ($members) {

echo "<ul>";

foreach ($members as $member) { ?>

<li><a href="<?php echo $member->url; ?>"><?php echo $member->title; ?></a></li>

<?php }

echo "</ul>";

}

} else {

throw new Wire404Exception();

}
<!-- Member Template -->

<?php if ($user->isSuperuser() OR $user->name === $page->name) { ?>

<h3>Hi <?php echo $page->title; ?> Welcome back</h3>

<?php if ($page->images) { ?>

<h5>Here are your images</h5>

<?php foreach ($page->images as $image) { ?>

<img src="<?php echo $image->url; ?>" alt="<?php echo $image->description; ?>" />

<?php } ?>

<?php } ?>

<?php } else {

throw new Wire404Exception();

}

<!-- Login Template -->

<?php 

$out = "";

$form = "
<form action='./' method='post' id='login_form'>

<label for='login_name'>Username</label>
<input type='text' name='login_name' autofocus>

<label for='login_pass'>Password</label>
<input type='password' name='login_pass'>

<input type='submit' id='submit' name='login_submit' value='login'>

</form>
";

if($input->post->login_submit) {
       // process submitted login form
       $name = $sanitizer->username($input->post->login_name);
       $pass = $input->post->login_pass;
       if($session->login($name, $pass)) {
        if ($user->isSuperuser()) {
            $session->redirect("../members");
           } else {
            $session->redirect("../members/$name");
           }
       } else $out = "<h2>Login failed, please try again.</h2>";
               $out .= $form;

} else {
 $out = "<h4>Please sign in, in order to view your profile page.</h4>";
      $out .= $form;
}

include ("./header.inc");

   echo $out;

include ("./footer.inc");
  • Like 2
Link to comment
Share on other sites

For user login you should use the login system. What onjegolders is suggesting is that you create a normal page on the tree for each user that you associate with it. This would allow you to have all the photos and any other info that you want to associate with the users, without having to use the real user pages for this (that would imply changing the "user" template to accommodate the new fields). Downside for this is that your client would have to create a page with the same name as the user everytime one is created. Apparently onjegolders has a solution for this that sounds good:

As my editor was the person adding clients, I made a simple front end template for them to add clients through which created the user and the page at the same time.

As I said, the alternative would be enhance the "user" template to accommodate all you need for each user. This is actually very simple to do, and I think you should at least try it. To do this go to setup>templates and click the "filters" bar to expand it, and choose yes for "show system templates". Edit the "users" templates and add the fields you need (I would suggest that you create a fiels of type fieldsetTabOpen, and put the new fields on a separate tab). Than your client just have to go to the "users" tab on the admin nav, and add all the info and images for each user there.

Link to comment
Share on other sites

Url Segments can be turned on a per-template basis.

Basically if you turned it on for the "member" template.

You can manipulate the url to show different content.

Say if on your member pages, each member had some profile information but also many images and some files. On your "member" template, you could do the following:

<?php
if ($input->urlSegment1 == "photos") {
include("./photos.inc");
} elseif ($input->urlSegment1 == "files") {
include("./files.inc");
} else {
// Display normal page stuff
} ?>

Then on your photos.inc file:

<?php

$photos = $page->images;

foreach ($photos as $photo) { ?>

 <img src="<?php echo $photo->url; ?>" width="200" height="200" alt="<?php echo $photo->description; ?>" />

<?php }
  • Like 1
Link to comment
Share on other sites

Thinking a bit further.

I could have a main page with public access.

On this page are the links to the pages that need to be password protected.

Each user has been given their login details to their page.

When that link is clicked the user is asked to login with their details.

Maybe that is what onjegolders is implying above. Can individual pages be set up for user login?

Sure, any page can be made to display only if the user is logged in, or has special permission. Again it's just a combination of using an "if" statement.

Eg:

<?php if ($user->isLoggedin()) {
 // display page
} ?>

Or:

<?php if ($user->isGuest()) {
 echo "Sorry you have to be logged in to see this page";
} ?>

As just two examples.

I recommend checking out Soma's really helpful cheatsheet for working in the templates, after a while it becomes second nature but it's still a useful tool.

http://processwire.com/api/cheatsheet/

Link to comment
Share on other sites

In terms of the actual images that will be stored somewhere in assets/files/... you'll want to protect them somehow (unless protecting through obscurity is enough for your purposes) but will have to let one of the more advanced users advise on this.

PW 2.3 protects file-based assets to unpublished or non-public pages, so this won't be a concern much longer.

One thing that can get annoying is having to make sure you're creating both the user and the page and that they share the same name. As my editor was the person adding clients, I made a simple front end template for them to add clients through which created the user and the page at the same time.

Matching up names is just one way to do it. I just put together a quick module that provides another way you could do it even more easily:

  • Like 3
Link to comment
Share on other sites

PW 2.3 protects file-based assets to unpublished or non-public pages, so this won't be a concern much longer.

Is this already in the dev branch? I have it installed and this feature doesn't seem to work. I can still access files from a unpublished or protected page.

Link to comment
Share on other sites

This is all really great stuff. I have tested the new module and it works. What I would like to do is if a user logs in they can only see (view) the page(s) associated with their user name via the page-edit-per-user module, rather than see the complete pages tree.

I did look at diogo's method of adding images to the user profile, but I can't work out how to only display those images to the user that is logged in.

Link to comment
Share on other sites

This is all really great stuff. I have tested the new module and it works. What I would like to do is if a user logs in they can only see (view) the page(s) associated with their user name via the page-edit-per-user module, rather than see the complete pages tree.

I did look at diogo's method of adding images to the user profile, but I can't work out how to only display those images to the user that is logged in.

Read up above Noose for ways of checking who is logged in.

If you were extending the "user" template and adding images to it you could display them in a "profile" template.

<!-- Profile Template -->
<?php
if ($user->isLoggedin()) { ?>
<h2>Welcome back <?php echo $user->name; ?></h2>
<?php if (count($user->images)) { ?>
<p>Below are your photos</p>
<?php foreach ($user->images as $image) { ?>
<img src="<?php echo $image->url; ?>" width="200" height="150" alt="<?php echo $image->description; ?>" />
<?php } ?>
<?php } ?>
<?php } else {
echo "<h4>Sorry you have to be logged in to visit your profile</h4>";
}

That way, only a user who is logged in will see a profile and they will only see their particular page as it is tied to $user

Link to comment
Share on other sites

BUT my module PageListImage module which shows image in the label in the page tree doesn't work anymore then... Arg

Any idea why it doesn't work? As long as it requests the image URL from the file/image field, rather than self-generating it, it should continue to work. Let me know if you'd like me to help troubleshoot this.

Link to comment
Share on other sites

Any idea why it doesn't work? As long as it requests the image URL from the file/image field, rather than self-generating it, it should continue to work. Let me know if you'd like me to help troubleshoot this.

I'll further investigate this issue, yes it is generating a new thumbnail.

Link to comment
Share on other sites

Shouldn't be a problem if its generating a thumbnail. The update is really meant to be as transparent as possible. Here's what's happening with the protected files:

  • Originally you have a URL like this, which is a direct link to the file: /site/assets/files/123/file.jpg
  • When it becomes protected, ProcessWire renames the "123" part to ".123", which according to PW's htaccess file makes the directory blocked from http. (I will probably change this to some other strategy, because directories with periods at the front might be skipped by FTP clients and such).
  • The new link for the file becomes: /path/to/page/-/file.jpg, a URL that will be handled by ProcessWire rather than pointing directly to the file. (the "/-/" part is configurable... it could be "/files/" for instance, if you preferred it).
  • When PW sees that unique URL segment "-" or "files" (or whatever), it first checks that the user has access to the page (/path/to/page). If they have access to it, then it checks if the requested file exists in /site/assets/files/.123/file.jpg. If it exists, it sends it to a passthrough function which outputs the file.

From the perspective of the API, you should not have to make any adjustments in how you work with it. Your code doesn't even need to know that the file is protected. It should all just work without side effects. However, if you are generating your own URL to the file (rather than using the one PW provides) then that won't work, because not only does the "123" directory no longer exist, but the new ".123" directory is not even http accessible.

Link to comment
Share on other sites

Greetings,

Very glad to find this topic, because I had a somewhat related question about handling user roles. Not only was my question answered, but I just expanded my general knowledge of ProcessWire by reading this thread.

This is such a terrific user community, which -- besides the value of the CMS itself -- is like gold to anyone learning this system.

I'm curious about one particular statement that onjegolders made:

... As my editor was the person adding clients, I made a simple front end template for them to add clients through which created the user and the page at the same time.

Can you share more about this? I'm curious about the best ways to give users front-end methods for creating pages.

Thanks again for everything!

Matthew

  • Like 2
Link to comment
Share on other sites

Form Builder is one way to do it. But it's actually very simple to create pages anywhere in ProcessWire from the API. Here's a simple example:

$page = new Page();
$page->parent = '/about/'; // or whatever parent you want
$page->template = 'basic-page'; // or whatever template you want
$page->title = "Test Page";
$page->body = "<p>This is a test, only a test.</p>";
$page->save();

  • Like 2
Link to comment
Share on other sites

Greetings,

Thank you Ryan.

I had a feeling it was not difficult to achieve this in ProcessWire. After all, I have yet to find anything that is difficult to achieve in ProcessWire!

But this should be a warning that, being in my early phases with ProcessWire, I am liable to ask questions that are very easy to answer.

My positive feelings about ProcessWire increase exponentially every day, based on the system itself and the community around it. It's quite amazing how much territory I have been able to cover in just a couple of weeks. And I am -- at best -- an intermediate PHP coder.

Thanks again,

Matthew

  • Like 3
Link to comment
Share on other sites

But this should be a warning that, being in my early phases with ProcessWire, I am liable to ask questions that are very easy to answer.

I think we all like to answer questions here, but especially like ones that are easy to answer. :)

Link to comment
Share on other sites

Greetings,

Very glad to find this topic, because I had a somewhat related question about handling user roles. Not only was my question answered, but I just expanded my general knowledge of ProcessWire by reading this thread.

This is such a terrific user community, which -- besides the value of the CMS itself -- is like gold to anyone learning this system.

I'm curious about one particular statement that onjegolders made:

Can you share more about this? I'm curious about the best ways to give users front-end methods for creating pages.

Thanks again for everything!

Matthew

Hiya Matthew, Ryan's right that Form Builder is an excellent tool for putting complicated forms out there quickly and easily but he's also right that it's pretty simple to do it yourself. I actually finished my templates just before purchasing Form Builder and I'm glad I did as it means I know how to make this all work with my own code but I also have a tool that can make life easier for me in the future.

Form Builder is fantastic and well worth a look but have a go at creating pages yourself with the API, it's very satisfying and easy to get going. Let me know if you need any help with the code :)

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...