parent
8fdc90bab7
commit
17013e8fe5
16 changed files with 483 additions and 201 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -69,10 +69,6 @@ i.icon-dl {
|
|||
content: ', ';
|
||||
}
|
||||
|
||||
.details .key {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.options ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)): ?>
|
||||
|
|
|
@ -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('●', 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('●', 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('●', 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('●', 8) ?>" autocomplete="off"/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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…"/>
|
||||
<input type="text" name="name" id="name" placeholder="New name…" 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…"/>
|
||||
<input type="text" name="email" id="email" placeholder="New e-mail…" 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…"/>
|
||||
<input type="password" name="password1" id="password1" placeholder="New password…" 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… (repeat)"/>
|
||||
<input type="password" name="password2" id="password2" placeholder="New password… (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"> </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"> </label>
|
||||
<button type="submit">Delete account</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -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__]);
|
||||
|
|
Loading…
Reference in a new issue