2013-10-05 19:24:08 +02:00
|
|
|
<?php
|
2013-10-05 21:24:20 +02:00
|
|
|
class UserController
|
2013-10-05 19:24:08 +02:00
|
|
|
{
|
2013-11-18 10:30:43 +01:00
|
|
|
private function loadUserView($user)
|
|
|
|
{
|
|
|
|
$flagged = in_array(TextHelper::reprUser($user), SessionHelper::get('flagged', []));
|
|
|
|
$this->context->flagged = $flagged;
|
|
|
|
$this->context->transport->user = $user;
|
|
|
|
$this->context->handleExceptions = true;
|
|
|
|
$this->context->viewName = 'user-view';
|
|
|
|
$this->context->stylesheets []= 'user-view.css';
|
|
|
|
$this->context->subTitle = $user->name;
|
|
|
|
}
|
|
|
|
|
2013-11-16 16:24:38 +01:00
|
|
|
private static function sendTokenizedEmail(
|
|
|
|
$user,
|
|
|
|
$body,
|
|
|
|
$subject,
|
|
|
|
$senderName,
|
|
|
|
$senderEmail,
|
|
|
|
$recipientEmail,
|
2013-11-18 15:41:16 +01:00
|
|
|
$linkActionName)
|
2013-10-16 18:07:23 +02:00
|
|
|
{
|
2013-11-16 16:24:38 +01:00
|
|
|
//prepare unique user token
|
2013-12-18 15:10:53 +01:00
|
|
|
$token = TokenModel::spawn();
|
|
|
|
$token->setUser($user);
|
|
|
|
$token->token = TokenModel::forgeUnusedToken();
|
2013-11-16 16:24:38 +01:00
|
|
|
$token->used = false;
|
|
|
|
$token->expires = null;
|
2013-12-18 15:10:53 +01:00
|
|
|
TokenModel::save($token);
|
2013-10-16 19:56:02 +02:00
|
|
|
|
|
|
|
\Chibi\Registry::getContext()->mailSent = true;
|
2013-11-18 15:41:16 +01:00
|
|
|
$tokens = [];
|
2013-10-16 18:07:23 +02:00
|
|
|
$tokens['host'] = $_SERVER['HTTP_HOST'];
|
2013-12-18 15:10:53 +01:00
|
|
|
$tokens['token'] = $token->token; //gosh this code looks so silly
|
2013-12-14 14:50:30 +01:00
|
|
|
$tokens['nl'] = PHP_EOL;
|
2013-11-18 15:41:16 +01:00
|
|
|
if ($linkActionName !== null)
|
2013-12-18 15:10:53 +01:00
|
|
|
$tokens['link'] = \Chibi\UrlHelper::route('user', $linkActionName, ['token' => $token->token]);
|
2013-10-16 18:07:23 +02:00
|
|
|
|
2013-11-16 16:24:38 +01:00
|
|
|
$body = wordwrap(TextHelper::replaceTokens($body, $tokens), 70);
|
|
|
|
$subject = TextHelper::replaceTokens($subject, $tokens);
|
|
|
|
$senderName = TextHelper::replaceTokens($senderName, $tokens);
|
|
|
|
$senderEmail = TextHelper::replaceTokens($senderEmail, $tokens);
|
2013-10-16 18:07:23 +02:00
|
|
|
|
2013-11-16 19:24:33 +01:00
|
|
|
if (empty($recipientEmail))
|
|
|
|
throw new SimpleException('Destination e-mail address was not found');
|
|
|
|
|
2013-10-16 18:07:23 +02:00
|
|
|
$headers = [];
|
2013-10-16 20:56:46 +02:00
|
|
|
$headers []= sprintf('MIME-Version: 1.0');
|
|
|
|
$headers []= sprintf('Content-Transfer-Encoding: 7bit');
|
|
|
|
$headers []= sprintf('Date: %s', date('r', $_SERVER['REQUEST_TIME']));
|
|
|
|
$headers []= sprintf('Message-ID: <%s>', $_SERVER['REQUEST_TIME'] . md5($_SERVER['REQUEST_TIME']) . '@' . $_SERVER['HTTP_HOST']);
|
|
|
|
$headers []= sprintf('From: %s <%s>', $senderName, $senderEmail);
|
|
|
|
$headers []= sprintf('Reply-To: %s', $senderEmail);
|
|
|
|
$headers []= sprintf('Return-Path: %s', $senderEmail);
|
|
|
|
$headers []= sprintf('Subject: %s', $subject);
|
|
|
|
$headers []= sprintf('Content-Type: text/plain; charset=utf-8', $subject);
|
|
|
|
$headers []= sprintf('X-Mailer: PHP/%s', phpversion());
|
|
|
|
$headers []= sprintf('X-Originating-IP: %s', $_SERVER['SERVER_ADDR']);
|
2013-11-17 20:30:04 +01:00
|
|
|
$encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
|
|
|
|
mail($recipientEmail, $encodedSubject, $body, implode("\r\n", $headers), '-f' . $senderEmail);
|
2013-11-16 21:21:43 +01:00
|
|
|
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('Sending e-mail with subject "{subject}" to {mail}', ['subject' => $subject, 'mail' => $recipientEmail]);
|
2013-10-16 18:07:23 +02:00
|
|
|
}
|
|
|
|
|
2013-11-16 16:24:38 +01:00
|
|
|
private static function sendEmailChangeConfirmation($user)
|
|
|
|
{
|
|
|
|
$regConfig = \Chibi\Registry::getConfig()->registration;
|
|
|
|
if (!$regConfig->confirmationEmailEnabled)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user->emailConfirmed = $user->emailUnconfirmed;
|
|
|
|
$user->emailUnconfirmed = null;
|
2013-11-16 16:24:38 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return self::sendTokenizedEmail(
|
|
|
|
$user,
|
|
|
|
$regConfig->confirmationEmailBody,
|
|
|
|
$regConfig->confirmationEmailSubject,
|
|
|
|
$regConfig->confirmationEmailSenderName,
|
|
|
|
$regConfig->confirmationEmailSenderEmail,
|
2013-12-18 15:10:53 +01:00
|
|
|
$user->emailUnconfirmed,
|
2013-11-18 15:41:16 +01:00
|
|
|
'activation');
|
2013-11-16 16:24:38 +01:00
|
|
|
}
|
|
|
|
|
2013-11-16 19:24:33 +01:00
|
|
|
private static function sendPasswordResetConfirmation($user)
|
|
|
|
{
|
|
|
|
$regConfig = \Chibi\Registry::getConfig()->registration;
|
|
|
|
|
|
|
|
return self::sendTokenizedEmail(
|
|
|
|
$user,
|
|
|
|
$regConfig->passwordResetEmailBody,
|
|
|
|
$regConfig->passwordResetEmailSubject,
|
|
|
|
$regConfig->passwordResetEmailSenderName,
|
|
|
|
$regConfig->passwordResetEmailSenderEmail,
|
2013-12-18 15:10:53 +01:00
|
|
|
$user->emailConfirmed,
|
2013-11-18 15:41:16 +01:00
|
|
|
'password-reset');
|
2013-11-16 19:24:33 +01:00
|
|
|
}
|
|
|
|
|
2013-10-14 10:22:53 +02:00
|
|
|
|
|
|
|
|
2013-10-05 19:24:08 +02:00
|
|
|
/**
|
|
|
|
* @route /users
|
2013-10-16 13:07:01 +02:00
|
|
|
* @route /users/{page}
|
|
|
|
* @route /users/{sortStyle}
|
|
|
|
* @route /users/{sortStyle}/{page}
|
|
|
|
* @validate sortStyle alpha|alpha,asc|alpha,desc|date,asc|date,desc|pending
|
|
|
|
* @validate page [0-9]+
|
2013-10-05 19:24:08 +02:00
|
|
|
*/
|
2013-10-16 13:07:01 +02:00
|
|
|
public function listAction($sortStyle, $page)
|
2013-10-05 19:24:08 +02:00
|
|
|
{
|
2013-10-16 13:07:01 +02:00
|
|
|
$this->context->stylesheets []= 'user-list.css';
|
|
|
|
$this->context->stylesheets []= 'paginator.css';
|
2013-10-22 00:17:06 +02:00
|
|
|
if ($this->context->user->hasEnabledEndlessScrolling())
|
2013-10-16 13:07:01 +02:00
|
|
|
$this->context->scripts []= 'paginator-endless.js';
|
|
|
|
|
|
|
|
if ($sortStyle == '' or $sortStyle == 'alpha')
|
|
|
|
$sortStyle = 'alpha,asc';
|
|
|
|
if ($sortStyle == 'date')
|
|
|
|
$sortStyle = 'date,asc';
|
|
|
|
|
2013-10-28 11:19:15 +01:00
|
|
|
$page = intval($page);
|
|
|
|
$usersPerPage = intval($this->config->browsing->usersPerPage);
|
|
|
|
$this->context->subTitle = 'users';
|
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ListUsers);
|
2013-10-16 13:07:01 +02:00
|
|
|
|
2013-11-30 13:59:29 +01:00
|
|
|
$page = max(1, $page);
|
2013-12-18 15:10:53 +01:00
|
|
|
$users = UserSearchService::getEntities($sortStyle, $usersPerPage, $page);
|
|
|
|
$userCount = UserSearchService::getEntityCount($sortStyle, $usersPerPage, $page);
|
2013-10-16 13:07:01 +02:00
|
|
|
$pageCount = ceil($userCount / $usersPerPage);
|
|
|
|
|
|
|
|
$this->context->sortStyle = $sortStyle;
|
|
|
|
$this->context->transport->paginator = new StdClass;
|
|
|
|
$this->context->transport->paginator->page = $page;
|
|
|
|
$this->context->transport->paginator->pageCount = $pageCount;
|
|
|
|
$this->context->transport->paginator->entityCount = $userCount;
|
|
|
|
$this->context->transport->paginator->entities = $users;
|
|
|
|
$this->context->transport->paginator->params = func_get_args();
|
|
|
|
$this->context->transport->users = $users;
|
2013-10-05 19:24:08 +02:00
|
|
|
}
|
|
|
|
|
2013-10-14 10:22:53 +02:00
|
|
|
|
|
|
|
|
2013-11-17 14:52:46 +01:00
|
|
|
/**
|
|
|
|
* @route /user/{name}/flag
|
|
|
|
* @validate name [^\/]+
|
|
|
|
*/
|
|
|
|
public function flagAction($name)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-11-17 14:52:46 +01:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::FlagUser);
|
|
|
|
|
|
|
|
if (InputHelper::get('submit'))
|
|
|
|
{
|
2013-11-17 20:30:04 +01:00
|
|
|
$key = TextHelper::reprUser($user);
|
2013-11-17 14:52:46 +01:00
|
|
|
|
2013-11-17 20:30:04 +01:00
|
|
|
$flagged = SessionHelper::get('flagged', []);
|
|
|
|
if (in_array($key, $flagged))
|
2013-11-17 14:52:46 +01:00
|
|
|
throw new SimpleException('You already flagged this user');
|
2013-11-17 20:30:04 +01:00
|
|
|
$flagged []= $key;
|
|
|
|
SessionHelper::set('flagged', $flagged);
|
2013-11-17 14:52:46 +01:00
|
|
|
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{user} flagged {subject} for moderator attention', ['subject' => TextHelper::reprUser($user)]);
|
2013-11-17 14:52:46 +01:00
|
|
|
StatusHelper::success();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-15 00:41:04 +02:00
|
|
|
/**
|
2013-10-15 13:14:48 +02:00
|
|
|
* @route /user/{name}/ban
|
2013-10-15 00:41:04 +02:00
|
|
|
* @validate name [^\/]+
|
|
|
|
*/
|
2013-10-15 13:14:48 +02:00
|
|
|
public function banAction($name)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-10-18 00:09:50 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::BanUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-11-17 14:52:46 +01:00
|
|
|
|
2013-10-21 23:50:30 +02:00
|
|
|
if (InputHelper::get('submit'))
|
|
|
|
{
|
|
|
|
$user->banned = true;
|
2013-12-18 15:10:53 +01:00
|
|
|
UserModel::save($user);
|
2013-11-17 14:52:46 +01:00
|
|
|
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{user} banned {subject}', ['subject' => TextHelper::reprUser($user)]);
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success();
|
2013-10-21 23:50:30 +02:00
|
|
|
}
|
2013-10-15 13:14:48 +02:00
|
|
|
}
|
|
|
|
|
2013-11-17 14:52:46 +01:00
|
|
|
|
|
|
|
|
2013-10-15 13:14:48 +02:00
|
|
|
/**
|
|
|
|
* @route /post/{name}/unban
|
|
|
|
* @validate name [^\/]+
|
|
|
|
*/
|
|
|
|
public function unbanAction($name)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-10-18 00:09:50 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::BanUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-11-17 14:52:46 +01:00
|
|
|
|
2013-10-21 23:50:30 +02:00
|
|
|
if (InputHelper::get('submit'))
|
|
|
|
{
|
|
|
|
$user->banned = false;
|
2013-12-18 15:10:53 +01:00
|
|
|
UserModel::save($user);
|
2013-11-17 14:52:46 +01:00
|
|
|
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{user} unbanned {subject}', ['subject' => TextHelper::reprUser($user)]);
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success();
|
2013-10-21 23:50:30 +02:00
|
|
|
}
|
2013-10-15 13:14:48 +02:00
|
|
|
}
|
|
|
|
|
2013-11-17 14:52:46 +01:00
|
|
|
|
|
|
|
|
2013-10-15 13:14:48 +02:00
|
|
|
/**
|
|
|
|
* @route /post/{name}/accept-registration
|
|
|
|
* @validate name [^\/]+
|
|
|
|
*/
|
|
|
|
public function acceptRegistrationAction($name)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-10-18 00:09:50 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::AcceptUserRegistration);
|
2013-10-21 23:50:30 +02:00
|
|
|
if (InputHelper::get('submit'))
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user->staffConfirmed = true;
|
|
|
|
UserModel::save($user);
|
2013-11-23 10:39:41 +01:00
|
|
|
LogHelper::log('{user} confirmed {subject}\'s account', ['subject' => TextHelper::reprUser($user)]);
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success();
|
2013-10-21 23:50:30 +02:00
|
|
|
}
|
2013-10-15 13:14:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @route /user/{name}/delete
|
|
|
|
* @validate name [^\/]+
|
|
|
|
*/
|
|
|
|
public function deleteAction($name)
|
2013-10-15 00:41:04 +02:00
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-10-18 00:09:50 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
|
|
|
PrivilegesHelper::confirmWithException(Privilege::DeleteUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-10-15 13:14:48 +02:00
|
|
|
|
2013-11-18 10:30:43 +01:00
|
|
|
$this->loadUserView($user);
|
2013-10-15 13:14:48 +02:00
|
|
|
$this->context->transport->tab = 'delete';
|
2013-10-15 00:41:04 +02:00
|
|
|
|
2013-10-15 20:31:38 +02:00
|
|
|
$this->context->suppliedCurrentPassword = $suppliedCurrentPassword = InputHelper::get('current-password');
|
2013-10-15 13:14:48 +02:00
|
|
|
|
2013-10-21 23:50:30 +02:00
|
|
|
if (InputHelper::get('submit'))
|
2013-10-15 13:14:48 +02:00
|
|
|
{
|
2013-11-16 21:21:43 +01:00
|
|
|
$name = $user->name;
|
2013-10-15 13:14:48 +02:00
|
|
|
if ($this->context->user->id == $user->id)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedPasswordHash = UserModel::hashPassword($suppliedCurrentPassword, $user->passSalt);
|
|
|
|
if ($suppliedPasswordHash != $user->passHash)
|
2013-10-15 13:14:48 +02:00
|
|
|
throw new SimpleException('Must supply valid password');
|
|
|
|
}
|
2013-11-22 21:20:56 +01:00
|
|
|
|
|
|
|
$oldId = $user->id;
|
2013-12-18 15:10:53 +01:00
|
|
|
UserModel::remove($user);
|
2013-11-22 21:20:56 +01:00
|
|
|
if ($oldId == $this->context->user->id)
|
2013-10-27 20:39:32 +01:00
|
|
|
AuthController::doLogOut();
|
2013-11-16 21:21:43 +01:00
|
|
|
|
2013-10-15 13:14:48 +02:00
|
|
|
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index'));
|
2013-11-23 10:39:41 +01:00
|
|
|
LogHelper::log('{user} removed {subject}\'s account', ['subject' => TextHelper::reprUser($name)]);
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success();
|
2013-10-15 13:14:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-22 00:17:06 +02:00
|
|
|
/**
|
|
|
|
* @route /user/{name}/settings
|
|
|
|
* @validate name [^\/]+
|
|
|
|
*/
|
|
|
|
public function settingsAction($name)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-10-22 00:17:06 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-10-25 17:25:05 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ChangeUserSettings, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-10-22 00:17:06 +02:00
|
|
|
|
2013-11-18 10:30:43 +01:00
|
|
|
$this->loadUserView($user);
|
2013-10-22 00:17:06 +02:00
|
|
|
$this->context->transport->tab = 'settings';
|
|
|
|
|
|
|
|
if (InputHelper::get('submit'))
|
|
|
|
{
|
|
|
|
$suppliedSafety = InputHelper::get('safety');
|
|
|
|
if (!is_array($suppliedSafety))
|
|
|
|
$suppliedSafety = [];
|
|
|
|
foreach (PostSafety::getAll() as $safety)
|
|
|
|
$user->enableSafety($safety, in_array($safety, $suppliedSafety));
|
|
|
|
|
|
|
|
$user->enableEndlessScrolling(InputHelper::get('endless-scrolling'));
|
2013-11-25 12:07:50 +01:00
|
|
|
$user->enablePostTagTitles(InputHelper::get('post-tag-titles'));
|
2013-12-05 22:19:21 +01:00
|
|
|
$user->enableHidingDislikedPosts(InputHelper::get('hide-disliked-posts'));
|
2013-10-22 00:17:06 +02:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
if ($user->accessRank != AccessRank::Anonymous)
|
|
|
|
UserModel::save($user);
|
2013-10-28 12:58:18 +01:00
|
|
|
if ($user->id == $this->context->user->id)
|
|
|
|
$this->context->user = $user;
|
2013-10-27 20:39:32 +01:00
|
|
|
AuthController::doReLog();
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success('Browsing settings updated!');
|
2013-10-22 00:17:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-15 13:14:48 +02:00
|
|
|
/**
|
|
|
|
* @route /user/{name}/edit
|
|
|
|
* @validate name [^\/]+
|
|
|
|
*/
|
|
|
|
public function editAction($name)
|
|
|
|
{
|
2013-10-15 20:33:53 +02:00
|
|
|
try
|
2013-10-15 13:14:48 +02:00
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-10-18 00:09:50 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-10-15 20:33:53 +02:00
|
|
|
|
2013-11-18 10:30:43 +01:00
|
|
|
$this->loadUserView($user);
|
2013-10-15 20:33:53 +02:00
|
|
|
$this->context->transport->tab = 'edit';
|
|
|
|
|
|
|
|
$this->context->suppliedCurrentPassword = $suppliedCurrentPassword = InputHelper::get('current-password');
|
|
|
|
$this->context->suppliedName = $suppliedName = InputHelper::get('name');
|
|
|
|
$this->context->suppliedPassword1 = $suppliedPassword1 = InputHelper::get('password1');
|
|
|
|
$this->context->suppliedPassword2 = $suppliedPassword2 = InputHelper::get('password2');
|
|
|
|
$this->context->suppliedEmail = $suppliedEmail = InputHelper::get('email');
|
|
|
|
$this->context->suppliedAccessRank = $suppliedAccessRank = InputHelper::get('access-rank');
|
2013-12-18 15:10:53 +01:00
|
|
|
$currentPasswordHash = $user->passHash;
|
2013-10-15 20:33:53 +02:00
|
|
|
|
2013-10-21 23:50:30 +02:00
|
|
|
if (InputHelper::get('submit'))
|
2013-10-15 20:33:53 +02:00
|
|
|
{
|
2013-11-16 16:24:38 +01:00
|
|
|
$confirmMail = false;
|
2013-11-16 21:21:43 +01:00
|
|
|
LogHelper::bufferChanges();
|
2013-11-16 16:24:38 +01:00
|
|
|
|
2013-10-21 23:50:30 +02:00
|
|
|
if ($suppliedName != '' and $suppliedName != $user->name)
|
|
|
|
{
|
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedName = UserModel::validateUserName($suppliedName);
|
2013-11-16 21:21:43 +01:00
|
|
|
$oldName = $user->name;
|
2013-10-21 23:50:30 +02:00
|
|
|
$user->name = $suppliedName;
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{user} renamed {old} to {new}', ['old' => TextHelper::reprUser($oldName), 'new' => TextHelper::reprUser($suppliedName)]);
|
2013-10-21 23:50:30 +02:00
|
|
|
}
|
2013-10-15 13:14:48 +02:00
|
|
|
|
2013-10-21 23:50:30 +02:00
|
|
|
if ($suppliedPassword1 != '')
|
2013-10-16 18:07:23 +02:00
|
|
|
{
|
2013-10-21 23:50:30 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ChangeUserPassword, PrivilegesHelper::getIdentitySubPrivilege($user));
|
|
|
|
if ($suppliedPassword1 != $suppliedPassword2)
|
|
|
|
throw new SimpleException('Specified passwords must be the same');
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedPassword = UserModel::validatePassword($suppliedPassword1);
|
|
|
|
$user->passHash = UserModel::hashPassword($suppliedPassword, $user->passSalt);
|
2013-11-23 10:39:41 +01:00
|
|
|
LogHelper::log('{user} changed {subject}\'s password', ['subject' => TextHelper::reprUser($user)]);
|
2013-10-16 18:07:23 +02:00
|
|
|
}
|
2013-10-21 23:50:30 +02:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
if ($suppliedEmail != '' and $suppliedEmail != $user->emailConfirmed)
|
2013-10-16 18:07:23 +02:00
|
|
|
{
|
2013-10-21 23:50:30 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ChangeUserEmail, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedEmail = UserModel::validateEmail($suppliedEmail);
|
2013-10-21 23:50:30 +02:00
|
|
|
if ($this->context->user->id == $user->id)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user->emailUnconfirmed = $suppliedEmail;
|
|
|
|
if (!empty($user->emailUnconfirmed))
|
2013-11-16 16:24:38 +01:00
|
|
|
$confirmMail = true;
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{user} changed e-mail to {mail}', ['mail' => $suppliedEmail]);
|
2013-10-21 23:50:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$user->emailUnconfirmed = null;
|
|
|
|
$user->emailConfirmed = $suppliedEmail;
|
2013-11-23 10:39:41 +01:00
|
|
|
LogHelper::log('{user} changed {subject}\'s e-mail to {mail}', ['subject' => TextHelper::reprUser($user), 'mail' => $suppliedEmail]);
|
2013-10-21 23:50:30 +02:00
|
|
|
}
|
2013-10-16 18:07:23 +02:00
|
|
|
}
|
2013-10-15 13:14:48 +02:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
if ($suppliedAccessRank != '' and $suppliedAccessRank != $user->accessRank)
|
2013-10-21 23:50:30 +02:00
|
|
|
{
|
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ChangeUserAccessRank, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedAccessRank = UserModel::validateAccessRank($suppliedAccessRank);
|
|
|
|
$user->accessRank = $suppliedAccessRank;
|
2013-11-23 10:39:41 +01:00
|
|
|
LogHelper::log('{user} changed {subject}\'s access rank to {rank}', ['subject' => TextHelper::reprUser($user), 'rank' => AccessRank::toString($suppliedAccessRank)]);
|
2013-10-21 23:50:30 +02:00
|
|
|
}
|
2013-10-15 20:33:53 +02:00
|
|
|
|
|
|
|
if ($this->context->user->id == $user->id)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedPasswordHash = UserModel::hashPassword($suppliedCurrentPassword, $user->passSalt);
|
2013-10-15 20:33:53 +02:00
|
|
|
if ($suppliedPasswordHash != $currentPasswordHash)
|
|
|
|
throw new SimpleException('Must supply valid current password');
|
|
|
|
}
|
2013-12-18 15:10:53 +01:00
|
|
|
UserModel::save($user);
|
2013-11-16 16:24:38 +01:00
|
|
|
|
|
|
|
if ($confirmMail)
|
|
|
|
self::sendEmailChangeConfirmation($user);
|
|
|
|
|
2013-11-16 21:21:43 +01:00
|
|
|
LogHelper::flush();
|
2013-11-16 18:40:26 +01:00
|
|
|
$message = 'Account settings updated!';
|
|
|
|
if ($confirmMail)
|
2013-11-16 21:21:43 +01:00
|
|
|
$message .= ' You will be sent an e-mail address confirmation message soon.';
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success($message);
|
2013-10-15 20:33:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception $e)
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$this->context->transport->user = UserModel::findByNameOrEmail($name);
|
2013-10-15 20:33:53 +02:00
|
|
|
throw $e;
|
2013-10-15 13:14:48 +02:00
|
|
|
}
|
2013-10-15 00:41:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-05 19:24:08 +02:00
|
|
|
/**
|
2013-12-18 15:10:53 +01:00
|
|
|
* @route /user/{name}/{tab}
|
2013-10-14 10:22:53 +02:00
|
|
|
* @route /user/{name}/{tab}/{page}
|
2013-10-05 19:24:08 +02:00
|
|
|
* @validate name [^\/]+
|
2013-10-14 10:22:53 +02:00
|
|
|
* @validate tab favs|uploads
|
|
|
|
* @validate page \d*
|
2013-10-05 19:24:08 +02:00
|
|
|
*/
|
2013-12-18 15:10:53 +01:00
|
|
|
public function viewAction($name, $tab = 'favs', $page)
|
2013-10-05 19:24:08 +02:00
|
|
|
{
|
2013-10-14 10:22:53 +02:00
|
|
|
$postsPerPage = intval($this->config->browsing->postsPerPage);
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
2013-10-14 10:22:53 +02:00
|
|
|
if ($tab === null)
|
|
|
|
$tab = 'favs';
|
|
|
|
if ($page === null)
|
|
|
|
$page = 1;
|
|
|
|
|
2013-10-18 00:09:50 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
|
2013-11-18 10:30:43 +01:00
|
|
|
$this->loadUserView($user);
|
2013-10-15 13:14:48 +02:00
|
|
|
$this->context->stylesheets []= 'post-list.css';
|
2013-10-19 19:34:15 +02:00
|
|
|
$this->context->stylesheets []= 'post-small.css';
|
2013-10-15 13:14:48 +02:00
|
|
|
$this->context->stylesheets []= 'paginator.css';
|
2013-11-24 21:50:46 +01:00
|
|
|
$this->context->scripts []= 'post-list.js';
|
2013-10-22 00:17:06 +02:00
|
|
|
if ($this->context->user->hasEnabledEndlessScrolling())
|
2013-10-15 13:14:48 +02:00
|
|
|
$this->context->scripts []= 'paginator-endless.js';
|
|
|
|
|
2013-10-28 11:19:15 +01:00
|
|
|
$query = '';
|
|
|
|
if ($tab == 'uploads')
|
|
|
|
$query = 'submit:' . $user->name;
|
|
|
|
elseif ($tab == 'favs')
|
|
|
|
$query = 'fav:' . $user->name;
|
|
|
|
else
|
|
|
|
throw new SimpleException('Wrong tab');
|
2013-10-14 10:22:53 +02:00
|
|
|
|
2013-11-30 13:59:29 +01:00
|
|
|
$page = max(1, $page);
|
2013-12-18 15:10:53 +01:00
|
|
|
$posts = PostSearchService::getEntities($query, $postsPerPage, $page);
|
|
|
|
$postCount = PostSearchService::getEntityCount($query, $postsPerPage, $page);
|
2013-10-14 10:22:53 +02:00
|
|
|
$pageCount = ceil($postCount / $postsPerPage);
|
2013-12-18 15:10:53 +01:00
|
|
|
PostModel::preloadTags($posts);
|
2013-10-14 10:22:53 +02:00
|
|
|
|
|
|
|
$this->context->transport->tab = $tab;
|
2013-11-24 21:50:46 +01:00
|
|
|
$this->context->transport->lastSearchQuery = $query;
|
2013-10-16 13:07:01 +02:00
|
|
|
$this->context->transport->paginator = new StdClass;
|
|
|
|
$this->context->transport->paginator->page = $page;
|
|
|
|
$this->context->transport->paginator->pageCount = $pageCount;
|
|
|
|
$this->context->transport->paginator->entityCount = $postCount;
|
|
|
|
$this->context->transport->paginator->entities = $posts;
|
2013-10-14 10:22:53 +02:00
|
|
|
$this->context->transport->posts = $posts;
|
2013-10-05 19:24:08 +02:00
|
|
|
}
|
2013-10-14 00:25:40 +02:00
|
|
|
|
2013-10-14 10:22:53 +02:00
|
|
|
|
|
|
|
|
2013-10-14 00:25:40 +02:00
|
|
|
/**
|
|
|
|
* @route /user/toggle-safety/{safety}
|
|
|
|
*/
|
|
|
|
public function toggleSafetyAction($safety)
|
|
|
|
{
|
2013-10-25 17:25:05 +02:00
|
|
|
PrivilegesHelper::confirmWithException(Privilege::ChangeUserSettings, PrivilegesHelper::getIdentitySubPrivilege($this->context->user));
|
2013-10-14 00:25:40 +02:00
|
|
|
|
|
|
|
if (!in_array($safety, PostSafety::getAll()))
|
|
|
|
throw new SimpleExcetpion('Invalid safety');
|
|
|
|
|
|
|
|
$this->context->user->enableSafety($safety,
|
|
|
|
!$this->context->user->hasEnabledSafety($safety));
|
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
if ($this->context->user->accessRank != AccessRank::Anonymous)
|
|
|
|
UserModel::save($this->context->user);
|
2013-10-27 20:39:32 +01:00
|
|
|
AuthController::doReLog();
|
2013-10-14 00:25:40 +02:00
|
|
|
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success();
|
2013-10-14 00:25:40 +02:00
|
|
|
}
|
2013-10-16 18:07:23 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @route /register
|
|
|
|
*/
|
|
|
|
public function registrationAction()
|
|
|
|
{
|
|
|
|
$this->context->handleExceptions = true;
|
|
|
|
$this->context->stylesheets []= 'auth.css';
|
|
|
|
$this->context->subTitle = 'registration form';
|
|
|
|
|
|
|
|
//check if already logged in
|
|
|
|
if ($this->context->loggedIn)
|
|
|
|
{
|
|
|
|
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index'));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$suppliedName = InputHelper::get('name');
|
|
|
|
$suppliedPassword1 = InputHelper::get('password1');
|
|
|
|
$suppliedPassword2 = InputHelper::get('password2');
|
|
|
|
$suppliedEmail = InputHelper::get('email');
|
|
|
|
$this->context->suppliedName = $suppliedName;
|
|
|
|
$this->context->suppliedPassword1 = $suppliedPassword1;
|
|
|
|
$this->context->suppliedPassword2 = $suppliedPassword2;
|
|
|
|
$this->context->suppliedEmail = $suppliedEmail;
|
|
|
|
|
2013-10-22 11:40:10 +02:00
|
|
|
if (InputHelper::get('submit'))
|
2013-10-16 18:07:23 +02:00
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedName = UserModel::validateUserName($suppliedName);
|
2013-10-16 18:07:23 +02:00
|
|
|
|
|
|
|
if ($suppliedPassword1 != $suppliedPassword2)
|
|
|
|
throw new SimpleException('Specified passwords must be the same');
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedPassword = UserModel::validatePassword($suppliedPassword1);
|
2013-10-16 18:07:23 +02:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
$suppliedEmail = UserModel::validateEmail($suppliedEmail);
|
2013-10-16 18:07:23 +02:00
|
|
|
if (empty($suppliedEmail) and $this->config->registration->needEmailForRegistering)
|
|
|
|
throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.');
|
|
|
|
|
|
|
|
//register the user
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbUser = UserModel::spawn();
|
2013-10-16 18:07:23 +02:00
|
|
|
$dbUser->name = $suppliedName;
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbUser->passHash = UserModel::hashPassword($suppliedPassword, $dbUser->passSalt);
|
|
|
|
$dbUser->emailUnconfirmed = $suppliedEmail;
|
2013-10-16 18:07:23 +02:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbUser->joinDate = time();
|
|
|
|
if (UserModel::getCount() == 0)
|
2013-10-16 18:07:23 +02:00
|
|
|
{
|
2013-11-16 16:24:38 +01:00
|
|
|
//very first user
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbUser->accessRank = AccessRank::Admin;
|
|
|
|
$dbUser->staffConfirmed = true;
|
|
|
|
$dbUser->emailUnconfirmed = null;
|
|
|
|
$dbUser->emailConfirmed = $suppliedEmail;
|
2013-10-16 18:07:23 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbUser->accessRank = AccessRank::Registered;
|
|
|
|
$dbUser->staffConfirmed = false;
|
|
|
|
$dbUser->staffConfirmed = null;
|
2013-10-16 18:07:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//save the user to db if everything went okay
|
2013-12-18 15:10:53 +01:00
|
|
|
UserModel::save($dbUser);
|
2013-11-16 16:24:38 +01:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
if (!empty($dbUser->emailUnconfirmed))
|
2013-11-16 16:24:38 +01:00
|
|
|
self::sendEmailChangeConfirmation($dbUser);
|
|
|
|
|
2013-11-16 18:40:26 +01:00
|
|
|
$message = 'Congratulations, your account was created.';
|
|
|
|
if (!empty($this->context->mailSent))
|
|
|
|
{
|
|
|
|
$message .= ' Please wait for activation e-mail.';
|
|
|
|
if ($this->config->registration->staffActivation)
|
|
|
|
$message .= ' After this, your registration must be confirmed by staff.';
|
|
|
|
}
|
|
|
|
elseif ($this->config->registration->staffActivation)
|
|
|
|
$message .= ' Your registration must be now confirmed by staff.';
|
|
|
|
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{subject} just signed up', ['subject' => TextHelper::reprUser($dbUser)]);
|
2013-11-16 18:40:26 +01:00
|
|
|
StatusHelper::success($message);
|
2013-10-16 18:07:23 +02:00
|
|
|
|
|
|
|
if (!$this->config->registration->needEmailForRegistering and !$this->config->registration->staffActivation)
|
|
|
|
{
|
2013-10-27 20:39:32 +01:00
|
|
|
$this->context->user = $dbUser;
|
|
|
|
AuthController::doReLog();
|
2013-10-16 18:07:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @route /activation/{token}
|
|
|
|
*/
|
|
|
|
public function activationAction($token)
|
|
|
|
{
|
|
|
|
$this->context->subTitle = 'account activation';
|
2013-11-16 18:40:26 +01:00
|
|
|
$this->context->viewName = 'message';
|
2013-10-16 18:07:23 +02:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbToken = TokenModel::findByToken($token);
|
|
|
|
TokenModel::checkValidity($dbToken);
|
2013-11-16 16:24:38 +01:00
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbUser = $dbToken->getUser();
|
|
|
|
$dbUser->emailConfirmed = $dbUser->emailUnconfirmed;
|
|
|
|
$dbUser->emailUnconfirmed = null;
|
2013-11-16 16:24:38 +01:00
|
|
|
$dbToken->used = true;
|
2013-12-18 15:10:53 +01:00
|
|
|
TokenModel::save($dbToken);
|
|
|
|
UserModel::save($dbUser);
|
2013-11-16 18:40:26 +01:00
|
|
|
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{subject} just activated account', ['subject' => TextHelper::reprUser($dbUser)]);
|
2013-11-16 18:40:26 +01:00
|
|
|
$message = 'Activation completed successfully.';
|
|
|
|
if ($this->config->registration->staffActivation)
|
|
|
|
$message .= ' However, your account still must be confirmed by staff.';
|
|
|
|
StatusHelper::success($message);
|
2013-10-16 18:07:23 +02:00
|
|
|
|
|
|
|
if (!$this->config->registration->staffActivation)
|
|
|
|
{
|
2013-10-27 20:39:32 +01:00
|
|
|
$this->context->user = $dbUser;
|
|
|
|
AuthController::doReLog();
|
2013-10-16 18:07:23 +02:00
|
|
|
}
|
|
|
|
}
|
2013-11-16 18:51:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2013-11-16 19:24:33 +01:00
|
|
|
* @route /password-reset/{token}
|
2013-11-16 18:51:34 +01:00
|
|
|
*/
|
2013-11-16 19:24:33 +01:00
|
|
|
public function passwordResetAction($token)
|
2013-11-16 18:51:34 +01:00
|
|
|
{
|
2013-11-16 19:24:33 +01:00
|
|
|
$this->context->subTitle = 'password reset';
|
|
|
|
$this->context->viewName = 'message';
|
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbToken = TokenModel::findByToken($token);
|
|
|
|
TokenModel::checkValidity($dbToken);
|
2013-11-16 19:24:33 +01:00
|
|
|
|
|
|
|
$alphabet = array_merge(range('A', 'Z'), range('a', 'z'), range('0', '9'));
|
|
|
|
$randomPassword = join('', array_map(function($x) use ($alphabet)
|
|
|
|
{
|
|
|
|
return $alphabet[$x];
|
|
|
|
}, array_rand($alphabet, 8)));
|
|
|
|
|
2013-12-18 15:10:53 +01:00
|
|
|
$dbUser = $dbToken->getUser();
|
|
|
|
$dbUser->passHash = UserModel::hashPassword($randomPassword, $dbUser->passSalt);
|
2013-11-16 19:24:33 +01:00
|
|
|
$dbToken->used = true;
|
2013-12-18 15:10:53 +01:00
|
|
|
TokenModel::save($dbToken);
|
|
|
|
UserModel::save($dbUser);
|
2013-11-16 19:24:33 +01:00
|
|
|
|
2013-11-22 23:32:56 +01:00
|
|
|
LogHelper::log('{subject} just reset password', ['subject' => TextHelper::reprUser($dbUser)]);
|
2013-11-17 20:30:04 +01:00
|
|
|
$message = 'Password reset successful. Your new password is **' . $randomPassword . '**.';
|
2013-11-16 19:24:33 +01:00
|
|
|
StatusHelper::success($message);
|
2013-11-16 18:51:34 +01:00
|
|
|
|
2013-11-16 19:24:33 +01:00
|
|
|
$this->context->user = $dbUser;
|
|
|
|
AuthController::doReLog();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @route /password-reset-proxy
|
|
|
|
*/
|
|
|
|
public function passwordResetProxyAction()
|
|
|
|
{
|
|
|
|
$this->context->subTtile = 'password reset';
|
|
|
|
$this->context->viewName = 'user-select';
|
2013-11-16 18:51:34 +01:00
|
|
|
$this->context->stylesheets []= 'auth.css';
|
2013-11-16 19:24:33 +01:00
|
|
|
|
|
|
|
if (InputHelper::get('submit'))
|
|
|
|
{
|
|
|
|
$name = InputHelper::get('name');
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
|
|
|
if (empty($user->emailConfirmed))
|
2013-11-16 19:24:33 +01:00
|
|
|
throw new SimpleException('This user has no e-mail confirmed; password reset cannot proceed');
|
|
|
|
|
|
|
|
self::sendPasswordResetConfirmation($user);
|
|
|
|
StatusHelper::success('E-mail sent. Follow instructions to reset password.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @route /activation-proxy
|
|
|
|
*/
|
|
|
|
public function activationProxyAction()
|
|
|
|
{
|
|
|
|
$this->context->subTitle = 'account activation';
|
2013-11-16 18:51:34 +01:00
|
|
|
$this->context->viewName = 'user-select';
|
2013-11-16 19:24:33 +01:00
|
|
|
$this->context->stylesheets []= 'auth.css';
|
|
|
|
|
2013-11-16 18:51:34 +01:00
|
|
|
if (InputHelper::get('submit'))
|
|
|
|
{
|
|
|
|
$name = InputHelper::get('name');
|
2013-12-18 15:10:53 +01:00
|
|
|
$user = UserModel::findByNameOrEmail($name);
|
|
|
|
if (empty($user->emailUnconfirmed))
|
2013-11-16 18:51:34 +01:00
|
|
|
{
|
2013-12-18 15:10:53 +01:00
|
|
|
if (!empty($user->emailConfirmed))
|
2013-11-16 18:51:34 +01:00
|
|
|
throw new SimpleException('E-mail was already confirmed; activation skipped');
|
|
|
|
else
|
|
|
|
throw new SimpleException('This user has no e-mail specified; activation cannot proceed');
|
|
|
|
}
|
|
|
|
self::sendEmailChangeConfirmation($user);
|
|
|
|
StatusHelper::success('Activation e-mail resent.');
|
|
|
|
}
|
|
|
|
}
|
2013-10-05 19:24:08 +02:00
|
|
|
}
|