diff --git a/data/config.ini b/data/config.ini index ec8b4010..e4740d27 100644 --- a/data/config.ini +++ b/data/config.ini @@ -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 diff --git a/public_html/dispatch.php b/public_html/dispatch.php index 448e19e2..c14f7883 100644 --- a/public_html/dispatch.php +++ b/public_html/dispatch.php @@ -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); diff --git a/src/Api/AbstractJob.php b/src/Api/AbstractJob.php index 657abe50..a71997a9 100644 --- a/src/Api/AbstractJob.php +++ b/src/Api/AbstractJob.php @@ -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'; diff --git a/src/Api/Api.php b/src/Api/Api.php index 26555d8a..48637c7c 100644 --- a/src/Api/Api.php +++ b/src/Api/Api.php @@ -1,6 +1,8 @@ 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; + } } diff --git a/src/Api/Jobs/AddUserJob.php b/src/Api/Jobs/AddUserJob.php new file mode 100644 index 00000000..6a426207 --- /dev/null +++ b/src/Api/Jobs/AddUserJob.php @@ -0,0 +1,51 @@ +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; + } +} diff --git a/src/Api/Jobs/EditUserEmailJob.php b/src/Api/Jobs/EditUserEmailJob.php index fb71b718..375e138e 100644 --- a/src/Api/Jobs/EditUserEmailJob.php +++ b/src/Api/Jobs/EditUserEmailJob.php @@ -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)); diff --git a/src/Api/Jobs/EditUserJob.php b/src/Api/Jobs/EditUserJob.php index d180db82..8b5b1729 100644 --- a/src/Api/Jobs/EditUserJob.php +++ b/src/Api/Jobs/EditUserJob.php @@ -9,10 +9,10 @@ class EditUserJob extends AbstractUserJob $subJobs = [ + new EditUserAccessRankJob(), new EditUserNameJob(), new EditUserPasswordJob(), new EditUserEmailJob(), - new EditUserAccessRankJob(), ]; foreach ($subJobs as $subJob) diff --git a/src/Api/Jobs/EditUserNameJob.php b/src/Api/Jobs/EditUserNameJob.php index 81553550..fe57b3c9 100644 --- a/src/Api/Jobs/EditUserNameJob.php +++ b/src/Api/Jobs/EditUserNameJob.php @@ -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); diff --git a/src/Controllers/UserController.php b/src/Controllers/UserController.php index 733ac03c..46b99521 100644 --- a/src/Controllers/UserController.php +++ b/src/Controllers/UserController.php @@ -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) diff --git a/src/Models/Enums/Privilege.php b/src/Models/Enums/Privilege.php index 3fb7a4b0..4f81040a 100644 --- a/src/Models/Enums/Privilege.php +++ b/src/Models/Enums/Privilege.php @@ -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; diff --git a/src/Models/UserModel.php b/src/Models/UserModel.php index 502023db..c12cd158 100644 --- a/src/Models/UserModel.php +++ b/src/Models/UserModel.php @@ -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'); diff --git a/src/Views/auth-login.phtml b/src/Views/auth-login.phtml index 45dd31ef..6c473bc5 100644 --- a/src/Views/auth-login.phtml +++ b/src/Views/auth-login.phtml @@ -11,7 +11,7 @@ Assets::addStylesheet('auth.css');

If you don't have an account yet,
- click here to create a new one. + click here to create a new one.

@@ -45,7 +45,7 @@ Assets::addStylesheet('auth.css');
diff --git a/src/Views/top-navigation.phtml b/src/Views/top-navigation.phtml index ad330ba1..da463304 100644 --- a/src/Views/top-navigation.phtml +++ b/src/Views/top-navigation.phtml @@ -69,7 +69,7 @@ $registerNavItem( 'Register', - \Chibi\Router::linkTo(['UserController', 'registrationAction']), + \Chibi\Router::linkTo(['UserController', 'registrationView']), $activeController == 'user' and $activeAction == 'registration'); } else diff --git a/src/Views/user-registration.phtml b/src/Views/user-registration.phtml index 151cd367..9a6dc542 100644 --- a/src/Views/user-registration.phtml +++ b/src/Views/user-registration.phtml @@ -23,7 +23,7 @@ Assets::setSubTitle('registration form'); type="text" id="name" name="name" - value="context->suppliedName) ?>" + value="" placeholder="e.g. darth_vader" autocomplete="off"/> @@ -36,7 +36,7 @@ Assets::setSubTitle('registration form'); type="password" id="password1" name="password1" - value="context->suppliedPassword1) ?>" + value="" placeholder="e.g. " autocomplete="off"/> @@ -49,7 +49,7 @@ Assets::setSubTitle('registration form'); type="password" id="password2" name="password2" - value="context->suppliedPassword2) ?>" + value="" placeholder="e.g. " autocomplete="off"/> @@ -62,7 +62,7 @@ Assets::setSubTitle('registration form'); type="text" id="email" name="email" - value="context->suppliedEmail) ?>" + value="" placeholder="e.g. vader@empire.gov" autocomplete="off"/>