Jump to content

Integrating a member / visitor login form


thetuningspoon

Recommended Posts

Yes, have it seen before and take a look at the source code. 

But what is the best way to to it? The existing user profile module or Ryans example here?

Or any other example posted here in the forums?

I don't know how secure and best practise PW modules are. Most Drupal modules are compliant to coding standards (translatable for example). But I found hard coded output (text messages) at user profile module while PW also have the possibility to use translatable text strings...? 

Link to comment
Share on other sites

I quickly looked at the repo and no it's far from good or standard or how it should be or can be. There's just a site folder with modules folder inside that contains a Fieldtype module that is a separate module from another guy. 

I'm not sure why this module is in the directory and it also isn't installable by ModulesManager for example.

I'm sorry as I mind sound patethic, but I always said that we should have clear guidlines how modules repos should be built and that there must be some quality assurance for modules posted to the official directory. This doesn't happen and makes me a little sad. 

(just a quick glance

$pass = $this->sanitizer->text($this->input->post->pass);

Just wrong to sanitize passwords...)

/rant

  • Like 5
Link to comment
Share on other sites

Hi Soma,

thank You for posting here. I agree with you. PW modules need some quality and security assurance and coding guidelines. 

At the moment - my first look at PW and modules - it's a really great framework to build own websites and applications. I'm sure modules from Ryan, you and some other experienced members here are good work and really stable to use! But many modules shouldn't be used at production environments...

So PW needs a better module repo and especially for new users some default modules like a good and stable login, user profile, ... 

Do not misunderstand me, the examples here in the forum are great! But some examples should be build to a module to make PW even more interesting and flexible for new users ;)

  • Like 1
Link to comment
Share on other sites

@Ryan   (or anyone else who can answer)

Does your example code allow a member to become a back end admin?  Or is this code suitable to create a front end members only site.

Also, can anyone point me to some code for new user registration, strictly for front end membership site, seperated completely from the back end admins?

Link to comment
Share on other sites

There's no strictly front vs back logins.

For front-end only, don't give them any of the default installed permissions, and only give him a guest role.

Later on you can expand it, creating own permissions and roles ( sets of permissions ).

You can work with these in your templates.

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...
I'm sorry as I mind sound patethic, but I always said that we should have clear guidlines how modules repos should be built and that there must be some quality assurance for modules posted to the official directory. This doesn't happen and makes me a little sad. 

Just want to mention that the module in question is filed under the proof-of-concept category, which means: 

Proof of concept modules are designed as examples or starting points for others to build from. May not be ideal for users wanting to plug-n-play.

Maybe there is some question as to whether we should even have this category, especially as the modules directory grows. 

I would also like to have dedicated modules managers (people) to ensure the quality and ongoing compatibility of modules in the directory. The current scale is beyond my own ability to keep up with on my own, but a team of us could do it. Soma, you would be my first choice, especially given the number of modules you've created–especially the highly-relevant Modules Manager. The current ratings system in there is meant to be a bit of a crowd-sourced solution, where the best modules also have the most "recommendations". But having a bigger QA team would be far preferable as a primary solution. 

  • Like 1
Link to comment
Share on other sites

What a coincidence that this thread turns up now. I've just finished a system for managing users and was wondering how best to share it. 

It consists of five template files, one stylesheet and a slightly modified InputfieldPassword module (I changed the validation and some text). You setup a page for each template, all of them children of a hidden /access/ page. The various forms are made with InputfieldForm. Each template sets $page->body and then includes a basic-page.php template file, like we see in many of the processwire profiles.

 /access/login/
 /access/profile/    (for changing your password, username or email address)
 /access/logout/
 /access/register/    (for creating a new user account)
 /access/reset/        (for when you've forgotten your password)

  • Each user acount must have a unique username.
  • An email address is collected for each user but does not need to be unique (it's okay for someone to have more than one account).
  • When setting an email address we verify it by emailing a message to that address. Confirm by clicking a link or pasting a code into a form (an 'email-confirmed' role is added).
  • Requests to reset a forgotten password are verified by emailing a message to the account's email address. Confirm by clicking a link or pasting a code into a form.
  • To close the registration process set the /access/register/ page status to Hidden.
     

For my own purposes, this is a convenient parts kit I can quickly add to a project. Seems like the easiest way to share it is as a profile. I suppose I could bundle up the files and create a module which installs everything for you but doesn't that seem just a bit overdone? Any suggestions?

Good points were made above about coding standards, translatable text strings, etc. I'd have to do some work on that. I value the multi-language capabilities in PW but hardly ever need them in my work so if the community insisted on it being standard would that encourage me to get over my aversion to the syntactic baggage it requires or would it discourage me from sharing?

For modules the Proof of Concept category works pretty well. It's nice to share unfinished work. Often the author's intent is easier to grasp in these less filled out implementations. Often there will never be a final version because every project is different. Framework add-ons can actually suffer from too much completeness. Do you want to transplant a seedling or a mature plant?

Perhaps coding standards for modules could be expressed as a checklist and implemented as tags in the Modules section of this site. Likewise for profiles and any other kind of package we may come up with.

Thanks to the many generous and thoughtful coders here.

  • Like 7
Link to comment
Share on other sites

I've just noticed something with front-end logins - too many failed login attempts throws an ugly server error (since we're not logged in we don't see the nice too many login attempts message).

Is there an easy way to intercept and display the appropriate error on the front-end instead of seeing a nasty-looking error page?

Link to comment
Share on other sites

I'm not sure what login you mean but for custom login using $session->login(user,password) you'd have to code it like this:

//..
try{
    $u = $session->login($username, $pass);
    if($u && $u->id){
        $session->redirect("/somepage/");
    }
} catch(Exception $e) {
    echo $e->getMessage();
}
 
  • Like 5
Link to comment
Share on other sites

  • 2 months later...

I recently had to setup front-end system to handle logins, password resets and changing passwords, so here's about how it was done. This should be functional code, but consider it pseudocode as you may need to make minor adjustments here and there. Please let me know if anything that doesn't compile and I'll correct it here.

The template approach used here is the one I most often use, which is that the templates may generate output, but not echo it. Instead, they stuff any generated output into a variable ($page->body in this case). Then the main.php template is included at the end, and it handles sending the output. This 'main' template approach is preferable to separate head/foot includes when dealing with login stuff, because we can start sessions and do redirects before any output is actually sent. For a simple example of a main template, see the end of this post.

1. In Admin > Setup > Fields, create a new text field called 'tmp_pass' and add it to the 'user' template. This will enable us to keep track of a temporary, randomly generated password for the user, when they request a password reset.

2a. Create a new template file called reset-pass.php that has the following:

/site/templates/reset-pass.php

$showForm = true; 
$email = $sanitizer->email($input->post->email);
if($email) {
  $u = $users->get("email=$email"); 
  if($u->id) {
    // generate a random, temporary password
    $pass = '';
    $chars = 'abcdefghjkmnopqrstuvwxyz23456789'; // add more as you see fit
    $length = mt_rand(9,12); // password between 9 and 12 characters
    for($n = 0; $n < $length; $n++) $pass .= $chars[mt_rand(0, strlen($chars)-1)];
    $u->of(false);
    $u->tmp_pass = $pass; // populate a temporary pass to their profile
    $u->save();
    $u->of(true); 
    $message = "Your temporary password on our web site is: $pass\n";
    $message .= "Please change it after you login.";
    mail($u->email, "Password reset", $message, "From: noreply@{$config->httpHost}"); 
    $page->body = "<p>An email has been dispatched to you with further instructions.</p>";
    $showForm = false;
  } else {
    $page->body = "<p>Sorry, account doesn't exist or doesn't have an email.</p>";
  }
}

if($showForm) $page->body .= "
  <h2>Reset your password</h2>
  <form action='./' method='post'>
  <label>E-Mail <input type='email' name='email'></label>
  <input type='submit'>
  </form>
";

// include the main HTML/markup template that outputs at least $page->body in an HTML document
include('./main.php'); 
2b. Create a page called /reset-pass/ that uses the above template.

3a. Create a login.php template. This is identical to other examples you may have seen, but with one major difference: it supports our password reset capability, where the user may login with a temporary password, when present. When successfully logging in with tmp_pass, the real password is changed to tmp_pass. Upon any successful authentication tmp_pass is cleared out for security.

/site/templates/login.php

if($user->isLoggedin()) $session->redirect('/profile/'); 
if($input->post->username && $input->post->pass) {
  $username = $sanitizer->username($input->post->username); 
  $pass = $input->post->pass; 
  $u = $users->get($username); 
  if($u->id && $u->tmp_pass && $u->tmp_pass === $pass) {
    // user logging in with tmp_pass, so change it to be their real pass
    $u->of(false);
    $u->pass = $u->tmp_pass;
    $u->save();
    $u->of(true);
  }
  $u = $session->login($username, $pass); 
  if($u) {
    // user is logged in, get rid of tmp_pass
    $u->of(false);
    $u->tmp_pass = '';
    $u->save();
    // now redirect to the profile edit page
    $session->redirect('/profile/'); 
  }
}

// present the login form
$headline = $input->post->username ? "Login failed" : "Please login";
$page->body = "
  <h2>$headline</h2>
  <form action='./' method='post'>
  <p>
  <label>Username <input type='text' name='username'></label>
  <label>Password <input type='password' name='pass'></label>
  </p>
  <input type='submit'>
  </form>
  <p><a href='/reset-pass/'>Forgot your password?</a></p>
";

include("./main.php"); // main markup template
3b. Create a /login/ page that uses the above template.

4a. Build a profile editing template that at least lets them change their password (but take it further if you want):

/site/templates/profile.php

// if user isn't logged in, then we pretend this page doesn't exist
if(!$user->isLoggedin()) throw new Wire404Exception(); 

// check if they submitted a password change
$pass = $input->post->pass; 
if($pass) {
  if(strlen($pass) < 6) {
    $page->body .= "<p>New password must be 6+ characters</p>";
  } else if($pass !== $input->post->pass_confirm) {
    $page->body .= "<p>Passwords do not match</p>";
  } else {
    $user->of(false);
    $user->pass = $pass; 
    $user->save();
    $user->of(true);
    $page->body .= "<p>Your password has been changed.</p>";
  }
}
// display a password change form
$page->body .= "
  <h2>Change password</h2>
  <form action='./' method='post'>
  <p>
  <label>New Password <input type='password' name='pass'></label><br>
  <label>New Password (confirm) <input type='password' name='pass_confirm'></label>
  </p>
  <input type='submit'>
  </form>
  <p><a href='/logout/'>Logout</a></p>
";
include("./main.php"); 
4b. Create a page called /profile/ that uses the template above.

5. Just to be complete, make a logout.php template and create a page called /logout/ that uses it.

/site/templates/logout.php

if($user->isLoggedin()) $session->logout();
$session->redirect('/'); 
6. The above templates include main.php at the end. This should just be an HTML document that outputs your site's markup, like a separate head.inc or foot.inc would do, except that it's all in one file and called after the output is generated, and we leave the job of sending the output to main.php. An example of the simplest possible main.php would be:

/site/templates/main.php

<html>
<head>
  <title><?=$page->title?></title>
</head>
<body>
  <?=$page->body?>
</body>
</html>

For this, what code for user registration wolud be? I want to implement this login process for my project, but I dont know how to do user registration. Can someone help?

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Seems like session control is preventing a front end editor from logging in with in 60 seconds.  If a front end editor logs out or types in the wrong password, I get a nasty 500 error.  Then after waiting 60 seconds, the login is golden.  I even changed username to pageName and still the same issues continue. Any way to fix this guys?

No matter what, successful or unsuccessful logins, my front end editors cannot login within 60 second from logging out or in or incorrect pass. 

thanks!

Link to comment
Share on other sites

For this, what code for user registration wolud be? I want to implement this login process for my project, but I dont know how to do user registration. Can someone help?

This might get you started:

if(!$users->get('tralala')->id) { // If not exists, Null user returned with ID of 0, thus evaluate to false
  $u = new User(); 
  $u->name = "tralala"; 
  $u->pass = "some-fancy-password-4U";
  $u->addRole("guest"); 
  $u->save();
}
Link to comment
Share on other sites

Any way to create a registration form that automatically ads the user type as frontendeditor? Then when they create a new page via form builder they are assigned to the new page or any other new page they create. Any light on this guys?

Link to comment
Share on other sites

You could set the role and appropriate permissions in the Access section in the Admin so that you know they have page creation privileges. Then create the user and add the role with something like:

$new_page = $users->add($firstName.$lastName.$someThingElse);
$new_page->addRole('frontEndUser');

If you want to restrict them to only their own pages... well there's a lot of ways to do it. Maybe one of the easiest routes is to place a condition on the return value of $page->createdUser like:

if($user == $page->createdUser){
  ...display your content
}
else{
 ...do something else
}

This is really easy if you're using a controller to handle outputting that particular set of page content: something like the SkyScraper Profile _out.php page because you only have to set that code into one page. Again, a thousand and two ways to skin a cat, all depends on what you're working with and what you feel comfortable with.

Link to comment
Share on other sites

@mindfull I have the registration for created and it works in which they are automatically assigned frontend-editor as a role. After a user registers, they are presented with a form builder embedded form, here they can select a category to post a new page too. The form that creates a new page is by form builder as an iframe. This is where I need the help to assign editing privileges to the user that created the new page, but I want them to only be able to edit that page. Right now if we see the new user register, then submit a new page, we manually add them to edit that page. Any light on this?

Link to comment
Share on other sites

@Ryan, do you know how I can prevent an internal server error that shows with all white screen. Basically, I created your front end login. However, if you attempt to login two times with incorrect password it throws the server error. If you login one time with incorrect values, it will toss the wrong user name message. I feel as if it's trying to display the must wait 60 seconds to login like a back end admin and cannot find it since it's a front end login. How can I fix this so I don't get the server error?

Link to comment
Share on other sites

Wow, I spoke too soon.  I get the error message showing properly no, no more server error nasty page.  I simply uploaded your code as a test.  

I get an error message in the footer since I have a link in the footer that changes logout when a user is logged in.

I cannot login period, when I do enter the correct credentials.

Here is what I have:

<?php
if($input->get->logout == 1) {
    $session->logout();
    $session->redirect("./"); // start them on a fresh page, or redirect to another
}

?>





<?php

 

include("./head.inc"); 


?>

<div class="row supersize">
<div class="medium-12 columns">



<div class="medium-4 columns">
<p> </p>
</div>
<div class="medium-4 columns">

 <h1><?echo $page->title;?></h1>

<?php 

/**
 * Login template
 * Based on a forum contribution by Ryan, can't locate it, but the are many examples of login forms.
 * 
 */

if($user->isLoggedin()) {
	// user is already logged in, so they don't need to be here
	$session->redirect($config->urls->root); 
}

// check for login before outputting markup
if($input->post->user && $input->post->pass) {

	$user = $sanitizer->username($input->post->user);
	$pass = $input->post->pass; 

try{
    $u = $session->login($username, $pass);
    if($u && $u->id){
        $session->redirect("/somepage/");
    }
} catch(Exception $e) {
    echo $e->getMessage();
}

}

?>
<p><?php if($input->post->user) echo "<div class='alert alert-error'>Username and or Password is incorrect!</div>"; ?></p>

<form class="" action='./' method='post'>
	<label style="color:#fff;" for="user">Username</label>
	<input type="text" name="user" id="user" placeholder="Enter your username">
	<label  style="color:#fff;" for="pass">Password</label>
	<input type="password" name="pass" id="pass" placeholder="Enter your password">
	<label></label>
	<button type="submit" name="submit" class="btn btn-primary">Submit</button>
</form>
<p>Forgot password? <a href='/forgot-password'>Reset here.</a></p>
</div>
<div class="medium-4 columns">
<p> </p>
</div>
</div>








</div>





<?php include("./foot.inc"); 

 ?> 
Link to comment
Share on other sites

  • 4 weeks later...

In their profile page where they can edit their password. I allow users to post new pages and currently have them edit their own pages posted via fredi front end editor module. Any light on giving a user the ability to unpublish, publish or delete their posted page? Perhaps a check mark with a submit or simply a button that allows this. Basically how an admin would publish, unpublish or delete pages now only difference, its only the page a user is assigned to edit through the front end. Any help is appreciated.

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
  • Recently Browsing   0 members

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