Preparation for #62

This commit is contained in:
Marcin Kurczewski 2013-11-16 16:24:38 +01:00
parent 9ec269330c
commit fb02feeed3
2 changed files with 120 additions and 28 deletions

View file

@ -1,27 +1,36 @@
<?php <?php
class UserController class UserController
{ {
private static function sendEmailConfirmation(&$user) private static function sendTokenizedEmail(
$user,
$body,
$subject,
$senderName,
$senderEmail,
$recipientEmail,
$tokens)
{ {
$regConfig = \Chibi\Registry::getConfig()->registration; //prepare unique user token
do
if (!$regConfig->confirmationEmailEnabled)
{ {
$user->email_confirmed = $user->email_unconfirmed; $tokenText = md5(mt_rand() . uniqid());
$user->email_unconfirmed = null;
return;
} }
while (R::findOne('usertoken', 'token = ?', [$tokenText]) !== null);
$token = R::dispense('usertoken');
$token->user = $user;
$token->token = $tokenText;
$token->used = false;
$token->expires = null;
R::store($token);
\Chibi\Registry::getContext()->mailSent = true; \Chibi\Registry::getContext()->mailSent = true;
$tokens = [];
$tokens['host'] = $_SERVER['HTTP_HOST']; $tokens['host'] = $_SERVER['HTTP_HOST'];
$tokens['link'] = \Chibi\UrlHelper::route('user', 'activation', ['token' => $user->email_token]); $tokens['token'] = $tokenText;
$body = wordwrap(TextHelper::replaceTokens($regConfig->confirmationEmailBody, $tokens), 70); $body = wordwrap(TextHelper::replaceTokens($body, $tokens), 70);
$subject = TextHelper::replaceTokens($regConfig->confirmationEmailSubject, $tokens); $subject = TextHelper::replaceTokens($subject, $tokens);
$senderName = TextHelper::replaceTokens($regConfig->confirmationEmailSenderName, $tokens); $senderName = TextHelper::replaceTokens($senderName, $tokens);
$senderEmail = TextHelper::replaceTokens($regConfig->confirmationEmailSenderEmail, $tokens); $senderEmail = TextHelper::replaceTokens($senderEmail, $tokens);
$recipientEmail = $user->email_unconfirmed;
$headers = []; $headers = [];
$headers []= sprintf('MIME-Version: 1.0'); $headers []= sprintf('MIME-Version: 1.0');
@ -39,6 +48,29 @@ class UserController
mail($recipientEmail, $subject, $body, implode("\r\n", $headers), '-f' . $senderEmail); mail($recipientEmail, $subject, $body, implode("\r\n", $headers), '-f' . $senderEmail);
} }
private static function sendEmailChangeConfirmation($user)
{
$regConfig = \Chibi\Registry::getConfig()->registration;
if (!$regConfig->confirmationEmailEnabled)
{
$user->email_confirmed = $user->email_unconfirmed;
$user->email_unconfirmed = null;
return;
}
$tokens = [];
$tokens['link'] = \Chibi\UrlHelper::route('user', 'activation', ['token' => '{token}']);
return self::sendTokenizedEmail(
$user,
$regConfig->confirmationEmailBody,
$regConfig->confirmationEmailSubject,
$regConfig->confirmationEmailSenderName,
$regConfig->confirmationEmailSenderEmail,
$user->email_unconfirmed,
$tokens);
}
/** /**
@ -250,6 +282,8 @@ class UserController
if (InputHelper::get('submit')) if (InputHelper::get('submit'))
{ {
$confirmMail = false;
if ($suppliedName != '' and $suppliedName != $user->name) if ($suppliedName != '' and $suppliedName != $user->name)
{ {
PrivilegesHelper::confirmWithException(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($user)); PrivilegesHelper::confirmWithException(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($user));
@ -274,7 +308,7 @@ class UserController
{ {
$user->email_unconfirmed = $suppliedEmail; $user->email_unconfirmed = $suppliedEmail;
if (!empty($user->email_unconfirmed)) if (!empty($user->email_unconfirmed))
self::sendEmailConfirmation($user); $confirmMail = true;
} }
else else
{ {
@ -296,6 +330,10 @@ class UserController
throw new SimpleException('Must supply valid current password'); throw new SimpleException('Must supply valid current password');
} }
R::store($user); R::store($user);
if ($confirmMail)
self::sendEmailChangeConfirmation($user);
$this->context->transport->success = true; $this->context->transport->success = true;
} }
} }
@ -425,17 +463,10 @@ class UserController
$dbUser->pass_hash = Model_User::hashPassword($suppliedPassword, $dbUser->pass_salt); $dbUser->pass_hash = Model_User::hashPassword($suppliedPassword, $dbUser->pass_salt);
$dbUser->email_unconfirmed = $suppliedEmail; $dbUser->email_unconfirmed = $suppliedEmail;
//prepare unique registration token
do
{
$emailToken = md5(mt_rand() . uniqid());
}
while (R::findOne('user', 'email_token = ?', [$emailToken]) !== null);
$dbUser->email_token = $emailToken;
$dbUser->join_date = time(); $dbUser->join_date = time();
if (R::findOne('user') === null) if (R::findOne('user') === null)
{ {
//very first user
$dbUser->access_rank = AccessRank::Admin; $dbUser->access_rank = AccessRank::Admin;
$dbUser->staff_confirmed = true; $dbUser->staff_confirmed = true;
$dbUser->email_unconfirmed = null; $dbUser->email_unconfirmed = null;
@ -446,12 +477,14 @@ class UserController
$dbUser->access_rank = AccessRank::Registered; $dbUser->access_rank = AccessRank::Registered;
$dbUser->staff_confirmed = false; $dbUser->staff_confirmed = false;
$dbUser->staff_confirmed = null; $dbUser->staff_confirmed = null;
if (!empty($dbUser->email_unconfirmed))
self::sendEmailConfirmation($dbUser);
} }
//save the user to db if everything went okay //save the user to db if everything went okay
R::store($dbUser); R::store($dbUser);
if (!empty($dbUser->email_unconfirmed))
self::sendEmailChangeConfirmation($dbUser);
$this->context->transport->success = true; $this->context->transport->success = true;
if (!$this->config->registration->needEmailForRegistering and !$this->config->registration->staffActivation) if (!$this->config->registration->needEmailForRegistering and !$this->config->registration->staffActivation)
@ -474,15 +507,21 @@ class UserController
if (empty($token)) if (empty($token))
throw new SimpleException('Invalid activation token'); throw new SimpleException('Invalid activation token');
$dbUser = R::findOne('user', 'email_token = ?', [$token]); $dbToken = R::findOne('usertoken', 'token = ?', [$token]);
if ($dbUser === null) if ($dbToken === null)
throw new SimpleException('No user with such activation token'); throw new SimpleException('No user with such activation token');
if (!$dbUser->email_unconfirmed) if ($dbToken->used)
throw new SimpleException('This user was already activated'); throw new SimpleException('This user was already activated');
if ($dbToken->expires !== null and time() > $dbToken->expires)
throw new SimpleException('Activation link expired.');
$dbUser = $dbToken->user;
$dbUser->email_confirmed = $dbUser->email_unconfirmed; $dbUser->email_confirmed = $dbUser->email_unconfirmed;
$dbUser->email_unconfirmed = null; $dbUser->email_unconfirmed = null;
$dbToken->used = true;
R::store($dbToken);
R::store($dbUser); R::store($dbUser);
$this->context->transport->success = true; $this->context->transport->success = true;

53
src/Upgrades/Upgrade6.sql Normal file
View file

@ -0,0 +1,53 @@
CREATE TABLE user2
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
pass_salt TEXT,
pass_hash TEXT,
staff_confirmed INTEGER,
email_unconfirmed TEXT,
email_confirmed TEXT,
join_date INTEGER,
access_rank INTEGER,
settings TEXT,
banned INTEGER
);
INSERT INTO user2
(id,
name,
pass_salt,
pass_hash,
staff_confirmed,
email_unconfirmed,
email_confirmed,
join_date,
access_rank,
settings,
banned)
SELECT
id,
name,
pass_salt,
pass_hash,
staff_confirmed,
email_unconfirmed,
email_confirmed,
join_date,
access_rank,
settings,
banned
FROM user;
DROP TABLE user;
ALTER TABLE user2 RENAME TO user;
CREATE TABLE usertoken
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
token VARCHAR(32),
used BOOLEAN,
expires INTEGER --TIMESTAMP
);
CREATE INDEX idx_fk_usertoken_user_id ON usertoken(user_id);