Fixed account activation links

This commit is contained in:
Marcin Kurczewski 2014-05-07 17:39:40 +02:00
parent 1bbba5de3c
commit 329f6a0259
12 changed files with 382 additions and 145 deletions

@ -1 +1 @@
Subproject commit 5e78e0a68a1188851d12e26c0f58c1ffe95ffb69
Subproject commit 3c70aa336c0571d83557d5fe66ff1b5cc0f3478f

View file

@ -36,130 +36,6 @@ $context->simpleActionName = null;
$context->simpleActionName);
});
\Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', '');
\Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', '/index');
\Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help');
\Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help/{tab}');
\Chibi\Router::register(['AuthController', 'loginView'], 'GET', '/auth/login');
\Chibi\Router::register(['AuthController', 'loginAction'], 'POST', '/auth/login');
\Chibi\Router::register(['AuthController', 'logoutAction'], 'POST', '/auth/logout');
\Chibi\Router::register(['AuthController', 'logoutAction'], 'GET', '/auth/logout');
\Chibi\Router::register(['LogController', 'listView'], 'GET', '/logs');
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}', ['name' => '[0-9a-zA-Z._-]+']);
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}/{page}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*']);
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}/{page}/{filter}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*', 'filter' => '.*']);
$postValidation =
[
'tag' => '[^\/]*',
'enable' => '0|1',
'source' => 'posts|mass-tag',
'query' => '[^\/]*',
'additionalInfo' => '[^\/]*',
'score' => '-1|0|1',
];
\Chibi\Router::register(['PostController', 'uploadView'], 'GET', '/posts/upload', $postValidation);
\Chibi\Router::register(['PostController', 'uploadAction'], 'POST', '/posts/upload', $postValidation);
\Chibi\Router::register(['PostController', 'editView'], 'GET', '/post/{id}/edit', $postValidation);
\Chibi\Router::register(['PostController', 'editAction'], 'POST', '/post/{id}/edit', $postValidation);
\Chibi\Router::register(['PostController', 'deleteAction'], 'POST', '/post/{id}/delete', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{additionalInfo}/{query}/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'randomView'], 'GET', '/random', $postValidation);
\Chibi\Router::register(['PostController', 'randomView'], 'GET', '/random/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'favoritesView'], 'GET', '/favorites', $postValidation);
\Chibi\Router::register(['PostController', 'favoritesView'], 'GET', '/favorites/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'upvotedView'], 'GET', '/upvoted', $postValidation);
\Chibi\Router::register(['PostController', 'upvotedView'], 'GET', '/upvoted/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'genericView'], 'GET', '/post/{id}', $postValidation);
\Chibi\Router::register(['PostController', 'fileView'], 'GET', '/post/{name}/retrieve', $postValidation);
\Chibi\Router::register(['PostController', 'thumbView'], 'GET', '/post/{name}/thumb', $postValidation);
\Chibi\Router::register(['PostController', 'toggleTagAction'], 'POST', '/post/{id}/toggle-tag/{tag}/{enable}', $postValidation);
\Chibi\Router::register(['PostController', 'flagAction'], 'POST', '/post/{id}/flag', $postValidation);
\Chibi\Router::register(['PostController', 'hideAction'], 'POST', '/post/{id}/hide', $postValidation);
\Chibi\Router::register(['PostController', 'unhideAction'], 'POST', '/post/{id}/unhide', $postValidation);
\Chibi\Router::register(['PostController', 'removeFavoriteAction'], 'POST', '/post/{id}/rem-fav', $postValidation);
\Chibi\Router::register(['PostController', 'addFavoriteAction'], 'POST', '/post/{id}/add-fav', $postValidation);
\Chibi\Router::register(['PostController', 'scoreAction'], 'POST', '/post/{id}/score/{score}', $postValidation);
\Chibi\Router::register(['PostController', 'featureAction'], 'POST', '/post/{id}/feature', $postValidation);
$commentValidation =
[
'id' => '\d+',
'page' => '\d+',
];
\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments', $commentValidation);
\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments/{page}', $commentValidation);
\Chibi\Router::register(['CommentController', 'addAction'], 'POST', '/comment/add', $commentValidation);
\Chibi\Router::register(['CommentController', 'deleteAction'], 'POST', '/comment/{id}/delete', $commentValidation);
\Chibi\Router::register(['CommentController', 'editView'], 'GET', '/comment/{id}/edit', $commentValidation);
\Chibi\Router::register(['CommentController', 'editAction'], 'POST', '/comment/{id}/edit', $commentValidation);
$tagValidation =
[
'page' => '\d*',
'filter' => '[^\/]+',
];
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags', $tagValidation);
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags/{page}', $tagValidation);
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags/{filter}/{page}', $tagValidation);
\Chibi\Router::register(['TagController', 'autoCompleteView'], 'GET', '/tags-autocomplete', $tagValidation);
\Chibi\Router::register(['TagController', 'relatedView'], 'GET', '/tags-related', $tagValidation);
\Chibi\Router::register(['TagController', 'renameView'], 'GET', '/tags-rename', $tagValidation);
\Chibi\Router::register(['TagController', 'renameAction'], 'POST', '/tags-rename', $tagValidation);
\Chibi\Router::register(['TagController', 'mergeView'], 'GET', '/tags-merge', $tagValidation);
\Chibi\Router::register(['TagController', 'mergeAction'], 'POST', '/tags-merge', $tagValidation);
$userValidation =
[
'name' => '[^\/]+',
'page' => '\d*',
'tab' => 'favs|uploads|settings|edit|delete',
'filter' => '[^\/]+',
];
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{filter}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'registrationView'], 'GET', '/register', $userValidation);
\Chibi\Router::register(['UserController', 'registrationAction'], 'POST', '/register', $userValidation);
\Chibi\Router::register(['UserController', 'activationView'], 'GET', '/activation', $userValidation);
\Chibi\Router::register(['UserController', 'activationAction'], 'POST', '/activation', $userValidation);
\Chibi\Router::register(['UserController', 'activationAction'], 'GET', '/activation/{tokenText}', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetView'], 'GET', '/password-reset', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'POST', '/password-reset', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'GET', '/password-reset/{tokenText}', $userValidation);
\Chibi\Router::register(['UserController', 'flagAction'], 'POST', '/user/{name}/flag', $userValidation);
\Chibi\Router::register(['UserController', 'banAction'], 'POST', '/user/{name}/ban', $userValidation);
\Chibi\Router::register(['UserController', 'unbanAction'], 'POST', '/user/{name}/unban', $userValidation);
\Chibi\Router::register(['UserController', 'acceptRegistrationAction'], 'POST', '/user/{name}/accept-registration', $userValidation);
\Chibi\Router::register(['UserController', 'deleteAction'], 'POST', '/user/{name}/delete', $userValidation);
\Chibi\Router::register(['UserController', 'settingsAction'], 'POST', '/user/{name}/settings', $userValidation);
\Chibi\Router::register(['UserController', 'editAction'], 'POST', '/user/{name}/edit', $userValidation);
foreach (['GET', 'POST'] as $method)
{
\Chibi\Router::register(['TagController', 'massTagRedirectAction'], $method, '/mass-tag-redirect', $tagValidation);
\Chibi\Router::register(['UserController', 'toggleSafetyAction'], $method, '/user/toggle-safety/{safety}', $userValidation);
}
Assets::setTitle($config->main->title);
$context->handleExceptions = false;

View file

@ -29,7 +29,7 @@ class ActivateUserEmailJob extends AbstractJob
$user = $token->getUser();
$user->confirmEmail();
$token->used = true;
$token->setUsed(true);
TokenModel::save($token);
UserModel::save($user);

View file

@ -6,4 +6,6 @@ class Mail
public $senderName;
public $senderEmail;
public $recipientEmail;
public $tokens;
}

View file

@ -1,12 +1,14 @@
<?php
class Mailer
{
private static $mailCounter = 0;
private static $mock = false;
private static $mailCounter;
private static $mailsSent;
private static $mock;
public static function init()
{
self::$mailCounter = 0;
self::$mailsSent = [];
self::$mock = false;
}
@ -15,6 +17,11 @@ class Mailer
return self::$mailCounter;
}
public static function getMailsSent()
{
return self::$mailsSent;
}
public static function mockSending()
{
self::$mock = true;
@ -63,6 +70,8 @@ class Mailer
if (!self::$mock)
mail($recipientEmail, $encodedSubject, $body, implode("\r\n", $headers), '-f' . $senderEmail);
$mail->tokens = $tokens;
self::$mailsSent []= $mail;
self::$mailCounter ++;
Logger::log('Sending e-mail with subject "{subject}" to {mail}', [
@ -79,13 +88,13 @@ class Mailer
//prepare unique user token
$token = TokenModel::spawn();
$token->setUser($user);
$token->token = TokenModel::forgeUnusedToken();
$token->used = false;
$token->expires = null;
$token->setText(TokenModel::forgeUnusedToken());
$token->setUsed(false);
$token->setExpirationDate(null);
TokenModel::save($token);
if (!self::$mock)
$tokens['link'] = \Chibi\Router::linkTo($linkDestination, ['token' => $token->token]);
$tokens['link'] = \Chibi\Router::linkTo($linkDestination, ['tokenText' => $token->getText()]);
$tokens['token'] = $token->getText(); //yeah
return self::sendMail($mail, $tokens);
}

View file

@ -1,21 +1,56 @@
<?php
class TokenEntity extends AbstractEntity implements IValidatable
{
public $userId;
public $token;
public $used;
public $expires;
protected $userId;
protected $token;
protected $used;
protected $expires;
public function validate()
{
//todo
}
public function getText()
{
return $this->token;
}
public function setText($tokenText)
{
$this->token = $tokenText;
}
public function isUsed()
{
return $this->used;
}
public function setUsed($used)
{
$this->used = $used;
}
public function getExpirationDate()
{
return $this->expires;
}
public function setExpirationDate($time)
{
$this->expires = $time;
}
public function getUser()
{
return UserModel::findById($this->userId);
}
public function getUserId()
{
return $this->userId;
}
public function setUser($user)
{
$this->userId = $user ? $user->getId() : null;

View file

@ -18,10 +18,10 @@ class TokenModel extends AbstractCrudModel
self::forgeId($token);
$bindings = [
'user_id' => $token->userId,
'token' => $token->token,
'used' => $token->used,
'expires' => $token->expires,
'user_id' => $token->getUserId(),
'token' => $token->getText(),
'used' => $token->isUsed(),
'expires' => $token->getExpirationDate(),
];
$stmt = new Sql\UpdateStatement();
@ -61,10 +61,10 @@ class TokenModel extends AbstractCrudModel
if (empty($token))
throw new SimpleException('Invalid security token');
if ($token->used)
if ($token->isUsed())
throw new SimpleException('This token was already used');
if ($token->expires !== null and time() > $token->expires)
if ($token->getExpirationDate() !== null and time() > $token->getExpirationDate())
throw new SimpleException('This token has expired');
}

View file

@ -120,12 +120,15 @@ class UserModel extends AbstractCrudModel
public static function findByNameOrEmail($key, $throw = true)
{
$key = trim($key);
$stmt = new Sql\SelectStatement();
$stmt->setColumn('*');
$stmt->setTable('user');
$stmt->setCriterion((new Sql\DisjunctionFunctor)
->add(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('name', new Sql\Binding(trim($key)))))
->add(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('email_confirmed', new Sql\Binding(trim($key))))));
->add(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('name', new Sql\Binding($key))))
->add(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('email_unconfirmed', new Sql\Binding($key))))
->add(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('email_confirmed', new Sql\Binding($key)))));
$row = Database::fetchOne($stmt);
if ($row)

View file

@ -20,6 +20,8 @@ require_once $rootDir . 'lib' . DS . 'chibi-core' . DS . 'include.php';
\Chibi\AutoLoader::registerFilesystem($rootDir . 'lib' . DS . 'chibi-sql');
\Chibi\AutoLoader::registerFilesystem(__DIR__);
require_once $rootDir . 'src' . DS . 'routes.php';
function getConfig()
{
global $config;

119
src/routes.php Normal file
View file

@ -0,0 +1,119 @@
<?php
\Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', '');
\Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', '/index');
\Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help');
\Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help/{tab}');
\Chibi\Router::register(['AuthController', 'loginView'], 'GET', '/auth/login');
\Chibi\Router::register(['AuthController', 'loginAction'], 'POST', '/auth/login');
\Chibi\Router::register(['AuthController', 'logoutAction'], 'POST', '/auth/logout');
\Chibi\Router::register(['AuthController', 'logoutAction'], 'GET', '/auth/logout');
\Chibi\Router::register(['LogController', 'listView'], 'GET', '/logs');
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}', ['name' => '[0-9a-zA-Z._-]+']);
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}/{page}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*']);
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}/{page}/{filter}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*', 'filter' => '.*']);
$postValidation =
[
'tag' => '[^\/]*',
'enable' => '0|1',
'source' => 'posts|mass-tag',
'query' => '[^\/]*',
'additionalInfo' => '[^\/]*',
'score' => '-1|0|1',
];
\Chibi\Router::register(['PostController', 'uploadView'], 'GET', '/posts/upload', $postValidation);
\Chibi\Router::register(['PostController', 'uploadAction'], 'POST', '/posts/upload', $postValidation);
\Chibi\Router::register(['PostController', 'editView'], 'GET', '/post/{id}/edit', $postValidation);
\Chibi\Router::register(['PostController', 'editAction'], 'POST', '/post/{id}/edit', $postValidation);
\Chibi\Router::register(['PostController', 'deleteAction'], 'POST', '/post/{id}/delete', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{additionalInfo}/{query}/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'randomView'], 'GET', '/random', $postValidation);
\Chibi\Router::register(['PostController', 'randomView'], 'GET', '/random/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'favoritesView'], 'GET', '/favorites', $postValidation);
\Chibi\Router::register(['PostController', 'favoritesView'], 'GET', '/favorites/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'upvotedView'], 'GET', '/upvoted', $postValidation);
\Chibi\Router::register(['PostController', 'upvotedView'], 'GET', '/upvoted/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'genericView'], 'GET', '/post/{id}', $postValidation);
\Chibi\Router::register(['PostController', 'fileView'], 'GET', '/post/{name}/retrieve', $postValidation);
\Chibi\Router::register(['PostController', 'thumbView'], 'GET', '/post/{name}/thumb', $postValidation);
\Chibi\Router::register(['PostController', 'toggleTagAction'], 'POST', '/post/{id}/toggle-tag/{tag}/{enable}', $postValidation);
\Chibi\Router::register(['PostController', 'flagAction'], 'POST', '/post/{id}/flag', $postValidation);
\Chibi\Router::register(['PostController', 'hideAction'], 'POST', '/post/{id}/hide', $postValidation);
\Chibi\Router::register(['PostController', 'unhideAction'], 'POST', '/post/{id}/unhide', $postValidation);
\Chibi\Router::register(['PostController', 'removeFavoriteAction'], 'POST', '/post/{id}/rem-fav', $postValidation);
\Chibi\Router::register(['PostController', 'addFavoriteAction'], 'POST', '/post/{id}/add-fav', $postValidation);
\Chibi\Router::register(['PostController', 'scoreAction'], 'POST', '/post/{id}/score/{score}', $postValidation);
\Chibi\Router::register(['PostController', 'featureAction'], 'POST', '/post/{id}/feature', $postValidation);
$commentValidation =
[
'id' => '\d+',
'page' => '\d+',
];
\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments', $commentValidation);
\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments/{page}', $commentValidation);
\Chibi\Router::register(['CommentController', 'addAction'], 'POST', '/comment/add', $commentValidation);
\Chibi\Router::register(['CommentController', 'deleteAction'], 'POST', '/comment/{id}/delete', $commentValidation);
\Chibi\Router::register(['CommentController', 'editView'], 'GET', '/comment/{id}/edit', $commentValidation);
\Chibi\Router::register(['CommentController', 'editAction'], 'POST', '/comment/{id}/edit', $commentValidation);
$tagValidation =
[
'page' => '\d*',
'filter' => '[^\/]+',
];
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags', $tagValidation);
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags/{page}', $tagValidation);
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags/{filter}/{page}', $tagValidation);
\Chibi\Router::register(['TagController', 'autoCompleteView'], 'GET', '/tags-autocomplete', $tagValidation);
\Chibi\Router::register(['TagController', 'relatedView'], 'GET', '/tags-related', $tagValidation);
\Chibi\Router::register(['TagController', 'renameView'], 'GET', '/tags-rename', $tagValidation);
\Chibi\Router::register(['TagController', 'renameAction'], 'POST', '/tags-rename', $tagValidation);
\Chibi\Router::register(['TagController', 'mergeView'], 'GET', '/tags-merge', $tagValidation);
\Chibi\Router::register(['TagController', 'mergeAction'], 'POST', '/tags-merge', $tagValidation);
\Chibi\Router::register(['TagController', 'massTagRedirectAction'], 'GET', '/mass-tag-redirect', $tagValidation);
$userValidation =
[
'name' => '[^\/]+',
'page' => '\d*',
'tab' => 'favs|uploads|settings|edit|delete',
'filter' => '[^\/]+',
];
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{filter}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'registrationView'], 'GET', '/register', $userValidation);
\Chibi\Router::register(['UserController', 'registrationAction'], 'POST', '/register', $userValidation);
\Chibi\Router::register(['UserController', 'activationView'], 'GET', '/activation', $userValidation);
\Chibi\Router::register(['UserController', 'activationAction'], 'POST', '/activation', $userValidation);
\Chibi\Router::register(['UserController', 'activationAction'], 'GET', '/activation/{tokenText}', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetView'], 'GET', '/password-reset', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'POST', '/password-reset', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'GET', '/password-reset/{tokenText}', $userValidation);
\Chibi\Router::register(['UserController', 'flagAction'], 'POST', '/user/{name}/flag', $userValidation);
\Chibi\Router::register(['UserController', 'banAction'], 'POST', '/user/{name}/ban', $userValidation);
\Chibi\Router::register(['UserController', 'unbanAction'], 'POST', '/user/{name}/unban', $userValidation);
\Chibi\Router::register(['UserController', 'acceptRegistrationAction'], 'POST', '/user/{name}/accept-registration', $userValidation);
\Chibi\Router::register(['UserController', 'deleteAction'], 'POST', '/user/{name}/delete', $userValidation);
\Chibi\Router::register(['UserController', 'settingsAction'], 'POST', '/user/{name}/settings', $userValidation);
\Chibi\Router::register(['UserController', 'editAction'], 'POST', '/user/{name}/edit', $userValidation);
\Chibi\Router::register(['UserController', 'toggleSafetyAction'], 'POST', '/user/toggle-safety/{safety}', $userValidation);

View file

@ -0,0 +1,149 @@
<?php
class ActivateUserEmailJobTest extends AbstractTest
{
public function testSending()
{
getConfig()->registration->needEmailForRegistering = true;
Mailer::mockSending();
$user = $this->mockUser();
$user->setUnconfirmedEmail('godzilla@whitestar.gov');
UserModel::save($user);
$this->assert->areEqual(0, Mailer::getMailCounter());
$this->assert->doesNotThrow(function() use ($user)
{
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::USER_NAME => $user->getName(),
]);
});
$this->assert->areEqual(1, Mailer::getMailCounter());
$tokens = Mailer::getMailsSent()[0]->tokens;
$tokenText = $tokens['token'];
$token = TokenModel::findByToken($tokenText);
$this->assert->areEqual($user->getId(), $token->getUser()->getId());
$this->assert->isTrue(strpos($tokens['link'], $tokenText) !== false);
return $tokenText;
}
public function testConfirming()
{
getConfig()->registration->needEmailForRegistering = true;
Mailer::mockSending();
$user = $this->mockUser();
$user->setUnconfirmedEmail('godzilla@whitestar.gov');
UserModel::save($user);
$this->assert->areEqual('godzilla@whitestar.gov', $user->getUnconfirmedEmail());
$this->assert->areEqual(null, $user->getConfirmedEmail());
$this->assert->doesNotThrow(function() use ($user)
{
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::USER_NAME => $user->getName(),
]);
});
$tokenText = Mailer::getMailsSent()[0]->tokens['token'];
$this->assert->doesNotThrow(function() use ($tokenText)
{
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::TOKEN => $tokenText,
]);
});
//reload local entity after changes done by the job
$user = UserModel::findById($user->getId());
$this->assert->areEqual(null, $user->getUnconfirmedEmail());
$this->assert->areEqual('godzilla@whitestar.gov', $user->getConfirmedEmail());
}
public function testUsingTokenTwice()
{
getConfig()->registration->needEmailForRegistering = true;
Mailer::mockSending();
$user = $this->mockUser();
$user->setUnconfirmedEmail('godzilla@whitestar.gov');
UserModel::save($user);
$this->assert->areEqual('godzilla@whitestar.gov', $user->getUnconfirmedEmail());
$this->assert->areEqual(null, $user->getConfirmedEmail());
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::USER_NAME => $user->getName(),
]);
$tokenText = Mailer::getMailsSent()[0]->tokens['token'];
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::TOKEN => $tokenText,
]);
$this->assert->throws(function() use ($tokenText)
{
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::TOKEN => $tokenText,
]);
}, 'This token was already used');
}
public function testTokensTwoUsersSameMail()
{
getConfig()->registration->needEmailForRegistering = true;
Mailer::mockSending();
$user1 = $this->mockUser();
$user2 = $this->mockUser();
$user1->setUnconfirmedEmail('godzilla@whitestar.gov');
$user2->setUnconfirmedEmail('godzilla@whitestar.gov');
UserModel::save($user1);
UserModel::save($user2);
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::USER_NAME => $user1->getName(),
]);
Api::run(
new ActivateUserEmailJob(),
[
ActivateUserEmailJob::USER_NAME => $user2->getName(),
]);
$tokens1 = Mailer::getMailsSent()[0]->tokens;
$tokens2 = Mailer::getMailsSent()[1]->tokens;
$token1text = $tokens1['token'];
$token2text = $tokens2['token'];
$this->assert->areNotEqual($token1text, $token2text);
$token1 = TokenModel::findByToken($token1text);
$token2 = TokenModel::findByToken($token2text);
$this->assert->areEqual($user1->getId(), $token1->getUser()->getId());
$this->assert->areEqual($user2->getId(), $token2->getUser()->getId());
$this->assert->areNotEqual($token1->getUserId(), $token2->getUserId());
}
}

View file

@ -263,6 +263,48 @@ class AddUserJobTest extends AbstractTest
$this->assert->areEqual(0, Mailer::getMailCounter());
}
public function testEmailsTwoUsersSameMail()
{
getConfig()->registration->needEmailForRegistering = true;
Mailer::mockSending();
$this->assert->areEqual(0, Mailer::getMailCounter());
$this->grantAccess('registerAccount');
$user1 = $this->assert->doesNotThrow(function()
{
return Api::run(
new AddUserJob(),
[
EditUserNameJob::NEW_USER_NAME => 'dummy',
EditUserPasswordJob::NEW_PASSWORD => 'sekai',
EditUserEmailJob::NEW_EMAIL => 'godzilla@whitestar.gov',
]);
});
$user2 = $this->assert->doesNotThrow(function()
{
return Api::run(
new AddUserJob(),
[
EditUserNameJob::NEW_USER_NAME => 'dummy2',
EditUserPasswordJob::NEW_PASSWORD => 'sekai',
EditUserEmailJob::NEW_EMAIL => 'godzilla@whitestar.gov',
]);
});
$this->assert->areEqual(2, Mailer::getMailCounter());
$token1text = Mailer::getMailsSent()[0]->tokens['token'];
$token2text = Mailer::getMailsSent()[1]->tokens['token'];
$this->assert->areNotEqual($token1text, $token2text);
$token1 = TokenModel::findByToken($token1text);
$token2 = TokenModel::findByToken($token2text);
$this->assert->areEqual($user1->getId(), $token1->getUser()->getId());
$this->assert->areEqual($user2->getId(), $token2->getUser()->getId());
}
public function testLogBuffering()
{
$this->testSaving();