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 changeUserAccessRank=admin
changeUserName=moderator changeUserName=moderator
acceptUserRegistration=moderator acceptUserRegistration=moderator
banUser=admin banUser.own=nobody
banUser.all=admin
deleteUser.own=registered
deleteUser.all=nobody
listComments=anonymous listComments=anonymous
listTags=anonymous listTags=anonymous

View file

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

View file

@ -1,16 +1,13 @@
#sidebar { #sidebar {
width: 200px; width: 200px;
} font-size: 90%;
.details .key {
margin-right: 0.5em;
} }
.tabs ul { .tabs ul {
list-style-type: none; list-style-type: none;
margin: 0 0 1em 0; margin: 0 0 1em 0;
padding: 0; padding: 0;
border-bottom: 1px solid #eee; border-bottom: 1px solid #ccc;
} }
.tabs li { .tabs li {
display: inline-block; display: inline-block;
@ -24,11 +21,11 @@
.tabs li a { .tabs li a {
border: 1px solid white; border: 1px solid white;
border-bottom: 1px solid #eee; border-bottom: 1px solid #ccc;
color: silver; color: silver;
} }
.tabs li.selected a { .tabs li.selected a {
border: 1px solid #eee; border: 1px solid #ccc;
border-bottom: 1px solid white; border-bottom: 1px solid white;
color: inherit; color: inherit;
} }
@ -46,3 +43,7 @@
form.aligned label.left { form.aligned label.left {
width: 10em; 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) if ($.when.all === undefined)
{ {
$.when.all = function(deferreds) $.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() $(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) $('li.edit a').click(function(e)
{ {
e.preventDefault(); e.preventDefault();

View file

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

View file

@ -414,6 +414,7 @@ class PostController
$edited = false; $edited = false;
$secondary = $post->uploader->id == $this->context->user->id ? 'own' : 'all'; $secondary = $post->uploader->id == $this->context->user->id ? 'own' : 'all';
$this->context->transport->post = $post;
/* safety */ /* safety */
$suppliedSafety = InputHelper::get('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 * @route /user/{name}/edit
* @validate name [^\/]+ * @validate name [^\/]+
*/ */
public function editAction($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->viewName = 'user-view';
$this->context->stylesheets []= 'user-view.css'; $this->context->stylesheets []= 'user-view.css';
$this->context->subTitle = $name; $this->context->subTitle = $name;
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewUser);
$user = self::locateUser($name); $this->context->suppliedOldPassword = $suppliedOldPassword = InputHelper::get('old-password');
$this->context->transport->user = $user; $this->context->suppliedName = $suppliedName = InputHelper::get('name');
$this->context->transport->tab = 'edit'; $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) 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); $postsPerPage = intval($this->config->browsing->postsPerPage);
$user = self::locateUser($name); $user = self::locateUser($name);
if ($tab === null) if ($tab === null)
@ -64,6 +196,15 @@ class UserController
if ($page === null) if ($page === null)
$page = 1; $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) $buildDbQuery = function($dbQuery, $user, $tab)
{ {
$dbQuery->from('post'); $dbQuery->from('post');

View file

@ -51,4 +51,73 @@ class Model_User extends RedBean_SimpleModel
$this->setSetting('safety-' . $safety, true); $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 ChangeUserAccessRank = 16;
const ChangeUserEmail = 17; const ChangeUserEmail = 17;
const ChangeUserName = 18; const ChangeUserName = 18;
const DeleteUser = 19;
const ListComments = 19; const ListComments = 20;
const ListTags = 20; const ListTags = 21;
} }

View file

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

View file

@ -15,18 +15,18 @@
</div> </div>
<div> <div>
<label class="left" for="user">User name:</label> <label class="left" for="name">User name:</label>
<input id="user" name="user" value="<?php echo $this->context->suppliedUser ?>" placeholder="e.g. darth_vader" autocomplete="off"/> <input id="name" name="name" value="<?php echo $this->context->suppliedName ?>" placeholder="e.g. darth_vader" autocomplete="off"/>
</div> </div>
<div> <div>
<label class="left" for="pass1">Password:</label> <label class="left" for="password1">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"/> <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>
<div> <div>
<label class="left" for="pass2">Password (repeat):</label> <label class="left" for="password2">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"/> <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>
<div> <div>

View file

@ -44,31 +44,43 @@
<div class="sidebar-unit details"> <div class="sidebar-unit details">
<h1>details</h1> <h1>details</h1>
<div class="safety"> <div class="key-value safety">
<span class="key">Safety:</span> <span class="key">Safety:</span>
<span class="value"><?php echo PostSafety::toString($this->context->transport->post->safety) ?></span> <span class="value" title="<?php echo $val = PostSafety::toString($this->context->transport->post->safety) ?>">
</div> <?php echo $val ?>
<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> </span>
</div> </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="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> </div>
<?php if ($this->context->transport->post->image_width > 0): ?> <?php if ($this->context->transport->post->image_width > 0): ?>
<div class="dim"> <div class="key-value dim">
<span class="key">Dimensions:</span> <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_width,
$this->context->transport->post->image_height) ?></span> $this->context->transport->post->image_height) ?>">
<?php echo $val ?>
</span>
</div> </div>
<?php endif ?> <?php endif ?>
@ -110,13 +122,13 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::FavoritePost)): ?> <?php if (PrivilegesHelper::confirm($this->context->user, Privilege::FavoritePost)): ?>
<?php if (!$this->context->favorite): ?> <?php if (!$this->context->favorite): ?>
<li class="add-fav"> <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 Add to favorites
</a> </a>
</li> </li>
<?php else: ?> <?php else: ?>
<li class="rem-fav"> <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 Remove from favorites
</a> </a>
</li> </li>
@ -150,13 +162,13 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::HidePost, $secondary)): ?> <?php if (PrivilegesHelper::confirm($this->context->user, Privilege::HidePost, $secondary)): ?>
<?php if ($this->context->transport->post->hidden): ?> <?php if ($this->context->transport->post->hidden): ?>
<li class="unhide"> <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 Unhide
</a> </a>
</li> </li>
<?php else: ?> <?php else: ?>
<li class="hide"> <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 Hide
</a> </a>
</li> </li>
@ -165,7 +177,7 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::DeletePost, $secondary)): ?> <?php if (PrivilegesHelper::confirm($this->context->user, Privilege::DeletePost, $secondary)): ?>
<li class="delete"> <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 Delete
</a> </a>
</li> </li>

View file

@ -9,15 +9,23 @@
<div class="sidebar-unit details"> <div class="sidebar-unit details">
<h1>details</h1> <h1>details</h1>
<div class="join-date"> <div class="key-value join-date">
<span class="key">Joined:</span> <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>
<div class="access-rank"> <div class="key-value access-rank">
<span class="key">Access rank:</span> <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> </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>
<div class="sidebar-unit options"> <div class="sidebar-unit options">
@ -50,6 +58,29 @@
</li> </li>
<?php endif ?> <?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> </ul>
<script type="text/javascript"> <script type="text/javascript">
@ -89,11 +120,23 @@
<?php else: ?> <?php else: ?>
<li class="edit"> <li class="edit">
<?php endif ?> <?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 Account settings
</a> </a>
</li> </li>
<?php endif ?> <?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> </ul>
</nav> </nav>
</div> </div>
@ -119,7 +162,7 @@
<?php endif ?> <?php endif ?>
<?php if ($this->context->transport->tab == 'edit'): ?> <?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): ?> <?php if ($this->context->user->id == $this->context->transport->user->id): ?>
<div class="old-password"> <div class="old-password">
<label class="left" for="old-password">Old password:</label> <label class="left" for="old-password">Old password:</label>
@ -131,25 +174,25 @@
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserName, $secondary)): ?> <?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserName, $secondary)): ?>
<div class="nickname"> <div class="nickname">
<label class="left" for="name">Name:</label> <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> </div>
<?php endif ?> <?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserEmail, $secondary)): ?> <?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserEmail, $secondary)): ?>
<div class="email"> <div class="email">
<label class="left" for="name">E-mail:</label> <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> </div>
<?php endif ?> <?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserPassword, $secondary)): ?> <?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserPassword, $secondary)): ?>
<div class="password1"> <div class="password1">
<label class="left" for="password1">New password:</label> <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>
<div class="password2"> <div class="password2">
<label class="left" for="password2"></label> <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> </div>
<?php endif ?> <?php endif ?>
@ -158,7 +201,7 @@
<label class="left" for="access-rank">Access rank:</label> <label class="left" for="access-rank">Access rank:</label>
<select name="access-rank" id="access-rank"> <select name="access-rank" id="access-rank">
<?php foreach (AccessRank::getAll() as $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"> <option value="<?php echo $rank ?>" selected="selected">
<?php else: ?> <?php else: ?>
<option value="<?php echo $rank ?>"> <option value="<?php echo $rank ?>">
@ -170,11 +213,42 @@
</div> </div>
<?php endif ?> <?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> <div>
<label class="left">&nbsp;</label> <label class="left">&nbsp;</label>
<button type="submit">Submit</button> <button type="submit">Submit</button>
</div> </div>
</form> </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 ?> <?php endif ?>
</div> </div>

View file

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