Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/29/2012 in all areas

  1. 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>
    3 points
  2. First pw site... http://www.stokar.com/ composer's management agency. Processwire was great for this!; took on every challenge and request the client had with ease. Thanks to Ryan, and to everyone on the forum - it was an essential resource for working out all of the code to make this site work. -marc
    2 points
  3. First of all, Pete is completely right: translation/internationalization is hard. It's tedious, nobody likes to do it, it sucks. I think I already mentioned that I'm involved in another open source project, which has very few developers, so we have to rely on non-developer help. Most of that is done in the translation area. From that experience, I would recommend to make creating and maintaining translations as easy as possible, even for "normal" users. It will help spread PW even more if it is properly translated in as many languages as possible. Personally, I would be fine with the grep command. However, a lot of people have to work on servers or in small hosting plans which don't offer shell access. For those people, some kind of non-shell solution would be helpful. Doesn't have to be integrated in PW or the admin backend at all, it could as well be an extra PHP script or something. Just a solution to get the translatable files without shell access, maybe marking "new" translatable files, if that's possible. I have to agree that PW's internationalization already is pretty comfortable. I also think it's perfectly acceptable to have some parts which are not (yet) translated. In my opinion, you can not use most open source software without knowing at least some English. Seems impossible. But once PW starts to attract the "non-technical users" (which, as far as I can tell, it already is), there will be more people wanting to use it which barely understand English. Or not at all. Trust me, it will not keep them from wanting to use it anyway. You'll very soon get inquiries whether we could have a subforum in Spanish or something.
    2 points
  4. 2 points
  5. First of all, I push quite a number of new and revised translations to GitHub today. Haven't checked for new translations yet since I did those on a server without ssh access, which makes it hard to check for new translatable files. Second, I admit I only skimmed those screenshots, but I am pretty sure most of this stuff is properly translated in the standard admin theme. I never use anything else, so I can't really tell whether it's related to the admin theme. You should check with the standard admin theme. Also always consider that there still are quite a number of parts of PW which are not translatable at all.
    1 point
  6. Since they already have to be translated for the module file, it's unnecessary duplication. Though I'm not opposed to duplication if it makes things simpler/faster for everyone. But since this one is specific to dropdowns in this admin theme (something not in all admin themes), maybe it would be better for it to grab the translated module titles rather than the page titles. Basically like this: foreach($children as $p) { if($p->process) { $info = wire('modules')->getModuleInfo($p->process); $title = $info['title']; } else { $title = $p->title; } echo "<li><a href='{$p->url}'>$title</a></li>"; } The other advantage of this approach is that it works with any modules, not just ones that have been predefined in default.php.
    1 point
  7. The disadvantage with uniqid() is that its output is predictable since the value returned is based on the current timestamp. So on the surface, it seems there's possibility for that to be exploited, although it might be challenging. The password generation I put in the example above is based all around random characters, which aren't predictable other than the set which they come from (a-z2-9) and the length (between 9 and 12). I think this is pretty strong. However, the security of it could be increased by adding more to the set of possible characters (punctuation, upper/lower, etc.) and increasing the possible length range, like up to 30 characters or something. I opted to limit the character set and exclude the letters that are easily confused with each other, like "o O 0" and "i I l 1", just in case people are hand-typing (rather than copy/pasting)… less support burden. Another thing I might add to the code would be to make it only work with users of a certain role. But that would be pretty site-specific, so left it out here.
    1 point
  8. I think for those menu subentries it would be easier to include them in the theme default.php, same like the top menu entries. So they can be translated from the same translation file for default.php. /* * Dynamic phrases that we want to be automatically translated * * These are in a comment so that they register with the parser, in place of the dynamic __() function calls with page titles. * * __("Pages"); * __("Setup"); * __("Modules"); * __("Access"); * __("Admin"); * Standard Submenus * __("Fields"); * __("Templates"); * __("Languages"); * __("Users"); * __("Roles"); * __("Permissions"); * */
    1 point
  9. I think that it would be fine to do it with PW pages, and have been played around with doing it that way myself (and may pursue it further in the future). But Pete is right that since comments are a fixed format, and potentially more vast than your site's content, it's more efficient for them to be in their own tables, separate from PW's pages. And that's the reason why PW's comments are their own thing, rather than pages. However, I think there are plenty of benefits to having them as pages too, but it is a bit of a compromise in efficiency for flexibility. And perhaps a worthwhile one. I'd say go for it. But ideally don't have any crossover with the fields you use for comments, and the fields you use on the rest of your site. That will ensure that the quantity/scale of the fields used by comments doesn't introduce any potential bottlenecks in your site's pages.
    1 point
  10. ...and among a million other reasons, it's responses like this that make Processwire incredible. There's a lot in there I can learn from. Thanks for sharing.
    1 point
  11. PW's database is really scalable in that each field is a table. This is fine, but for comments systems and other cases where you're only going to build the structure ONCE and scale it to millions of entries it can be preferable to have it in its own table. For example, if you build it as PW pages to only have 3 fields - name, email and comment, that's 3 tables (but remember there are other tables that come into play! - the pages table and the field_title table have to be in there for each page!). Sure, it's quick enough since it's still the one query that's getting data from those tables, but it would save some overhead when you get to really large numbers of comments to have it as one table. In fact I doubt the overhead would even be very high with separate tables doing it all as PW pages, so maybe ryan can elaborate on possible reasons to keep it separate.
    1 point
  12. Gravatar support would be cool. I think I've seen it done somewhere else that it links to Gravatar based on the email address and defaults to a pre-set list of icons otherwise so you're not looking at the same boring silhouette or "no avatar" text. Something like that would be as simple as adding a default avatars folder and picking one at random and could make it a bit fun. To see what I mean, scroll to the comments here and you'll see a bunch of stand-in cartoon avatars for those without one: http://www.rockpapershotgun.com/2012/08/28/rome-sweet-rome-crusader-kings-ii-expands/ Maybe not a necessary feature, but certainly an easy thing to code to make it as easy as dropping some images into a "default-avatars" folder to have it select one. If I had to guess, I think it might select those from the site above based on the square root of the member ID rounded to the nearest whole number or something like that, since they are the same for each person every time you load the page. Anyway, I've babbled on about that point enough. Spam protection - stopforumspam.com would be a good option if it's not in already, but there are others as well. The obvious issue is the more that you check against the longer it takes to query. Maybe when PW is a lot more mainstream it could even go down the route of a PW-run central anti-spam database like these forums have (run by IPB and spammers marked as spammers by site owners). Of course that requires manpower that's not available at present and the database would be very empty to begin with To prevent double post even without a redirect could a unique ID just not be sent with the form submission? I guess like on the forums you might want to say something in addition to what you just posted so it would be good to check if the content of the new post is the same as the old post and if not then append it to the previous post. I don't mean post, I mean comment Textformatter plugins - are we talking about support for Markdown and the new BBCode one you've done? That would be fab. I think that's all my thoughts for now. Brain tired, sleep imminent. Oh wait, it's only 1.45pm
    1 point
  13. Hi, I did this one for design agency Ant Design in my "coding-for-other-designers" role: http://aotr.com.au/ Regards Marty
    1 point
  14. 1 point
  15. Ok, I got a little time and did it myself Please go there and change it as you wish. http://toolbe.lt/Processwire
    1 point
×
×
  • Create New...