Closed #1; closed #2; closed #4; closed #27

This commit is contained in:
Marcin Kurczewski 2013-10-15 13:14:48 +02:00
parent 8fdc90bab7
commit 17013e8fe5
16 changed files with 483 additions and 201 deletions

View file

@ -68,7 +68,10 @@ changeUserEmail.all=admin
changeUserAccessRank=admin
changeUserName=moderator
acceptUserRegistration=moderator
banUser=admin
banUser.own=nobody
banUser.all=admin
deleteUser.own=registered
deleteUser.all=nobody
listComments=anonymous
listTags=anonymous

View file

@ -101,6 +101,15 @@ body {
border: 0;
}
footer {
text-align: center;
margin-top: 1em;
padding-top: 0.5em;
border-top: 1px solid #eee;
font-size: small;
color: silver;
}
.clear {
display: block;
clear: both;
@ -111,7 +120,6 @@ body {
width: 256px;
margin-right: 2em;
}
#sidebar .sidebar-unit {
margin: 0 0 1.5em 0;
padding: 0.75em;
@ -119,24 +127,40 @@ body {
padding-left: 0;
border-left: 0;
}
#sidebar h1 {
margin-top: 0;
}
h1, h2, h3 {
font-weight: normal;
#sidebar .key {
padding-right: 0.5em;
}
#sidebar .key-value {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#inner-content {
overflow: hidden;
}
h1, h2, h3 {
font-weight: normal;
}
p:first-child,
h1:first-child {
margin-top: 0;
}
hr {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAIElEQVQYlWNgQAPv3r37j4wHXBJdATY5BnyScAX4TAUAdfp5IbOdz/YAAAAASUVORK5CYII=');
border: 0;
height: 4px;
}
a {
color: firebrick;
text-decoration: none;
@ -202,7 +226,6 @@ form.aligned input[type=checkbox] {
label {
display: inline-block;
}
label,
input,
select,
@ -210,9 +233,13 @@ button {
font-family: inherit;
font-size: 11pt;
}
input:not([type=radio], [type=checkbox], [type=file]) {
select,
input:not([type=radio]):not([type=checkbox]):not([type=file]) {
border: 1px solid #ccc;
}
ul.tagit input {
border: 0 !important;
}
button {
font-size: 115%;
padding: 0.2em 0.7em;
@ -235,6 +262,10 @@ button:hover {
margin: 0 auto;
}
.alert-success {
border-color: #aba;
background-color: #aea;
}
.alert-error {
border-color: #faa;
background-color: #fdd;
@ -245,21 +276,6 @@ button:hover {
background-color: #ffd;
}
footer {
text-align: center;
margin-top: 1em;
padding-top: 0.5em;
border-top: 1px solid #eee;
font-size: small;
color: silver;
}
.inactive {
opacity: .5;
}
hr {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAIElEQVQYlWNgQAPv3r37j4wHXBJdATY5BnyScAX4TAUAdfp5IbOdz/YAAAAASUVORK5CYII=');
border: 0;
height: 4px;
}

View file

@ -69,10 +69,6 @@ i.icon-dl {
content: ', ';
}
.details .key {
margin-right: 0.5em;
}
.options ul {
list-style-type: none;
margin: 0;

View file

@ -1,16 +1,13 @@
#sidebar {
width: 200px;
}
.details .key {
margin-right: 0.5em;
font-size: 90%;
}
.tabs ul {
list-style-type: none;
margin: 0 0 1em 0;
padding: 0;
border-bottom: 1px solid #eee;
border-bottom: 1px solid #ccc;
}
.tabs li {
display: inline-block;
@ -24,11 +21,11 @@
.tabs li a {
border: 1px solid white;
border-bottom: 1px solid #eee;
border-bottom: 1px solid #ccc;
color: silver;
}
.tabs li.selected a {
border: 1px solid #eee;
border: 1px solid #ccc;
border-bottom: 1px solid white;
color: inherit;
}
@ -46,3 +43,7 @@
form.aligned label.left {
width: 10em;
}
form.edit .alert {
margin: 1em 0;
}

View file

@ -1,3 +1,7 @@
$.fn.hasAttr = function(name) {
return this.attr(name) !== undefined;
};
if ($.when.all === undefined)
{
$.when.all = function(deferreds)
@ -39,4 +43,46 @@ $(function()
}
});
});
function confirmEvent(e)
{
if (!confirm($(this).attr('data-confirm-text')))
{
e.preventDefault();
e.stopPropagation();
}
}
$('form[data-confirm-text]').submit(confirmEvent);
$('a[data-confirm-text]').click(confirmEvent);
$('a.simple-action').click(function(e)
{
if(e.isPropagationStopped())
return;
e.preventDefault();
var aDom = $(this);
if (aDom.hasClass('inactive'))
return;
aDom.addClass('inactive');
var url = $(this).attr('href') + '?json';
$.get(url, function(data)
{
if (data['success'])
{
if (aDom.hasAttr('data-redirect-url'))
window.location.href = aDom.attr('data-redirect-url');
else
window.location.reload();
}
else
{
alert(data['errorMessage']);
aDom.removeClass('inactive');
}
});
});
});

View file

@ -1,61 +1,5 @@
$(function()
{
$('.add-fav a, .rem-fav a, .hide a, .unhide a').click(function(e)
{
e.preventDefault();
var aDom = $(this);
if (aDom.hasClass('inactive'))
return;
aDom.addClass('inactive');
var url = $(this).attr('href') + '?json';
$.get(url, function(data)
{
if (data['success'])
{
window.location.reload();
}
else
{
alert(data['errorMessage']);
aDom.removeClass('inactive');
}
});
});
$('.delete a').click(function(e)
{
e.preventDefault();
var aDom = $(this);
if (aDom.hasClass('inactive'))
return;
aDom.addClass('inactive');
//todo: move this string literal to html
if (confirm(aDom.attr('data-confirm-text')))
{
var url = $(this).attr('href') + '?json';
$.get(url, function(data)
{
if (data['success'])
{
window.location.href = aDom.attr('data-redirect-url');
}
else
{
alert(data['errorMessage']);
aDom.removeClass('inactive');
}
});
}
else
{
aDom.removeClass('inactive');
}
});
$('li.edit a').click(function(e)
{
e.preventDefault();

View file

@ -1,12 +1,6 @@
<?php
class AuthController
{
private static function hashPassword($pass, $salt2)
{
$salt1 = \Chibi\Registry::getConfig()->registration->salt;
return sha1($salt1 . $salt2 . $pass);
}
/**
* @route /auth/login
*/
@ -23,21 +17,24 @@ class AuthController
return;
}
$suppliedUser = InputHelper::get('user');
$suppliedPass = InputHelper::get('pass');
if ($suppliedUser !== null and $suppliedPass !== null)
$suppliedName = InputHelper::get('name');
$suppliedPassword = InputHelper::get('password');
if ($suppliedName !== null and $suppliedPassword !== null)
{
$dbUser = R::findOne('user', 'name = ?', [$suppliedUser]);
$dbUser = R::findOne('user', 'name = ?', [$suppliedName]);
if ($dbUser === null)
throw new SimpleException('Invalid username');
$suppliedPassHash = self::hashPassword($suppliedPass, $dbUser->pass_salt);
if ($suppliedPassHash != $dbUser->pass_hash)
$suppliedPasswordHash = Model_User::hashPassword($suppliedPassword, $dbUser->pass_salt);
if ($suppliedPasswordHash != $dbUser->pass_hash)
throw new SimpleException('Invalid password');
if (!$dbUser->staff_confirmed and $this->config->registration->staffActivation)
throw new SimpleException('Staff hasn\'t confirmed your registration yet');
if ($dbUser->banned)
throw new SimpleException('You are banned');
if (!$dbUser->email_confirmed and $this->config->registration->emailActivation)
throw new SimpleException('You haven\'t confirmed your e-mail address yet');
@ -74,72 +71,53 @@ class AuthController
return;
}
$suppliedUser = InputHelper::get('user');
$suppliedPass1 = InputHelper::get('pass1');
$suppliedPass2 = InputHelper::get('pass2');
$suppliedName = InputHelper::get('name');
$suppliedPassword1 = InputHelper::get('password1');
$suppliedPassword2 = InputHelper::get('password2');
$suppliedEmail = InputHelper::get('email');
$this->context->suppliedUser = $suppliedUser;
$this->context->suppliedPass1 = $suppliedPass1;
$this->context->suppliedPass2 = $suppliedPass2;
$this->context->suppliedName = $suppliedName;
$this->context->suppliedPassword1 = $suppliedPassword1;
$this->context->suppliedPassword2 = $suppliedPassword2;
$this->context->suppliedEmail = $suppliedEmail;
$regConfig = $this->config->registration;
$passMinLength = intval($regConfig->passMinLength);
$passRegex = $regConfig->passRegex;
$userNameMinLength = intval($regConfig->userNameMinLength);
$userNameRegex = $regConfig->userNameRegex;
$emailActivation = $regConfig->emailActivation;
$staffActivation = $regConfig->staffActivation;
$this->context->transport->staffActivation = $staffActivation;
$this->context->transport->emailActivation = $emailActivation;
if ($suppliedUser !== null)
if ($suppliedName !== null)
{
$dbUser = R::findOne('user', 'name = ?', [$suppliedUser]);
if ($dbUser !== null)
{
if (!$dbUser->email_confirmed)
throw new SimpleException('User with this name is already registered and awaits e-mail confirmation');
$suppliedName = Model_User::validateUserName($suppliedName);
if (!$dbUser->staff_confirmed)
throw new SimpleException('User with this name is already registered and awaits admin confirmation');
throw new SimpleException('User with this name is already registered');
}
if (strlen($suppliedUser) < $userNameMinLength)
throw new SimpleException(sprintf('User name must have at least %d characters', $userNameMinLength));
if (!preg_match($userNameRegex, $suppliedUser))
throw new SimpleException('User name contains invalid characters');
if ($suppliedPass1 != $suppliedPass2)
if ($suppliedPassword1 != $suppliedPassword2)
throw new SimpleException('Specified passwords must be the same');
$suppliedPassword = Model_User::validatePassword($suppliedPassword1);
if (strlen($suppliedPass1) < $passMinLength)
throw new SimpleException(sprintf('Password must have at least %d characters', $passMinLength));
if (!preg_match($passRegex, $suppliedPass1))
throw new SimpleException('Password contains invalid characters');
$suppliedEmail = Model_User::validateEmail($suppliedEmail);
if (empty($suppliedEmail) and $emailActivation)
throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.');
if (!empty($suppliedEmail) and !TextHelper::isValidEmail($suppliedEmail))
throw new SimpleException('E-mail address appears to be invalid');
//register the user
$dbUser = R::dispense('user');
$dbUser->name = $suppliedUser;
$dbUser->name = $suppliedName;
$dbUser->pass_salt = md5(mt_rand() . uniqid());
$dbUser->pass_hash = self::hashPassword($suppliedPass1, $dbUser->pass_salt);
$dbUser->pass_hash = Model_User::hashPassword($suppliedPassword, $dbUser->pass_salt);
$dbUser->email = $suppliedEmail;
$dbUser->join_date = time();
$dbUser->staff_confirmed = $staffActivation ? false : true;
$dbUser->email_confirmed = $emailActivation ? false : true;
$dbUser->access_rank = R::findOne('user') === null ? AccessRank::Admin : AccessRank::Registered;
if (R::findOne('user') === null)
{
$dbUser->staff_confirmed = true;
$dbUser->email_confirmed = true;
$dbUser->access_rank = AccessRank::Admin;
}
else
{
$dbUser->staff_confirmed = false;
$dbUser->email_confirmed = false;
$dbUser->access_rank = AccessRank::Registered;
}
//prepare unique registration token
do

View file

@ -414,6 +414,7 @@ class PostController
$edited = false;
$secondary = $post->uploader->id == $this->context->user->id ? 'own' : 'all';
$this->context->transport->post = $post;
/* safety */
$suppliedSafety = InputHelper::get('safety');

View file

@ -22,20 +22,160 @@ class UserController
/**
* @route /user/{name}/ban
* @validate name [^\/]+
*/
public function banAction($name)
{
$user = self::locateUser($name);
$secondary = $user->id == $this->context->user->id ? 'own' : 'all';
PrivilegesHelper::confirmWithException($this->context->user, Privilege::BanUser, $secondary);
$user->banned = true;
R::store($user);
$this->context->transport->success = true;
}
/**
* @route /post/{name}/unban
* @validate name [^\/]+
*/
public function unbanAction($name)
{
$user = self::locateUser($name);
$secondary = $user->id == $this->context->user->id ? 'own' : 'all';
PrivilegesHelper::confirmWithException($this->context->user, Privilege::BanUser, $secondary);
$user->banned = false;
R::store($user);
$this->context->transport->success = true;
}
/**
* @route /post/{name}/accept-registration
* @validate name [^\/]+
*/
public function acceptRegistrationAction($name)
{
$user = self::locateUser($name);
PrivilegesHelper::confirmWithException($this->context->user, Privilege::AcceptUserRegistration);
$user->staff_confirmed = true;
R::store($user);
$this->context->transport->success = true;
}
/**
* @route /user/{name}/delete
* @validate name [^\/]+
*/
public function deleteAction($name)
{
$user = self::locateUser($name);
$secondary = $user->id == $this->context->user->id ? 'own' : 'all';
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewUser, $secondary);
PrivilegesHelper::confirmWithException($this->context->user, Privilege::DeleteUser, $secondary);
$this->context->handleExceptions = true;
$this->context->transport->user = $user;
$this->context->transport->tab = 'delete';
$this->context->viewName = 'user-view';
$this->context->stylesheets []= 'user-view.css';
$this->context->subTitle = $name;
$this->context->suppliedOldPassword = $suppliedOldPassword = InputHelper::get('old-password');
if (InputHelper::get('remove'))
{
if ($this->context->user->id == $user->id)
{
$suppliedPasswordHash = Model_User::hashPassword($suppliedOldPassword, $user->pass_salt);
if ($suppliedPasswordHash != $user->pass_hash)
throw new SimpleException('Must supply valid password');
}
$user->ownFavoritee = [];
R::store($user);
#R::trashAll(R::findAll('favoritee', 'user_id = ?', [$user->id]));
R::trash($user);
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index'));
$this->context->transport->success = true;
}
}
/**
* @route /user/{name}/edit
* @validate name [^\/]+
*/
public function editAction($name)
{
$user = self::locateUser($name);
$edited = false;
$secondary = $user->id == $this->context->user->id ? 'own' : 'all';
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewUser, $secondary);
$this->context->handleExceptions = true;
$this->context->transport->user = $user;
$this->context->transport->tab = 'edit';
$this->context->viewName = 'user-view';
$this->context->stylesheets []= 'user-view.css';
$this->context->subTitle = $name;
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewUser);
$user = self::locateUser($name);
$this->context->transport->user = $user;
$this->context->transport->tab = 'edit';
$this->context->suppliedOldPassword = $suppliedOldPassword = InputHelper::get('old-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');
$oldPasswordHash = $user->pass_hash;
if ($suppliedName != '' and $suppliedName != $user->name)
{
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ChangeUserName, $secondary);
$suppliedName = Model_User::validateUserName($suppliedName);
$user->name = $suppliedName;
$edited = true;
}
if ($suppliedPassword1 != '')
{
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ChangeUserPassword, $secondary);
if ($suppliedPassword1 != $suppliedPassword2)
throw new SimpleException('Specified passwords must be the same');
$suppliedPassword = Model_User::validatePassword($suppliedPassword1);
$user->pass_hash = Model_User::hashPassword($suppliedPassword, $user->pass_salt);
$edited = true;
}
if ($suppliedEmail != '' and $suppliedEmail != $user->email)
{
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ChangeUserEmail, $secondary);
$suppliedEmail = Model_User::validateEmail($suppliedEmail);
$user->email = $suppliedEmail;
$edited = true;
}
if ($suppliedAccessRank != '' and $suppliedAccessRank != $user->access_rank)
{
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ChangeUserAccessRank, $secondary);
$suppliedAccessRank = Model_User::validateAccessRank($suppliedAccessRank);
$user->access_rank = $suppliedAccessRank;
$edited = true;
}
if ($edited)
{
if ($this->context->user->id == $user->id)
{
$suppliedPasswordHash = Model_User::hashPassword($suppliedOldPassword, $user->pass_salt);
if ($suppliedPasswordHash != $oldPasswordHash)
throw new SimpleException('Must supply valid old password');
}
R::store($user);
$this->context->transport->success = true;
}
}
@ -49,14 +189,6 @@ class UserController
*/
public function viewAction($name, $tab, $page)
{
$this->context->stylesheets []= 'user-view.css';
$this->context->stylesheets []= 'post-list.css';
$this->context->stylesheets []= 'paginator.css';
if ($this->config->browsing->endlessScrolling)
$this->context->scripts []= 'paginator-endless.js';
$this->context->subTitle = $name;
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewUser);
$postsPerPage = intval($this->config->browsing->postsPerPage);
$user = self::locateUser($name);
if ($tab === null)
@ -64,6 +196,15 @@ class UserController
if ($page === null)
$page = 1;
$secondary = $user->id == $this->context->user->id ? 'own' : 'all';
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewUser, $secondary);
$this->context->stylesheets []= 'user-view.css';
$this->context->stylesheets []= 'post-list.css';
$this->context->stylesheets []= 'paginator.css';
if ($this->config->browsing->endlessScrolling)
$this->context->scripts []= 'paginator-endless.js';
$this->context->subTitle = $name;
$buildDbQuery = function($dbQuery, $user, $tab)
{
$dbQuery->from('post');

View file

@ -51,4 +51,73 @@ class Model_User extends RedBean_SimpleModel
$this->setSetting('safety-' . $safety, true);
}
}
public static function validateUserName($userName)
{
$userName = trim($userName);
$dbUser = R::findOne('user', 'name = ?', [$userName]);
if ($dbUser !== null)
{
if (!$dbUser->email_confirmed and \Chibi\Registry::getConfig()->registration->emailActivation)
throw new SimpleException('User with this name is already registered and awaits e-mail confirmation');
if (!$dbUser->staff_confirmed and \Chibi\Registry::getConfig()->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');
}
$userNameMinLength = intval(\Chibi\Registry::getConfig()->registration->userNameMinLength);
$userNameRegex = \Chibi\Registry::getConfig()->registration->userNameRegex;
if (strlen($userName) < $userNameMinLength)
throw new SimpleException(sprintf('User name must have at least %d characters', $userNameMinLength));
if (!preg_match($userNameRegex, $userName))
throw new SimpleException('User name contains invalid characters');
return $userName;
}
public static function validatePassword($password)
{
$passMinLength = intval(\Chibi\Registry::getConfig()->registration->passMinLength);
$passRegex = \Chibi\Registry::getConfig()->registration->passRegex;
if (strlen($password) < $passMinLength)
throw new SimpleException(sprintf('Password must have at least %d characters', $passMinLength));
if (!preg_match($passRegex, $password))
throw new SimpleException('Password contains invalid characters');
return $password;
}
public static function validateEmail($email)
{
$email = trim($email);
if (!empty($email) and !TextHelper::isValidEmail($email))
throw new SimpleException('E-mail address appears to be invalid');
return $email;
}
public static function validateAccessRank($accessRank)
{
$accessRank = intval($accessRank);
if (!in_array($accessRank, AccessRank::getAll()))
throw new SimpleException('Invalid access rank type "' . $accessRank . '"');
return $accessRank;
}
public static function hashPassword($pass, $salt2)
{
$salt1 = \Chibi\Registry::getConfig()->registration->salt;
return sha1($salt1 . $salt2 . $pass);
}
}

View file

@ -20,7 +20,8 @@ class Privilege extends Enum
const ChangeUserAccessRank = 16;
const ChangeUserEmail = 17;
const ChangeUserName = 18;
const DeleteUser = 19;
const ListComments = 19;
const ListTags = 20;
const ListComments = 20;
const ListTags = 21;
}

View file

@ -5,13 +5,13 @@
</div>
<div>
<label class="left" for="user">User name:</label>
<input id="user" name="user"/>
<label class="left" for="name">User name:</label>
<input id="name" name="name"/>
</div>
<div>
<label class="left" for="pass">Password:</label>
<input type="password" id="pass" name="pass"/>
<label class="left" for="password">Password:</label>
<input type="password" id="password" name="password"/>
</div>
<?php if (isset($this->context->transport->errorMessage)): ?>

View file

@ -15,18 +15,18 @@
</div>
<div>
<label class="left" for="user">User name:</label>
<input id="user" name="user" value="<?php echo $this->context->suppliedUser ?>" placeholder="e.g. darth_vader" autocomplete="off"/>
<label class="left" for="name">User name:</label>
<input id="name" name="name" value="<?php echo $this->context->suppliedName ?>" placeholder="e.g. darth_vader" autocomplete="off"/>
</div>
<div>
<label class="left" for="pass1">Password:</label>
<input type="password" id="pass1" name="pass1" value="<?php echo $this->context->suppliedPass1 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>" autocomplete="off"/>
<label class="left" for="password1">Password:</label>
<input type="password" id="password1" name="password1" value="<?php echo $this->context->suppliedPassword1 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>" autocomplete="off"/>
</div>
<div>
<label class="left" for="pass2">Password (repeat):</label>
<input type="password" id="pass2" name="pass2" value="<?php echo $this->context->suppliedPass2 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>" autocomplete="off"/>
<label class="left" for="password2">Password (repeat):</label>
<input type="password" id="password2" name="password2" value="<?php echo $this->context->suppliedPassword2 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>" autocomplete="off"/>
</div>
<div>

View file

@ -44,31 +44,43 @@
<div class="sidebar-unit details">
<h1>details</h1>
<div class="safety">
<div class="key-value safety">
<span class="key">Safety:</span>
<span class="value"><?php echo PostSafety::toString($this->context->transport->post->safety) ?></span>
</div>
<div class="uploader">
<span class="key">Uploader:</span>
<span class="value">
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->transport->post->uploader->name]) ?>">
<?php echo $this->context->transport->post->uploader->name ?>
</a>
<span class="value" title="<?php echo $val = PostSafety::toString($this->context->transport->post->safety) ?>">
<?php echo $val ?>
</span>
</div>
<div class="date">
<div class="key-value uploader">
<span class="key">Uploader:</span>
<?php if ($this->context->transport->post->uploader->id): ?>
<span class="value" title="<?php echo $val = $this->context->transport->post->uploader->name ?>">
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->transport->post->uploader->name]) ?>">
<?php echo $val ?>
</a>
</span>
<?php else: ?>
<span class="value" title="[deleted user]">
[deleted user]
</span>
<?php endif ?>
</div>
<div class="key-value date">
<span class="key">Date:</span>
<span class="value"><?php echo date('Y-m-d H:i', $this->context->transport->post->upload_date) ?></span>
<span class="value" title="<?php echo $val = date('Y-m-d H:i', $this->context->transport->post->upload_date) ?>">
<?php echo $val ?>
</span>
</div>
<?php if ($this->context->transport->post->image_width > 0): ?>
<div class="dim">
<div class="key-value dim">
<span class="key">Dimensions:</span>
<span class="value"><?php printf('%dx%d',
<span class="value" title="<?php echo $val = sprintf('%dx%d',
$this->context->transport->post->image_width,
$this->context->transport->post->image_height) ?></span>
$this->context->transport->post->image_height) ?>">
<?php echo $val ?>
</span>
</div>
<?php endif ?>
@ -110,13 +122,13 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::FavoritePost)): ?>
<?php if (!$this->context->favorite): ?>
<li class="add-fav">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'add-favorite', ['id' => $this->context->transport->post->id]) ?>">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('post', 'add-favorite', ['id' => $this->context->transport->post->id]) ?>">
Add to favorites
</a>
</li>
<?php else: ?>
<li class="rem-fav">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'rem-favorite', ['id' => $this->context->transport->post->id]) ?>">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('post', 'rem-favorite', ['id' => $this->context->transport->post->id]) ?>">
Remove from favorites
</a>
</li>
@ -150,13 +162,13 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::HidePost, $secondary)): ?>
<?php if ($this->context->transport->post->hidden): ?>
<li class="unhide">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'unhide', ['id' => $this->context->transport->post->id]) ?>">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('post', 'unhide', ['id' => $this->context->transport->post->id]) ?>">
Unhide
</a>
</li>
<?php else: ?>
<li class="hide">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'hide', ['id' => $this->context->transport->post->id]) ?>">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('post', 'hide', ['id' => $this->context->transport->post->id]) ?>">
Hide
</a>
</li>
@ -165,7 +177,7 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::DeletePost, $secondary)): ?>
<li class="delete">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'delete', ['id' => $this->context->transport->post->id]) ?>" data-confirm-text="Are you sure?" data-redirect-url="<?php echo \Chibi\UrlHelper::route('post', 'list') ?>">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('post', 'delete', ['id' => $this->context->transport->post->id]) ?>" data-confirm-text="Are you sure?" data-redirect-url="<?php echo \Chibi\UrlHelper::route('post', 'list') ?>">
Delete
</a>
</li>

View file

@ -9,15 +9,23 @@
<div class="sidebar-unit details">
<h1>details</h1>
<div class="join-date">
<div class="key-value join-date">
<span class="key">Joined:</span>
<span class="value"><?php echo date('Y-m-d', $this->context->transport->user->join_date) ?></span>
<span class="value" title="<?php echo $val = date('Y-m-d', $this->context->transport->user->join_date) ?>"><?php echo $val ?></span>
</div>
<div class="access-rank">
<div class="key-value access-rank">
<span class="key">Access rank:</span>
<span class="value"><?php echo strtolower(AccessRank::toString($this->context->transport->user->access_rank)) ?></span>
<span class="value" title="<?php echo $val = strtolower(AccessRank::toString($this->context->transport->user->access_rank)) ?>"><?php echo $val ?></span>
</div>
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
<div class="key-value email">
<span class="key">E-mail:</span>
<span class="value" title="<?php echo $val = ($this->context->transport->user->email ?: 'none specified') ?>"><?php echo $val ?></span>
<br>(only you can see this)
</div>
<?php endif ?>
</div>
<div class="sidebar-unit options">
@ -50,6 +58,29 @@
</li>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::BanUser, $secondary)): ?>
<?php if (!$this->context->transport->user->banned): ?>
<li class="ban">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('user', 'ban', ['name' => $this->context->transport->user->name]) ?>" data-confirm-text="Are you sure?">
Ban user
</a>
</li>
<?php else: ?>
<li class="unban">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('user', 'unban', ['name' => $this->context->transport->user->name]) ?>" data-confirm-text="Are you sure?">
Unban user
</a>
</li>
<?php endif ?>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::AcceptUserRegistration) and !$this->context->transport->user->staff_confirmed and $this->config->registration->staffActivation): ?>
<li class="accept-registration">
<a class="simple-action" href="<?php echo \Chibi\UrlHelper::route('user', 'accept-registration', ['name' => $this->context->transport->user->name]) ?>">
Accept registration
</a>
</li>
<?php endif ?>
</ul>
<script type="text/javascript">
@ -89,11 +120,23 @@
<?php else: ?>
<li class="edit">
<?php endif ?>
<a href="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['name' => $this->context->transport->user->name, 'tab' => 'edit']) ?>">
<a href="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['name' => $this->context->transport->user->name]) ?>">
Account settings
</a>
</li>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::DeleteUser, $secondary)): ?>
<?php if ($this->context->transport->tab == 'delete'): ?>
<li class="selected delete">
<?php else: ?>
<li class="delete">
<?php endif ?>
<a href="<?php echo \Chibi\UrlHelper::route('user', 'delete', ['name' => $this->context->transport->user->name]) ?>">
Delete account
</a>
</li>
<?php endif ?>
</ul>
</nav>
</div>
@ -119,7 +162,7 @@
<?php endif ?>
<?php if ($this->context->transport->tab == 'edit'): ?>
<form action="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['id' => $this->context->transport->user->id]) ?>" method="post" class="edit aligned" autocomplete="off">
<form action="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['name' => $this->context->transport->user->name]) ?>" method="post" class="edit aligned" autocomplete="off">
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
<div class="old-password">
<label class="left" for="old-password">Old password:</label>
@ -131,25 +174,25 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserName, $secondary)): ?>
<div class="nickname">
<label class="left" for="name">Name:</label>
<input type="text" name="name" id="name" placeholder="New name&hellip;"/>
<input type="text" name="name" id="name" placeholder="New name&hellip;" value="<?php echo $this->context->suppliedName ?>"/>
</div>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserEmail, $secondary)): ?>
<div class="email">
<label class="left" for="name">E-mail:</label>
<input type="text" name="email" id="email" placeholder="New e-mail&hellip;"/>
<input type="text" name="email" id="email" placeholder="New e-mail&hellip;" value="<?php echo $this->context->suppliedEmail ?>"/>
</div>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserPassword, $secondary)): ?>
<div class="password1">
<label class="left" for="password1">New password:</label>
<input type="password" name="password1" id="password1" placeholder="New password&hellip;"/>
<input type="password" name="password1" id="password1" placeholder="New password&hellip;" value="<?php echo $this->context->suppliedPassword1 ?>"/>
</div>
<div class="password2">
<label class="left" for="password2"></label>
<input type="password" name="password2" id="password2" placeholder="New password&hellip; (repeat)"/>
<input type="password" name="password2" id="password2" placeholder="New password&hellip; (repeat)" value="<?php echo $this->context->suppliedPassword2 ?>"/>
</div>
<?php endif ?>
@ -158,7 +201,7 @@
<label class="left" for="access-rank">Access rank:</label>
<select name="access-rank" id="access-rank">
<?php foreach (AccessRank::getAll() as $rank): ?>
<?php if ($rank == $this->context->transport->user->access_rank): ?>
<?php if (($this->context->suppliedAccessRank != '' and $rank == $this->context->suppliedAccessRank) or ($this->context->suppliedAccessRank == '' and $rank == $this->context->transport->user->access_rank)): ?>
<option value="<?php echo $rank ?>" selected="selected">
<?php else: ?>
<option value="<?php echo $rank ?>">
@ -170,11 +213,42 @@
</div>
<?php endif ?>
<?php if ($this->context->transport->success === true): ?>
<p class="alert alert-success">Account settings updated!</p>
<?php elseif (isset($this->context->transport->errorMessage)): ?>
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
<?php endif ?>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Submit</button>
</div>
</form>
<?php elseif ($this->context->transport->tab == 'delete'): ?>
<form action="<?php echo \Chibi\UrlHelper::route('user', 'delete', ['name' => $this->context->transport->user->name]) ?>" method="post" class="edit aligned" autocomplete="off" data-confirm-text="Are you sure you want to delete your account?">
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
<div class="old-password">
<label class="left" for="old-password">Old password:</label>
<input type="password" name="old-password" id="old-password" placeholder="Old password"/>
</div>
<?php endif ?>
<input type="hidden" name="remove" value="1"/>
<?php if ($this->context->transport->success === true): ?>
<p class="alert alert-success">Account settings updated!</p>
<?php elseif (isset($this->context->transport->errorMessage)): ?>
<p class="alert alert-error">Error: <?php echo $this->context->transport->errorMessage ?></p>
<?php endif ?>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Delete account</button>
</div>
</form>
<?php endif ?>
</div>

View file

@ -41,7 +41,7 @@ function configFactory()
$config = configFactory();
R::setup('sqlite:' . $config->main->dbPath);
#R::dependencies(['tag' => ['post'], 'post' => ['user']]);
R::dependencies(['tag' => ['post'], 'favoritee' => ['post', 'user']]);
//wire models
\Chibi\AutoLoader::init([$config->chibi->userCodeDir, __DIR__]);