Moved account registering to API

This commit is contained in:
Marcin Kurczewski 2014-05-04 14:57:44 +02:00
parent 4c66ca2b01
commit 83239a492d
14 changed files with 122 additions and 79 deletions

View file

@ -70,6 +70,9 @@ passwordResetEmailSubject = "{host} - password reset"
passwordResetEmailBody = "Hello,{nl}{nl}You received this e-mail because someone requested a password reset for user with this e-mail address at {host}. If it's you, visit {link} to finish password reset process, otherwise you may ignore and delete this e-mail.{nl}{nl}Kind regards,{nl}{host} mailing system"
[privileges]
registerAccount=anonymous
;registerAccount=nobody
uploadPost=registered
listPosts=anonymous
listPosts.sketchy=registered

View file

@ -143,6 +143,12 @@ $userValidation =
\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', '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);
@ -150,14 +156,11 @@ $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', 'genericView'], 'GET', '/user/{name}/{tab}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}/{page}', $userValidation);
foreach (['GET', 'POST'] as $method)
{
\Chibi\Router::register(['TagController', 'massTagRedirectAction'], $method, '/mass-tag-redirect', $tagValidation);
\Chibi\Router::register(['UserController', 'registrationAction'], $method, '/register', $userValidation);
\Chibi\Router::register(['UserController', 'activationAction'], $method, '/activation/{token}', $userValidation);
\Chibi\Router::register(['UserController', 'activationProxyAction'], $method, '/activation-proxy', $userValidation);
\Chibi\Router::register(['UserController', 'activationProxyAction'], $method, '/activation-proxy/{token}', $userValidation);

View file

@ -6,6 +6,7 @@ abstract class AbstractJob
const POST_NAME = 'post-name';
const TAG_NAME = 'tag-name';
const TAG_NAMES = 'tags';
const USER_ID = 'user-id';
const USER_NAME = 'user-name';
const TEXT = 'text';
const PAGE_NUMBER = 'page-number';

View file

@ -1,6 +1,8 @@
<?php
class Api
final class Api
{
protected static $checkPrivileges;
public static function run($job, $jobArgs)
{
$user = Auth::getCurrentUser();
@ -10,18 +12,21 @@ class Api
$job->setArguments($jobArgs);
$job->prepare();
if ($job->requiresAuthentication())
Access::assertAuthentication();
if (self::$checkPrivileges)
{
if ($job->requiresAuthentication())
Access::assertAuthentication();
if ($job->requiresConfirmedEmail())
Access::assertEmailConfirmation();
if ($job->requiresConfirmedEmail())
Access::assertEmailConfirmation();
$p = $job->requiresPrivilege();
list ($privilege, $subPrivilege) = is_array($p)
? $p
: [$p, false];
if ($privilege !== false)
Access::assert($privilege, $subPrivilege);
$p = $job->requiresPrivilege();
list ($privilege, $subPrivilege) = is_array($p)
? $p
: [$p, false];
if ($privilege !== false)
Access::assert($privilege, $subPrivilege);
}
return $job->execute();
});
@ -40,4 +45,14 @@ class Api
});
return $statuses;
}
public static function disablePrivilegeChecking()
{
self::$checkPrivileges = false;
}
public static function enablePrivilegeChecking()
{
self::$checkPrivileges = true;
}
}

View file

@ -0,0 +1,51 @@
<?php
class AddUserJob extends AbstractJob
{
public function execute()
{
$firstUser = UserModel::getCount() == 0;
$user = UserModel::spawn();
$user->joinDate = time();
$user->staffConfirmed = $firstUser;
$user->name = $this->getArgument(EditUserNameJob::NEW_USER_NAME);
UserModel::forgeId($user);
$arguments = $this->getArguments();
$arguments[EditUserJob::USER_NAME] = $user->name;
$arguments[EditUserAccessRankJob::NEW_ACCESS_RANK] = $firstUser
? AccessRank::Admin
: AccessRank::Registered;
LogHelper::bufferChanges();
Api::disablePrivilegeChecking();
Api::run(new EditUserJob(), $arguments);
Api::enablePrivilegeChecking();
LogHelper::setBuffer([]);
if ($firstUser and empty($user->emailConfirmed))
{
$user->emailConfirmed = $user->emailUnconfirmed;
$user->emailUnconfirmed = null;
}
//load the user after edits
$user = UserModel::findById($user->id);
//save the user to db if everything went okay
UserModel::save($user);
LogHelper::log('{subject} just signed up', [
'subject' => TextHelper::reprUser($user)]);
LogHelper::flush();
return $user;
}
public function requiresPrivilege()
{
return Privilege::RegisterAccount;
}
}

View file

@ -5,6 +5,10 @@ class EditUserEmailJob extends AbstractUserJob
public function execute()
{
if (getConfig()->registration->needEmailForRegistering)
if (!$this->hasArguemnt(self::NEW_EMAIL) or empty($this->getArgument(self::NEW_EMAIL)))
throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.');
$user = $this->user;
$newEmail = UserModel::validateEmail($this->getArgument(self::NEW_EMAIL));

View file

@ -9,10 +9,10 @@ class EditUserJob extends AbstractUserJob
$subJobs =
[
new EditUserAccessRankJob(),
new EditUserNameJob(),
new EditUserPasswordJob(),
new EditUserEmailJob(),
new EditUserAccessRankJob(),
];
foreach ($subJobs as $subJob)

View file

@ -6,13 +6,14 @@ class EditUserNameJob extends AbstractUserJob
public function execute()
{
$user = $this->user;
$newName = UserModel::validateUserName($this->getArgument(self::NEW_USER_NAME));
$newName = $this->getArgument(self::NEW_USER_NAME);
$oldName = $user->name;
if ($oldName == $newName)
return $user;
$user->name = $newName;
UserModel::validateUserName($user);
UserModel::save($user);

View file

@ -171,7 +171,7 @@ class UserController
Auth::setCurrentUser($user);
}
public function registrationAction()
public function registrationView()
{
$context = getContext();
$context->handleExceptions = true;
@ -182,56 +182,26 @@ class UserController
\Chibi\Util\Url::forward(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
exit;
}
}
$suppliedName = InputHelper::get('name');
$suppliedPassword1 = InputHelper::get('password1');
$suppliedPassword2 = InputHelper::get('password2');
$suppliedEmail = InputHelper::get('email');
$context->suppliedName = $suppliedName;
$context->suppliedPassword1 = $suppliedPassword1;
$context->suppliedPassword2 = $suppliedPassword2;
$context->suppliedEmail = $suppliedEmail;
public function registrationAction()
{
$this->registrationView();
if (!InputHelper::get('submit'))
return;
$suppliedName = UserModel::validateUserName($suppliedName);
if ($suppliedPassword1 != $suppliedPassword2)
if (InputHelper::get('password1') != InputHelper::get('password2'))
throw new SimpleException('Specified passwords must be the same');
$suppliedPassword = UserModel::validatePassword($suppliedPassword1);
$suppliedEmail = UserModel::validateEmail($suppliedEmail);
if (empty($suppliedEmail) and getConfig()->registration->needEmailForRegistering)
throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.');
$user = Api::run(new AddUserJob(),
[
EditUserNameJob::NEW_USER_NAME => InputHelper::get('name'),
EditUserPasswordJob::NEW_PASSWORD => InputHelper::get('password1'),
EditUserEmailJob::NEW_EMAIL => InputHelper::get('email'),
]);
//register the user
$dbUser = UserModel::spawn();
$dbUser->name = $suppliedName;
$dbUser->passHash = UserModel::hashPassword($suppliedPassword, $dbUser->passSalt);
$dbUser->emailUnconfirmed = $suppliedEmail;
$dbUser->joinDate = time();
if (UserModel::getCount() == 0)
if (!getConfig()->registration->needEmailForRegistering and !getConfig()->registration->staffActivation)
{
//very first user
$dbUser->accessRank = AccessRank::Admin;
$dbUser->staffConfirmed = true;
$dbUser->emailUnconfirmed = null;
$dbUser->emailConfirmed = $suppliedEmail;
Auth::setCurrentUser($user);
}
else
{
$dbUser->accessRank = AccessRank::Registered;
$dbUser->staffConfirmed = false;
$dbUser->staffConfirmed = null;
}
//save the user to db if everything went okay
UserModel::save($dbUser);
if (!empty($dbUser->emailUnconfirmed))
EditUserEmailJob::sendEmail($dbUser);
$message = 'Congratulations, your account was created.';
if (Mailer::getMailCounter() > 0)
@ -243,13 +213,7 @@ class UserController
elseif (getConfig()->registration->staffActivation)
$message .= ' Your registration must be now confirmed by staff.';
LogHelper::log('{subject} just signed up', ['subject' => TextHelper::reprUser($dbUser)]);
Messenger::message($message);
if (!getConfig()->registration->needEmailForRegistering and !getConfig()->registration->staffActivation)
{
Auth::setCurrentUser($dbUser);
}
}
public function activationAction($token)

View file

@ -18,6 +18,7 @@ class Privilege extends Enum
const ScorePost = 31;
const FlagPost = 34;
const RegisterAccount = 38;
const ListUsers = 11;
const ViewUser = 12;
const ViewUserEmail = 22;

View file

@ -176,18 +176,18 @@ class UserModel extends AbstractCrudModel
public static function validateUserName($userName)
public static function validateUserName(UserEntity $user)
{
$userName = trim($userName);
$userName = trim($user->name);
$config = getConfig();
$dbUser = self::findByName($userName, false);
if ($dbUser !== null)
$otherUser = self::findByName($userName, false);
if ($otherUser !== null and $otherUser->id != $user->id)
{
if (!$dbUser->emailConfirmed and $config->registration->needEmailForRegistering)
if (!$otherUser->emailConfirmed and $config->registration->needEmailForRegistering)
throw new SimpleException('User with this name is already registered and awaits e-mail confirmation');
if (!$dbUser->staffConfirmed and $config->registration->staffActivation)
if (!$otherUser->staffConfirmed and $config->registration->staffActivation)
throw new SimpleException('User with this name is already registered and awaits staff confirmation');
throw new SimpleException('User with this name is already registered');

View file

@ -11,7 +11,7 @@ Assets::addStylesheet('auth.css');
<p>
If you don't have an account yet,<br/>
<a href="<?= \Chibi\Router::linkTo(['UserController', 'registrationAction']); ?>">click here</a> to create a new one.
<a href="<?= \Chibi\Router::linkTo(['UserController', 'registrationView']); ?>">click here</a> to create a new one.
</p>
<div class="form-row">
@ -45,7 +45,7 @@ Assets::addStylesheet('auth.css');
<ul>
<li><a href="<?= \Chibi\Router::linkTo(['UserController', 'passwordResetProxyAction']) ?>">I don't remember my password</a></li>
<li><a href="<?= \Chibi\Router::linkTo(['UserController', 'activationProxyAction']) ?>">I haven't received activation e-mail</a></li>
<li><a href="<?= \Chibi\Router::linkTo(['UserController', 'registrationAction']) ?>">I don't have an account</a></li>
<li><a href="<?= \Chibi\Router::linkTo(['UserController', 'registrationView']) ?>">I don't have an account</a></li>
</ul>
</div>
</div>

View file

@ -69,7 +69,7 @@
$registerNavItem(
'Register',
\Chibi\Router::linkTo(['UserController', 'registrationAction']),
\Chibi\Router::linkTo(['UserController', 'registrationView']),
$activeController == 'user' and $activeAction == 'registration');
}
else

View file

@ -23,7 +23,7 @@ Assets::setSubTitle('registration form');
type="text"
id="name"
name="name"
value="<?= htmlspecialchars($this->context->suppliedName) ?>"
value="<?= htmlspecialchars(InputHelper::get('name')) ?>"
placeholder="e.g. darth_vader"
autocomplete="off"/>
</div>
@ -36,7 +36,7 @@ Assets::setSubTitle('registration form');
type="password"
id="password1"
name="password1"
value="<?= htmlspecialchars($this->context->suppliedPassword1) ?>"
value="<?= htmlspecialchars(InputHelper::get('password1')) ?>"
placeholder="e.g. <?= str_repeat('&#x25cf;', 8) ?>"
autocomplete="off"/>
</div>
@ -49,7 +49,7 @@ Assets::setSubTitle('registration form');
type="password"
id="password2"
name="password2"
value="<?= htmlspecialchars($this->context->suppliedPassword2) ?>"
value="<?= htmlspecialchars(InputHelper::get('password2')) ?>"
placeholder="e.g. <?= str_repeat('&#x25cf;', 8) ?>"
autocomplete="off"/>
</div>
@ -62,7 +62,7 @@ Assets::setSubTitle('registration form');
type="text"
id="email"
name="email"
value="<?= htmlspecialchars($this->context->suppliedEmail) ?>"
value="<?= htmlspecialchars(InputHelper::get('email')) ?>"
placeholder="e.g. vader@empire.gov" autocomplete="off"/>
</div>
</div>