Allow resetting password through email.
This also adopts the use of an Alert template for error and success messages.
This commit is contained in:
parent
3587447cc0
commit
7487068171
3
TODO.md
3
TODO.md
@ -1,10 +1,9 @@
|
|||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
* Draaiing van foto's bij importeren goedzetten
|
* Draaiing van foto's bij importeren goedzetten
|
||||||
* Import asset ownership
|
|
||||||
* Import users
|
* Import users
|
||||||
|
* Import asset ownership
|
||||||
* Pagina om één foto te bekijken
|
* Pagina om één foto te bekijken
|
||||||
* Taggen door gebruikers
|
* Taggen door gebruikers
|
||||||
* Uploaden door gebruikers
|
* Uploaden door gebruikers
|
||||||
* Album management
|
* Album management
|
||||||
* Password reset via e-mail
|
|
||||||
|
@ -29,9 +29,12 @@ class Login extends HTMLController
|
|||||||
if (isset($_POST['redirect_url']))
|
if (isset($_POST['redirect_url']))
|
||||||
header('Location: ' . base64_decode($_POST['redirect_url']));
|
header('Location: ' . base64_decode($_POST['redirect_url']));
|
||||||
elseif (isset($_SESSION['login_url']))
|
elseif (isset($_SESSION['login_url']))
|
||||||
|
{
|
||||||
|
unset($_SESSION['redirect_url']);
|
||||||
header('Location: ' . $_SESSION['redirect_url']);
|
header('Location: ' . $_SESSION['redirect_url']);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
header('Location: ' . BASEURL . '/admin/');
|
header('Location: ' . BASEURL . '/');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -39,15 +42,28 @@ class Login extends HTMLController
|
|||||||
}
|
}
|
||||||
|
|
||||||
parent::__construct('Log in - ' . SITE_TITLE);
|
parent::__construct('Log in - ' . SITE_TITLE);
|
||||||
$this->page->appendStylesheet(BASEURL . '/css/admin.css');
|
|
||||||
$form = new LogInForm('Log in');
|
$form = new LogInForm('Log in');
|
||||||
if ($login_error)
|
if ($login_error)
|
||||||
$form->setErrorMessage('Invalid email address or password.');
|
$form->adopt(new Alert('', 'Invalid email address or password.', 'error'));
|
||||||
|
|
||||||
// Tried anything? Be helpful, at least.
|
// Tried anything? Be helpful, at least.
|
||||||
if (isset($_POST['emailaddress']))
|
if (isset($_POST['emailaddress']))
|
||||||
$form->setEmail($_POST['emailaddress']);
|
$form->setEmail($_POST['emailaddress']);
|
||||||
|
|
||||||
|
// A message from the past/present/future?
|
||||||
|
if (isset($_SESSION['login_msg']))
|
||||||
|
{
|
||||||
|
$form->adopt(new Alert($_SESSION['login_msg'][0], $_SESSION['login_msg'][1], $_SESSION['login_msg'][2]));
|
||||||
|
unset($_SESSION['login_msg']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Going somewhere?
|
||||||
|
if (!empty($_GET['redirect']) && ($url = base64_decode($_GET['redirect'])))
|
||||||
|
{
|
||||||
|
$_SESSION['login_url'] = $url;
|
||||||
|
$form->setRedirectUrl($url);
|
||||||
|
}
|
||||||
|
|
||||||
$this->page->adopt($form);
|
$this->page->adopt($form);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
81
controllers/ResetPassword.php
Normal file
81
controllers/ResetPassword.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
/*****************************************************************************
|
||||||
|
* ResetPassword.php
|
||||||
|
* Contains the controller for the reset password procedure.
|
||||||
|
*
|
||||||
|
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
class ResetPassword extends HTMLController
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Already logged in? Then you don't need this.
|
||||||
|
if (Registry::get('user')->isLoggedIn())
|
||||||
|
throw new UserFacingException('You are already logged in.');
|
||||||
|
|
||||||
|
// Verifying an existing reset key?
|
||||||
|
if (isset($_GET['step'], $_GET['email'], $_GET['key']) && $_GET['step'] == 2)
|
||||||
|
{
|
||||||
|
$email = rawurldecode($_GET['email']);
|
||||||
|
$id_user = Authentication::getUserid($email);
|
||||||
|
if ($id_user === false)
|
||||||
|
throw new UserFacingException('Invalid email address. Please make sure you copied the full link in the email you received.');
|
||||||
|
|
||||||
|
$key = $_GET['key'];
|
||||||
|
if (!Authentication::checkResetKey($id_user, $key))
|
||||||
|
throw new UserFacingException('Invalid reset token. Please make sure you copied the full link in the email you received. Note: you cannot use the same token twice.');
|
||||||
|
|
||||||
|
parent::__construct('Reset password - ' . SITE_TITLE);
|
||||||
|
$form = new PasswordResetForm($email, $key);
|
||||||
|
$this->page->adopt($form);
|
||||||
|
|
||||||
|
// Are they trying to set something already?
|
||||||
|
if (isset($_POST['password1'], $_POST['password2']))
|
||||||
|
{
|
||||||
|
$missing = [];
|
||||||
|
if (strlen($_POST['password1']) < 6 || !preg_match('~[^A-z]~', $_POST['password1']))
|
||||||
|
$missing[] = 'Please fill in a password that is at least six characters long and contains at least one non-alphabetic character (e.g. a number or symbol).';
|
||||||
|
if ($_POST['password1'] != $_POST['password2'])
|
||||||
|
$missing[] = 'The passwords you entered do not match.';
|
||||||
|
|
||||||
|
// So, are we good to go?
|
||||||
|
if (empty($missing))
|
||||||
|
{
|
||||||
|
Authentication::updatePassword($id_user, Authentication::computeHash($_POST['password1']));
|
||||||
|
$_SESSION['login_msg'] = ['Your password has been reset', 'You can now use the form below to log in to your account.', 'success'];
|
||||||
|
header('Location: ' . BASEURL . '/login/');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$form->adopt(new Alert('Some fields require your attention', '<ul><li>' . implode('</li><li>', $missing) . '</li></ul>', 'error'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent::__construct('Reset password - ' . SITE_TITLE);
|
||||||
|
$form = new ForgotPasswordForm();
|
||||||
|
$this->page->adopt($form);
|
||||||
|
|
||||||
|
// Have they submitted an email address yet?
|
||||||
|
if (isset($_POST['emailaddress']) && preg_match('~^.+@.+\.[a-z]+$~', trim($_POST['emailaddress'])))
|
||||||
|
{
|
||||||
|
$id_user = Authentication::getUserid(trim($_POST['emailaddress']));
|
||||||
|
if ($id_user === false)
|
||||||
|
{
|
||||||
|
$form->adopt(new Alert('Invalid email address', 'The email address you provided could not be found in our system. Please try again.', 'error'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Authentication::setResetKey($id_user);
|
||||||
|
Email::resetMail($id_user);
|
||||||
|
|
||||||
|
// Show the success message
|
||||||
|
$this->page->clear();
|
||||||
|
$box = new DummyBox('An email has been sent');
|
||||||
|
$box->adopt(new Alert('', 'We have sent an email to ' . $_POST['emailaddress'] . ' containing details on how to reset your password.', 'success'));
|
||||||
|
$this->page->adopt($box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,31 @@ class Authentication
|
|||||||
return empty($res) ? false : $res;
|
return empty($res) ? false : $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function setResetKey($id_user)
|
||||||
|
{
|
||||||
|
return Registry::get('db')->query('
|
||||||
|
UPDATE users
|
||||||
|
SET reset_key = {string:key}
|
||||||
|
WHERE id_user = {int:id}',
|
||||||
|
[
|
||||||
|
'id' => $id_user,
|
||||||
|
'key' => self::newActivationKey(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function checkResetKey($id_user, $reset_key)
|
||||||
|
{
|
||||||
|
$key = Registry::get('db')->queryValue('
|
||||||
|
SELECT reset_key
|
||||||
|
FROM users
|
||||||
|
WHERE id_user = {int:id}',
|
||||||
|
[
|
||||||
|
'id' => $id_user,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $key == $reset_key;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies whether the user is currently logged in.
|
* Verifies whether the user is currently logged in.
|
||||||
*/
|
*/
|
||||||
@ -62,6 +87,18 @@ class Authentication
|
|||||||
return isset($_SESSION['user_id']) && self::checkExists($_SESSION['user_id']);
|
return isset($_SESSION['user_id']) && self::checkExists($_SESSION['user_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a new activation key.
|
||||||
|
*/
|
||||||
|
public static function newActivationKey()
|
||||||
|
{
|
||||||
|
$alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
$string = '';
|
||||||
|
for ($i = 0; $i < 16; $i++)
|
||||||
|
$string .= $alpha[mt_rand(0, strlen($alpha) - 1)];
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks a password for a given username against the database.
|
* Checks a password for a given username against the database.
|
||||||
*/
|
*/
|
||||||
|
@ -21,6 +21,7 @@ class Dispatcher
|
|||||||
'managetags' => 'ManageTags',
|
'managetags' => 'ManageTags',
|
||||||
'manageusers' => 'ManageUsers',
|
'manageusers' => 'ManageUsers',
|
||||||
'people' => 'ViewPeople',
|
'people' => 'ViewPeople',
|
||||||
|
'resetpassword' => 'ResetPassword',
|
||||||
'suggest' => 'ProvideAutoSuggest',
|
'suggest' => 'ProvideAutoSuggest',
|
||||||
'timeline' => 'ViewTimeline',
|
'timeline' => 'ViewTimeline',
|
||||||
'uploadmedia' => 'UploadMedia',
|
'uploadmedia' => 'UploadMedia',
|
||||||
@ -77,6 +78,11 @@ class Dispatcher
|
|||||||
else
|
else
|
||||||
self::trigger403();
|
self::trigger403();
|
||||||
}
|
}
|
||||||
|
catch (UserFacingException $e)
|
||||||
|
{
|
||||||
|
$debug_info = ErrorHandler::getDebugInfo($e->getTrace());
|
||||||
|
ErrorHandler::display($e->getMessage(), $debug_info, false);
|
||||||
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
ErrorHandler::handleError(E_USER_ERROR, 'Unspecified exception: ' . $e->getMessage(), $e->getFile(), $e->getLine());
|
ErrorHandler::handleError(E_USER_ERROR, 'Unspecified exception: ' . $e->getMessage(), $e->getFile(), $e->getLine());
|
||||||
@ -93,7 +99,7 @@ class Dispatcher
|
|||||||
public static function kickGuest()
|
public static function kickGuest()
|
||||||
{
|
{
|
||||||
$form = new LogInForm('Log in');
|
$form = new LogInForm('Log in');
|
||||||
$form->setErrorMessage('Admin access required. Please log in.');
|
$form->adopt(new Alert('', 'You need to be logged in to view this page.', 'error'));
|
||||||
$form->setRedirectUrl($_SERVER['REQUEST_URI']);
|
$form->setRedirectUrl($_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
$page = new MainTemplate('Login required');
|
$page = new MainTemplate('Login required');
|
||||||
|
100
models/Email.php
Normal file
100
models/Email.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
/*****************************************************************************
|
||||||
|
* Email.php
|
||||||
|
* Contains key class Email.
|
||||||
|
*
|
||||||
|
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
class Email
|
||||||
|
{
|
||||||
|
public static function send($address, $addressee, $subject, $body, $headers = '')
|
||||||
|
{
|
||||||
|
// Set a boundary.
|
||||||
|
$boundary = uniqid('sr');
|
||||||
|
|
||||||
|
if (empty($headers))
|
||||||
|
$headers .= "From: HashRU Pics <no-reply@pics.hashru.nl>\r\n";
|
||||||
|
|
||||||
|
// Set up headers.
|
||||||
|
$headers .= "MIME-Version: 1.0\r\n";
|
||||||
|
$headers .= "Content-Type: multipart/alternative;boundary=$boundary\r\n";
|
||||||
|
|
||||||
|
// Start the message with a plaintext version of the mail.
|
||||||
|
$message = "This is a MIME encoded message.";
|
||||||
|
$message .= "\r\n\r\n--$boundary\r\n";
|
||||||
|
$message .= "Content-type: text/plain;charset=utf-8\r\n\r\n";
|
||||||
|
$message .= self::wrapLines($body);
|
||||||
|
|
||||||
|
// Autolink URLs and wrap lines.
|
||||||
|
$html_body = preg_replace('~\b(?!")https?://[^"\s]+~', '<a href="$0">$0</a>', $body);
|
||||||
|
$html_body = preg_replace('~(\s+)(www\..+\.[^"\s]+?)(\.|\s+)~', '$1<a href="https://$2">$2</a>$3', $html_body);
|
||||||
|
$html_body = preg_replace('~={10,}~', '<hr>', $html_body);
|
||||||
|
$html_body = self::wrapLines(str_replace("\r", "<br>\r", $html_body), 80, "\r\n");
|
||||||
|
|
||||||
|
// Then, more excitingly, add an HTML version!
|
||||||
|
$message .= "\r\n\r\n--" . $boundary . "\r\n";
|
||||||
|
$message .= "Content-type: text/html;charset=utf-8\r\n\r\n";
|
||||||
|
$message .= "<html>\r\n<head><style type=\"text/css\">\r\nbody { font: 13px Helvetica, Arial, sans-serif; }\r\n</style></head>\r\n<body><p>" .
|
||||||
|
$html_body . "</p></body>\r\n</html>";
|
||||||
|
|
||||||
|
// End off with a final boundary.
|
||||||
|
$message .= "\r\n\r\n--" . $boundary . "--";
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
return file_put_contents(BASEDIR . '/mail_dumps.txt', "To: \"$addressee\" <$address>\r\n$headers\r\nSubject: $subject\r\n" . self::wrapLines($message), FILE_APPEND);
|
||||||
|
else
|
||||||
|
return mail("\"$addressee\" <$address>", $subject, $message, $headers, '-fbounces@pics.hashru.nl');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function wrapLines($body, $maxlength = 80, $break = "\r\n")
|
||||||
|
{
|
||||||
|
$lines = explode("\n", $body);
|
||||||
|
$wrapped = "";
|
||||||
|
foreach ($lines as $line)
|
||||||
|
$wrapped .= wordwrap($line, $maxlength, $break) . $break;
|
||||||
|
return $wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function parseTemplate($template, $replacements)
|
||||||
|
{
|
||||||
|
$replacement_keys = array_map(function($el) { return "%$el%"; }, array_keys($replacements));
|
||||||
|
$subject = str_replace($replacement_keys, array_values($replacements), $template['subject']);
|
||||||
|
$body = str_replace($replacement_keys, array_values($replacements), $template['body']);
|
||||||
|
return [$subject, $body];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function resetMail($id_user)
|
||||||
|
{
|
||||||
|
$row = Registry::get('db')->queryAssoc('
|
||||||
|
SELECT first_name, surname, emailaddress, reset_key
|
||||||
|
FROM users
|
||||||
|
WHERE id_user = {int:id_user}',
|
||||||
|
[
|
||||||
|
'id_user' => $id_user,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (empty($row))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
list($subject, $body) = self::parseTemplate([
|
||||||
|
'subject' => 'Information on how to reset your HashRU password',
|
||||||
|
'body' => str_replace("\n", "\r\n", 'Dear %FIRST_NAME%,
|
||||||
|
|
||||||
|
You are receiving this email because a password reset request was issued on our website.
|
||||||
|
|
||||||
|
If you did not request a password reset, please disregard this email. Otherwise, please follow the link below.
|
||||||
|
|
||||||
|
%RESET_LINK%
|
||||||
|
|
||||||
|
The HashRU Pics team'),
|
||||||
|
], [
|
||||||
|
'FIRST_NAME' => $row['first_name'],
|
||||||
|
'RESET_LINK' => BASEURL . '/resetpassword/?step=2&email=' . rawurlencode($row['emailaddress']) . '&key=' . $row['reset_key'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$addressee = trim($row['first_name'] . ' ' . $row['surname']);
|
||||||
|
self::send($row['emailaddress'], $addressee, $subject, $body);
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
* ErrorHandler.php
|
* ErrorHandler.php
|
||||||
* Contains key class ErrorHandler.
|
* Contains key class ErrorHandler.
|
||||||
*
|
*
|
||||||
* Kabuki CMS (C) 2013-2015, Aaron van Geffen
|
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
class ErrorHandler
|
class ErrorHandler
|
||||||
@ -11,6 +11,18 @@ class ErrorHandler
|
|||||||
private static $error_count = 0;
|
private static $error_count = 0;
|
||||||
private static $handling_error;
|
private static $handling_error;
|
||||||
|
|
||||||
|
public static function enable()
|
||||||
|
{
|
||||||
|
set_error_handler('ErrorHandler::handleError');
|
||||||
|
ini_set("display_errors", DEBUG ? "On" : "Off");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function disable()
|
||||||
|
{
|
||||||
|
set_error_handler(NULL);
|
||||||
|
ini_set("display_errors", "Off");
|
||||||
|
}
|
||||||
|
|
||||||
// Handler for standard PHP error messages.
|
// Handler for standard PHP error messages.
|
||||||
public static function handleError($error_level, $error_message, $file, $line, $context = null)
|
public static function handleError($error_level, $error_message, $file, $line, $context = null)
|
||||||
{
|
{
|
||||||
@ -121,14 +133,27 @@ class ErrorHandler
|
|||||||
return $error_message;
|
return $error_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function display($message, $debug_info)
|
public static function display($message, $debug_info, $is_sensitive = true)
|
||||||
{
|
{
|
||||||
|
$is_admin = Registry::has('user') && Registry::get('user')->isAdmin();
|
||||||
|
|
||||||
// Just show the message if we're running in a console.
|
// Just show the message if we're running in a console.
|
||||||
if (empty($_SERVER['HTTP_HOST']))
|
if (empty($_SERVER['HTTP_HOST']))
|
||||||
{
|
{
|
||||||
echo $message;
|
echo $message;
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
// JSON request?
|
||||||
|
elseif (isset($_GET['json']) || isset($_GET['format']) && $_GET['format'] == 'json')
|
||||||
|
{
|
||||||
|
if (DEBUG || $is_admin)
|
||||||
|
echo json_encode(['error' => $message . "\n\n" . $debug_info]);
|
||||||
|
elseif (!$is_sensitive)
|
||||||
|
echo json_encode(['error' => $message]);
|
||||||
|
else
|
||||||
|
echo json_encode(['error' => 'Our apologies, an error occured while we were processing your request. Please try again later, or contact us if the problem persists.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialise the main template to present a nice message to the user.
|
// Initialise the main template to present a nice message to the user.
|
||||||
$page = new MainTemplate('An error occured!');
|
$page = new MainTemplate('An error occured!');
|
||||||
@ -146,6 +171,8 @@ class ErrorHandler
|
|||||||
$page->adopt(new AdminBar());
|
$page->adopt(new AdminBar());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elseif (!$is_sensitive)
|
||||||
|
$page->adopt(new DummyBox('An error occured!', '<p>' . $message . '</p>'));
|
||||||
else
|
else
|
||||||
$page->adopt(new DummyBox('An error occured!', '<p>Our apologies, an error occured while we were processing your request. Please try again later, or contact us if the problem persists.</p>'));
|
$page->adopt(new DummyBox('An error occured!', '<p>Our apologies, an error occured while we were processing your request. Please try again later, or contact us if the problem persists.</p>'));
|
||||||
|
|
||||||
|
12
models/UserFacingException.php
Normal file
12
models/UserFacingException.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
/*****************************************************************************
|
||||||
|
* UserFacingException.php
|
||||||
|
* Contains exception class UserFacingException.
|
||||||
|
*
|
||||||
|
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
class UserFacingException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -395,6 +395,70 @@ textarea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Alert boxes -- styling borrowed from Bootstrap 2
|
||||||
|
-----------------------------------------------------*/
|
||||||
|
.alert {
|
||||||
|
padding: 8px 35px 8px 14px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||||
|
background-color: #fcf8e3;
|
||||||
|
border: 1px solid #fbeed5;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.alert,
|
||||||
|
.alert h4 {
|
||||||
|
color: #c09853;
|
||||||
|
}
|
||||||
|
.alert h4 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.alert .close {
|
||||||
|
position: relative;
|
||||||
|
top: -2px;
|
||||||
|
right: -21px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.alert-success {
|
||||||
|
background-color: #dff0d8;
|
||||||
|
border-color: #d6e9c6;
|
||||||
|
color: #468847;
|
||||||
|
}
|
||||||
|
.alert-success h4 {
|
||||||
|
color: #468847;
|
||||||
|
}
|
||||||
|
.alert-danger,
|
||||||
|
.alert-error {
|
||||||
|
background-color: #f2dede;
|
||||||
|
border-color: #eed3d7;
|
||||||
|
color: #b94a48;
|
||||||
|
}
|
||||||
|
.alert-danger h4,
|
||||||
|
.alert-error h4 {
|
||||||
|
color: #b94a48;
|
||||||
|
}
|
||||||
|
.alert-info {
|
||||||
|
background-color: #d9edf7;
|
||||||
|
border-color: #bce8f1;
|
||||||
|
color: #3a87ad;
|
||||||
|
}
|
||||||
|
.alert-info h4 {
|
||||||
|
color: #3a87ad;
|
||||||
|
}
|
||||||
|
.alert-block {
|
||||||
|
padding-top: 14px;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
}
|
||||||
|
.alert-block > p,
|
||||||
|
.alert-block > ul {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.alert-block p + p {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Responsive: smartphone in portrait
|
/* Responsive: smartphone in portrait
|
||||||
---------------------------------------*/
|
---------------------------------------*/
|
||||||
@media only screen and (max-width: 895px) {
|
@media only screen and (max-width: 895px) {
|
||||||
|
24
templates/Alert.php
Normal file
24
templates/Alert.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
/*****************************************************************************
|
||||||
|
* Alert.php
|
||||||
|
* Defines the key template Alert.
|
||||||
|
*
|
||||||
|
* Kabuki CMS (C) 2013-2015, Aaron van Geffen
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
class Alert extends SubTemplate
|
||||||
|
{
|
||||||
|
public function __construct($title = '', $message = '', $type = 'alert')
|
||||||
|
{
|
||||||
|
$this->_title = $title;
|
||||||
|
$this->_message = $message;
|
||||||
|
$this->_type = in_array($type, ['alert', 'error', 'success', 'info']) ? $type : 'alert';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function html_content()
|
||||||
|
{
|
||||||
|
echo '
|
||||||
|
<div class="alert', $this->_type != 'alert' ? ' alert-' . $this->_type : '', '">', (!empty($this->_title) ? '
|
||||||
|
<strong>' . $this->_title . '</strong><br>' : ''), $this->_message, '</div>';
|
||||||
|
}
|
||||||
|
}
|
29
templates/ForgotPasswordForm.php
Normal file
29
templates/ForgotPasswordForm.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
/*****************************************************************************
|
||||||
|
* ForgotPasswordForm.php
|
||||||
|
* Contains the forget password form template.
|
||||||
|
*
|
||||||
|
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
class ForgotPasswordForm extends SubTemplate
|
||||||
|
{
|
||||||
|
protected function html_content()
|
||||||
|
{
|
||||||
|
echo '
|
||||||
|
<div class="boxed_content">
|
||||||
|
<h2>Password reset procedure</h2>';
|
||||||
|
|
||||||
|
foreach ($this->_subtemplates as $template)
|
||||||
|
$template->html_main();
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<p>Please fill in the email address you used to sign up in the form below. You will be sent a reset link to your email address.</p>
|
||||||
|
<form class="form-horizontal" action="', BASEURL, '/resetpassword/?step=1" method="post">
|
||||||
|
<label class="control-label" for="field_emailaddress">E-mail address:</label><br>
|
||||||
|
<input type="text" id="field_emailaddress" name="emailaddress">
|
||||||
|
<button type="submit" class="btn btn-primary">Send mail</button>
|
||||||
|
</form>
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
}
|
@ -8,15 +8,9 @@
|
|||||||
|
|
||||||
class LogInForm extends SubTemplate
|
class LogInForm extends SubTemplate
|
||||||
{
|
{
|
||||||
private $error_message = '';
|
|
||||||
private $redirect_url = '';
|
private $redirect_url = '';
|
||||||
private $emailaddress = '';
|
private $emailaddress = '';
|
||||||
|
|
||||||
public function setErrorMessage($message)
|
|
||||||
{
|
|
||||||
$this->error_message = $message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRedirectUrl($url)
|
public function setRedirectUrl($url)
|
||||||
{
|
{
|
||||||
$_SESSION['login_url'] = $url;
|
$_SESSION['login_url'] = $url;
|
||||||
@ -32,12 +26,10 @@ class LogInForm extends SubTemplate
|
|||||||
{
|
{
|
||||||
echo '
|
echo '
|
||||||
<form action="', BASEURL, '/login/" method="post" id="login">
|
<form action="', BASEURL, '/login/" method="post" id="login">
|
||||||
<h3>Admin login</h3>';
|
<h3>Log in</h3>';
|
||||||
|
|
||||||
// Invalid login? Show a message.
|
foreach ($this->_subtemplates as $template)
|
||||||
if (!empty($this->error_message))
|
$template->html_main();
|
||||||
echo '
|
|
||||||
<p style="color: red">', $this->error_message, '</p>';
|
|
||||||
|
|
||||||
echo '
|
echo '
|
||||||
<dl>
|
<dl>
|
||||||
@ -54,7 +46,10 @@ class LogInForm extends SubTemplate
|
|||||||
<input type="hidden" name="redirect_url" value="', base64_encode($this->redirect_url), '">';
|
<input type="hidden" name="redirect_url" value="', base64_encode($this->redirect_url), '">';
|
||||||
|
|
||||||
echo '
|
echo '
|
||||||
<div><button type="submit" class="btn btn-primary" id="field_login" name="login" tabindex="3">Log in</button></div>
|
<a href="', BASEURL, '/resetpassword/">Forgotten your password?</a>
|
||||||
|
<div class="buttonstrip">
|
||||||
|
<button type="submit" class="btn btn-primary" id="field_login" name="login" tabindex="3">Log in</button>
|
||||||
|
</div>
|
||||||
</form>';
|
</form>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
templates/PasswordResetForm.php
Normal file
46
templates/PasswordResetForm.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
/*****************************************************************************
|
||||||
|
* PasswordResetForm.php
|
||||||
|
* Contains the password reset form template.
|
||||||
|
*
|
||||||
|
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
class PasswordResetForm extends SubTemplate
|
||||||
|
{
|
||||||
|
private $email;
|
||||||
|
private $key;
|
||||||
|
|
||||||
|
public function __construct($email, $key)
|
||||||
|
{
|
||||||
|
$this->email = $email;
|
||||||
|
$this->key = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function html_content()
|
||||||
|
{
|
||||||
|
echo '
|
||||||
|
<div class="boxed_content">
|
||||||
|
<h2>Password reset procedure</h2>';
|
||||||
|
|
||||||
|
foreach ($this->_subtemplates as $template)
|
||||||
|
$template->html_main();
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<p>You have successfully confirmed your identify. Please use the form below to set a new password.</p>
|
||||||
|
<form class="form-horizontal" action="', BASEURL, '/resetpassword/?step=2&email=', rawurlencode($this->email), '&key=', $this->key, '" method="post">
|
||||||
|
<p>
|
||||||
|
<label class="control-label" for="field_password1">New password:</label>
|
||||||
|
<input type="password" id="field_password1" name="password1">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label class="control-label" for="field_password2">Repeat new password:</label>
|
||||||
|
<input type="password" id="field_password2" name="password2">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">Reset password</button>
|
||||||
|
</form>
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user