Fix#10 - Add name, surname and username editing
This commit is contained in:
Jan Jon 2018-07-22 21:03:07 +02:00 committed by Vojtěch Sajdl
parent 3d8329137b
commit 9e472db6f9
3 changed files with 378 additions and 206 deletions

View File

@ -16,9 +16,19 @@ if (isset($_POST['password']))
$displayed_user->change_password(); $displayed_user->change_password();
} }
if (isset($_POST['username']))
{
$displayed_user->change_username();
}
if (isset($_POST['name']))
{
$displayed_user->change_name();
}
if (isset($_POST['email'])) if (isset($_POST['email']))
{ {
$displayed_user->email_link(); $success = $displayed_user->email_link();
} }
if (isset($_POST['permission'])) if (isset($_POST['permission']))
@ -36,10 +46,19 @@ Template::render_header(_("User"), true);
?> ?>
<div class="text-center"> <div class="text-center">
<h1><?php echo _("User settings");?></h1> <h1><?php
if ($_SESSION['user'] == $_GET['id'])
{
echo _("User settings");
}else{
echo _("User");
} ?></h1>
</div> </div>
<?php if (isset($message)){?> <?php if (isset($message)){?>
<p class="alert alert-danger"><?php echo $message?></p> <p class="alert alert-danger"><?php echo $message?></p>
<?php } <?php }
if (isset($success)){?>
<p class="alert alert-success"><?php echo $success?></p>
<?php }
$displayed_user->render_user_settings(); $displayed_user->render_user_settings();

View File

@ -127,7 +127,11 @@ class User
$messages[] = _("Rank"); $messages[] = _("Rank");
} }
if (!isset($messages)){ if (isset($messages)){
$message = "Please enter ".implode(", ", $messages);
return;
}
$name = $_POST['name']; $name = $_POST['name'];
$surname = $_POST['surname']; $surname = $_POST['surname'];
$username = $_POST['username']; $username = $_POST['username'];
@ -171,8 +175,12 @@ class User
$stmt->bind_param("ssssssi", $email, $username, $name, $surname, $hash, $salt, $permission); $stmt->bind_param("ssssssi", $email, $username, $name, $surname, $hash, $salt, $permission);
$stmt->execute(); $stmt->execute();
if ($stmt->affected_rows>0) if ($stmt->affected_rows==0)
{ {
$message = _("Username or email already used");
return;
}
$to = $email; $to = $email;
$subject = _('User account created').' - '.NAME; $subject = _('User account created').' - '.NAME;
$msg = sprintf(_("Hi %s!<br>"."Your account has been created. You can login with your email address at <a href=\"%s\">%s</a> with password %s - please change it as soon as possible."), $name." ".$surname,WEB_URL."/admin", WEB_URL."/admin", $pass); $msg = sprintf(_("Hi %s!<br>"."Your account has been created. You can login with your email address at <a href=\"%s\">%s</a> with password %s - please change it as soon as possible."), $name." ".$surname,WEB_URL."/admin", WEB_URL."/admin", $pass);
@ -187,14 +195,6 @@ class User
header("Location: ".WEB_URL."/admin/?do=settings"); header("Location: ".WEB_URL."/admin/?do=settings");
} }
} }
else{
$message = _("Username or email already used");
}
}
else{
$message = "Please enter ".implode(", ", $messages);
}
}
else { else {
$message = _("You don't have the permission to do that!"); $message = _("You don't have the permission to do that!");
} }
@ -210,8 +210,16 @@ class User
public static function login() public static function login()
{ {
global $message, $mysqli; global $message, $mysqli;
if (isset($_POST['email'])) if (!isset($_POST['email']) && !isset($_POST['email']))
{ {
return;
}
if ((!isset($_POST['email']) || !isset($_POST['email'])))
{
$message = _("Please fill in your email and password!");
return;
}
$email = $_POST['email']; $email = $_POST['email'];
$pass = $_POST['pass']; $pass = $_POST['pass'];
@ -219,30 +227,36 @@ class User
$stmt->bind_param("s", $email); $stmt->bind_param("s", $email);
$stmt->execute(); $stmt->execute();
$query = $stmt->get_result(); $query = $stmt->get_result();
if ($query->num_rows)
{
$result = $query->fetch_assoc();
if ($query->num_rows<1)
{
$message = _("Wrong email or password");
return;
}
$result = $query->fetch_assoc();
$salt = $result["salt"]; $salt = $result["salt"];
$id = $result["id"]; $id = $result["id"];
$active = $result["active"]; $active = $result["active"];
if (!$active) if (!$active)
{ {
$message = _("Your account has been disabled. Please contact administrator."); $message = _("Your account has been disabled. Please contact administrator.");
return;
} }
else
{
$hash = hash('sha256', $pass.$salt);
$hash = hash('sha256', $pass.$salt);
$stmt = $mysqli->prepare("SELECT count(*) as count FROM users WHERE id=? AND password_hash=?"); $stmt = $mysqli->prepare("SELECT count(*) as count FROM users WHERE id=? AND password_hash=?");
$stmt->bind_param("is", $id, $hash); $stmt->bind_param("is", $id, $hash);
$stmt->execute(); $stmt->execute();
$query = $stmt->get_result(); $query = $stmt->get_result();
if (!$query->fetch_assoc()['count']) if (!$query->fetch_assoc()['count'])
{ {
$message = _("Wrong email or password"); $message = _("Wrong email or password");
}else return;
{ }
if (isset($_POST['remember'])&&$_POST['remember']) if (isset($_POST['remember'])&&$_POST['remember'])
{ {
$year = strtotime('+356 days', time()); $year = strtotime('+356 days', time());
@ -250,16 +264,10 @@ class User
setcookie('token', $token, $year, "/"); setcookie('token', $token, $year, "/");
setcookie('user', $id, $year, "/"); setcookie('user', $id, $year, "/");
} }
$_SESSION['user'] = $id; $_SESSION['user'] = $id;
header("Location: ".WEB_URL."/admin"); header("Location: ".WEB_URL."/admin");
} }
}
}
else{
$message = _("Wrong email or password");
}
}
}
/** /**
* Checks whether token is valid (this means is in database and associated * Checks whether token is valid (this means is in database and associated
@ -301,29 +309,70 @@ class User
{ {
global $permissions, $user; global $permissions, $user;
?> ?>
<div class="row user">
<div class="col-md-2 col-md-offset-2"><img src="https://www.gravatar.com/avatar/<?php echo md5( strtolower( trim( $this->email ) ) );?>?s=160"
alt="<?php echo _("Profile picture");?>"></div>
<div class="col-md-6">
<?php if($this->id==$_SESSION['user']||$user->get_rank()<1){
?>
<form action="<?php echo WEB_URL;?>/admin/?do=user&amp;id=<?php echo $this->id; ?>" method="POST">
<div class="input-group">
<div class="col-md-12">
<div class="row"> <div class="row">
<div class="col-md-2 col-md-offset-2"><img src="https://www.gravatar.com/avatar/<?php echo md5( strtolower( trim( $this->email ) ) );?>" alt="<?php echo _("Profile picture");?>"></div> <label class="form-name" for="name"><?php echo _("Name"); ?></label>
<div class="col-md-6"><h3><?php echo $this->name." ".$this->surname;?></h3></div> <label class="form-name" for="surname"><?php echo _("Surname"); ?></label>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-2 col-md-offset-2"><strong><?php echo _("ID");?></strong></div> <input type="text" name="name" placeholder="<?php echo _("Name"); ?>"
<div class="col-md-6"><?php echo $this->id; ?></div> title="<?php echo _("Name"); ?>" class="form-control form-name"
value=<?php echo htmlspecialchars($this->name, ENT_QUOTES);?>>
<input type="text" name="surname" placeholder="<?php echo _("Surname"); ?>"
title="<?php echo _("Surname"); ?>" class="form-control form-name"
value=<?php echo htmlspecialchars($this->surname, ENT_QUOTES);?>>
</div> </div>
<div class="row"> </div>
<div class="col-md-2 col-md-offset-2"><strong><?php echo _("Username");?></strong></div> </div>
<div class="col-md-6"><?php echo $this->username." "; if ($this->id!=$_SESSION['user'] && $user->get_rank()<=1 && ($user->get_rank()<$this->rank)) <div class="input-group">
{ <button type="submit" class="btn btn-primary pull-right"><?php echo _("Change name");?></button>
echo "<a href='".WEB_URL."/admin/?do=user&id=".$this->id."&what=toggle'>"; </div>
echo "<i class='fa fa-".($this->active?"check success":"times danger")."'></i></a>"; </form>
<?php
}else{ }else{
echo "<i class='fa fa-".($this->active?"check success":"times danger")."'></i>"; ?>
}?></div> <h3><?php echo $this->name." ".$this->surname;?></h3>
<?php
}?>
</div> </div>
</div>
<form action="<?php echo WEB_URL;?>/admin/?do=user&amp;id=<?php echo $this->id; ?>" method="POST">
<div class="row user">
<div class="col-md-2 col-md-offset-2"><strong><?php echo _("Username");?></strong></div>
<div class="col-md-6">
<?php
if ($this->id==$_SESSION['user'] || $user->get_rank()<1){?>
<div class="input-group">
<input type="text" class="form-control" name="username" required value="<?php echo htmlspecialchars($this->username, ENT_QUOTES);?>">
<span class="input-group-btn">
<button type="submit" class="btn btn-primary pull-right"><?php echo _("Change username");?></button>
</span>
</div>
<?php
}else{?><?php echo $this->username." ";
if ($user->get_rank()>=1){
echo "<i class='fa fa-".($this->active?"check success":"times danger")."'></i>";
}
}
?>
</div>
</div>
</form>
<form action="<?php echo WEB_URL;?>/admin/?do=user&id=<?php echo $this->id; ?>" method="POST"> <form action="<?php echo WEB_URL;?>/admin/?do=user&id=<?php echo $this->id; ?>" method="POST">
<div class="row"> <div class="row user">
<div class="col-md-2 col-md-offset-2"><strong><?php echo _("Role");?></strong></div> <div class="col-md-2 col-md-offset-2"><strong><?php echo _("Role");?></strong></div>
<div class="col-md-6"><?php if ($user->get_rank() == 0 && $this->id != $_SESSION['user']){?> <div class="input-group"><select class="form-control" name="permission"><?php foreach ($permissions as $key => $value) { <div class="col-md-6"><?php if ($user->get_rank() == 0 && $this->id != $_SESSION['user']){?>
<div class="input-group"><select class="form-control" name="permission">
<?php foreach ($permissions as $key => $value) {
echo "<option value='$key' ".($key==$this->rank?"selected":"").">$value</option>"; echo "<option value='$key' ".($key==$this->rank?"selected":"").">$value</option>";
} ?> } ?>
</select><span class="input-group-btn"> </select><span class="input-group-btn">
@ -333,10 +382,10 @@ class User
</div> </div>
</form> </form>
<?php if($this->id==$_SESSION['user']) <?php if($this->id==$_SESSION['user']||$user->get_rank()<1)
{?> {?>
<form action="<?php echo WEB_URL;?>/admin/?do=user" method="POST"> <form action="<?php echo WEB_URL;?>/admin/?do=user&amp;id=<?php echo $this->id; ?>" method="POST">
<div class="row"> <div class="row user">
<div class="col-md-2 col-md-offset-2"><strong>Email</strong></div> <div class="col-md-2 col-md-offset-2"><strong>Email</strong></div>
<div class="col-md-6"> <div class="col-md-6">
<div class="input-group"> <div class="input-group">
@ -348,6 +397,21 @@ class User
</div> </div>
</div> </div>
</form> </form>
<?php }else
{
?>
<div class="row user">
<div class="col-md-2 col-md-offset-2"><strong><?php echo _("Email");?></strong></div>
<div class="col-md-6">
<a href="mailto:<?php echo $this->email; ?>"><?php echo $this->email; ?></a>
</div>
</div>
<?php
}
if($this->id==$_SESSION['user']){
?>
<form action="<?php echo WEB_URL;?>/admin/?do=user" method="POST"> <form action="<?php echo WEB_URL;?>/admin/?do=user" method="POST">
<div class="row"> <div class="row">
<div class="col-md-2 col-md-offset-2"><strong><?php echo _("Password");?></strong></div> <div class="col-md-2 col-md-offset-2"><strong><?php echo _("Password");?></strong></div>
@ -364,17 +428,7 @@ class User
</form> </form>
<?php <?php
} }
else
{
?>
<div class="row">
<div class="col-md-2 col-md-offset-2"><strong><?php echo _("Email");?></strong></div>
<div class="col-md-6">
<a href="mailto:<?php echo $this->email; ?>"><?php echo $this->email; ?></a>
</div>
</div>
<?php
}
if ($this->id!=$_SESSION['user'] && $user->get_rank()<=1 && ($user->get_rank()<$this->rank)) if ($this->id!=$_SESSION['user'] && $user->get_rank()<=1 && ($user->get_rank()<$this->rank))
{?> {?>
<div class="row"> <div class="row">
@ -392,6 +446,71 @@ class User
<?php } <?php }
} }
/**
* Changes username of user by POST[ID].
* @return void
*/
public function change_username()
{
global $mysqli, $message, $user;
$id = $this->id;
$stmt = $mysqli->prepare("SELECT count(*) FROM users WHERE username LIKE ?");
$stmt->bind_param("s",$_POST["username"]);
$stmt->execute();
if ($stmt->num_rows > 0)
{
$message = _("This username is already taken.");
return;
}
$stmt->close();
if ($_SESSION['user'] != $id && $user->get_rank()>0)
{
$message = _("Cannot change username of other users!");
}else{
$stmt = $mysqli->prepare("UPDATE users SET username = ? WHERE id=?");
$stmt->bind_param("si",$_POST["username"],$id);
$stmt->execute();
$stmt->close();
header("Location: /admin/?do=user&id=".$id);
}
}
/**
* Changes name and surname of user by POST[ID].
* @return void
*/
public function change_name()
{
global $mysqli, $message, $user;
if (strlen(trim($_POST['name']))==0) {
$messages[] = _("Name");
}
if(strlen(trim($_POST['surname']))==0) {
$messages[] = _("Surname");
}
if (!empty($messages))
{
$message = "Please enter ".implode(", ", $messages);
return;
}
$id = $this->id;
if ($_SESSION['user'] != $id && $user->get_rank()>0)
{
$message = _("Cannot change names of other users!");
}else{
$stmt = $mysqli->prepare("UPDATE users SET `name` = ?, `surname` = ? WHERE id=?");
$stmt->bind_param("ssi",$_POST["name"],$_POST["surname"],$id);
$stmt->execute();
$stmt->close();
header("Location: /admin/?do=user&id=".$id);
}
}
/** /**
* Changes user password and deletes all remember tokens so all other sessions * Changes user password and deletes all remember tokens so all other sessions
* won't stay logged in without knowing new pass. Uses token when reseting password. * won't stay logged in without knowing new pass. Uses token when reseting password.
@ -405,7 +524,9 @@ class User
if ($_POST['password']!=$_POST['password_repeat']) if ($_POST['password']!=$_POST['password_repeat'])
{ {
$message = _("Passwords do not match!"); $message = _("Passwords do not match!");
}else{ return;
}
if (!$token) if (!$token)
{ {
if ($_SESSION['user']!=$id) if ($_SESSION['user']!=$id)
@ -416,8 +537,8 @@ class User
$stmt->bind_param("i", $id); $stmt->bind_param("i", $id);
$stmt->execute(); $stmt->execute();
$query = $stmt->get_result(); $query = $stmt->get_result();
$result = $query->fetch_assoc(); $result = $query->fetch_assoc();
$salt = $result['salt']; $salt = $result['salt'];
$pass = $_POST['old_password']; $pass = $_POST['old_password'];
$hash = hash('sha256', $pass.$salt); $hash = hash('sha256', $pass.$salt);
@ -425,6 +546,7 @@ class User
$stmt = $mysqli->prepare("SELECT count(*) as count FROM users WHERE id=? AND password_hash = ?"); $stmt = $mysqli->prepare("SELECT count(*) as count FROM users WHERE id=? AND password_hash = ?");
$stmt->bind_param("is", $id, $hash); $stmt->bind_param("is", $id, $hash);
$stmt->execute(); $stmt->execute();
if ($stmt->get_result()->fetch_assoc()['count']) if ($stmt->get_result()->fetch_assoc()['count'])
{ {
$pass = $_POST['password']; $pass = $_POST['password'];
@ -433,10 +555,12 @@ class User
$stmt->bind_param("si", $hash, $id); $stmt->bind_param("si", $hash, $id);
$stmt->execute(); $stmt->execute();
$stmt->close(); $stmt->close();
$stmt = $mysqli->prepare("DELETE FROM tokens WHERE user = ? AND data = 'remember'"); $stmt = $mysqli->prepare("DELETE FROM tokens WHERE user = ? AND data = 'remember'");
$stmt->bind_param("d", $id); $stmt->bind_param("d", $id);
$stmt->execute(); $stmt->execute();
$stmt->get_result(); $stmt->get_result();
User::logout(); User::logout();
} }
else{ else{
@ -451,6 +575,7 @@ class User
$stmt->execute(); $stmt->execute();
$query = $stmt->get_result(); $query = $stmt->get_result();
$result = $query->fetch_assoc(); $result = $query->fetch_assoc();
$salt = $result['salt']; $salt = $result['salt'];
$pass = $_POST['password']; $pass = $_POST['password'];
$hash = hash('sha256', $pass.$salt); $hash = hash('sha256', $pass.$salt);
@ -459,6 +584,7 @@ class User
$stmt->bind_param("si", $hash,$id); $stmt->bind_param("si", $hash,$id);
$stmt->execute(); $stmt->execute();
$stmt->close(); $stmt->close();
$stmt = $mysqli->prepare("DELETE FROM tokens WHERE user = ? AND data = 'remember'"); $stmt = $mysqli->prepare("DELETE FROM tokens WHERE user = ? AND data = 'remember'");
$stmt->bind_param("d", $id); $stmt->bind_param("d", $id);
$stmt->execute(); $stmt->execute();
@ -468,11 +594,9 @@ class User
{ {
$message = _("Invalid token detected, please retry your request from start!"); $message = _("Invalid token detected, please retry your request from start!");
} }
Token::delete($token); Token::delete($token);
} }
} }
}
/** /**
* Sends email with link for password reset, link is token protected and valid only once. * Sends email with link for password reset, link is token protected and valid only once.
@ -511,11 +635,23 @@ class User
* @return void * @return void
*/ */
public function email_link(){ public function email_link(){
global $user; global $user, $mysqli;
$email = $_POST['email']; $email = $_POST['email'];
$time = strtotime('+1 day', time());
$id = $this->id; $id = $this->id;
if ($user->get_rank()<1 && $id!=$_SESSION['user'])
{
$stmt = $mysqli->prepare("UPDATE users SET email = ? WHERE id=?");
$stmt->bind_param("sd", $email, $id);
$stmt->execute();
$stmt->get_result();
header("Location: /admin/?do=user&id=".$id);
return;
}
$time = strtotime('+1 day', time());
$token = Token::add($id, 'email;$email', $time); $token = Token::add($id, 'email;$email', $time);
$link = WEB_URL."/admin/?do=change-email&id=$id&token=$token"; $link = WEB_URL."/admin/?do=change-email&id=$id&token=$token";
@ -528,6 +664,7 @@ class User
$headers .= "Reply-To: ".MAILER_NAME.' <'.MAILER_ADDRESS.'>'.PHP_EOL; $headers .= "Reply-To: ".MAILER_NAME.' <'.MAILER_ADDRESS.'>'.PHP_EOL;
mail($to, $subject, $msg, $headers); mail($to, $subject, $msg, $headers);
return _('Confirmation email sent!');
} }
/** /**

View File

@ -93,7 +93,7 @@ div.center {
#wrapper #wrapper
{ {
max-width: 900px; max-width: 1024px;
min-height: calc(100vh - 157px); min-height: calc(100vh - 157px);
padding-right: 15px; padding-right: 15px;
padding-left: 15px padding-left: 15px
@ -600,3 +600,19 @@ i.danger{
body .h1,body .h2,body .h3,body h1,body h2,body h3 { body .h1,body .h2,body .h3,body h1,body h2,body h3 {
margin-top: 18px; margin-top: 18px;
} }
.row.user .input-group
{
width: 100%;
margin-bottom: 5px
}
.row.user .form-name{
width: 50%;
float: left;
}
label.form-name
{
line-height: 20px
}