Backend for e-mail notifications. Actual sending of e-mail TODO

This commit is contained in:
Phyks 2013-09-28 19:31:27 +02:00
parent b2727d9254
commit 9d73675aea
5 changed files with 137 additions and 23 deletions

2
TODO
View File

@ -1,6 +1,6 @@
* Check database creation in install.php * Check database creation in install.php
* Don't display the whole balance table if not admin * Don't display the whole balance table if not admin
* Notifications by e-mail for users
Improvements : Improvements :
============== ==============

View File

@ -3,15 +3,17 @@ require_once('data/config.php');
require_once('Storage.class.php'); require_once('Storage.class.php');
class User extends Storage { class User extends Storage {
protected $id = 0, $login, $display_name, $password, $admin, $json_token; protected $id = 0, $login, $email, $display_name, $password, $admin, $json_token, $notifications;
protected $TABLE_NAME = "Users"; protected $TABLE_NAME = "Users";
protected $fields = array( protected $fields = array(
'id'=>'key', 'id'=>'key',
'login'=>'string', 'login'=>'string',
'email'=>'string',
'display_name'=>'string', 'display_name'=>'string',
'password'=>'password', 'password'=>'password',
'admin'=>'bool', 'admin'=>'bool',
'json_token'=>'string', 'json_token'=>'string',
'notifications'=>'int'
); );
public function __construct() { public function __construct() {
@ -32,6 +34,10 @@ class User extends Storage {
return $this->id; return $this->id;
} }
public function getEmail() {
return $this->email;
}
public function getAdmin() { public function getAdmin() {
return $this->admin; return $this->admin;
} }
@ -40,6 +46,10 @@ class User extends Storage {
return $this->json_token; return $this->json_token;
} }
public function getNotifications() {
return $this->notifications;
}
// Setters // Setters
// ======= // =======
public function setId($id) { public function setId($id) {
@ -50,6 +60,16 @@ class User extends Storage {
$this->login = $login; $this->login = $login;
} }
public function setEmail($email) {
if(filter_var($email, FILTER_VALIDATE_EMAIL) !== false) {
$this->email = $email;
return true;
}
else {
return false;
}
}
public function setDisplayName($display_name) { public function setDisplayName($display_name) {
$this->display_name = $display_name; $this->display_name = $display_name;
} }
@ -66,6 +86,26 @@ class User extends Storage {
$this->json_token = $token; $this->json_token = $token;
} }
public function setNotifications($notifications) {
switch($notifications) {
case 1:
$this->notifications = 1;
break;
case 2:
$this->notifications = 2;
break;
case 3:
$this->notifications = 3;
break;
default:
$this->notifications = 3;
break;
}
}
// Password functions // Password functions
// ================== // ==================
public function encrypt($text) { public function encrypt($text) {
@ -99,10 +139,10 @@ class User extends Storage {
// =============== // ===============
public function sessionStore($serialize = true) { public function sessionStore($serialize = true) {
if($serialize) { if($serialize) {
return serialize(array('id'=>$this->id, 'login'=>$this->login, 'display_name'=>$this->display_name, 'password'=>$this->password, 'admin'=>$this->admin, 'json_token'=>$this->json_token)); return serialize(array('id'=>$this->id, 'login'=>$this->login, 'email'=>$this->email, 'display_name'=>$this->display_name, 'password'=>$this->password, 'admin'=>$this->admin, 'json_token'=>$this->json_token, 'notifications'=>$this->notifications));
} }
else { else {
return array('id'=>$this->id, 'login'=>$this->login, 'display_name'=>$this->display_name, 'password'=>$this->password, 'admin'=>$this->admin, 'json_token'=>$this->json_token); return array('id'=>$this->id, 'login'=>$this->login, 'email'=>$this->email, 'display_name'=>$this->display_name, 'password'=>$this->password, 'admin'=>$this->admin, 'json_token'=>$this->json_token, 'notifications'=>$this->notifications);
} }
} }
@ -114,10 +154,12 @@ class User extends Storage {
$this->setId($user_data['id']); $this->setId($user_data['id']);
$this->setLogin($user_data['login']); $this->setLogin($user_data['login']);
$this->setEmail($user_data['email']);
$this->setDisplayName($user_data['display_name']); $this->setDisplayName($user_data['display_name']);
$this->setPassword($user_data['password']); $this->setPassword($user_data['password']);
$this->setAdmin($user_data['admin']); $this->setAdmin($user_data['admin']);
$this->setJsonToken($user_data['json_token']); $this->setJsonToken($user_data['json_token']);
$this->setNotifications($user_data['notifications']);
} }
// Check wether a user already exists or not // Check wether a user already exists or not
@ -137,9 +179,11 @@ class User extends Storage {
public function secureDisplay() { public function secureDisplay() {
$this->id = (int) $this->id; $this->id = (int) $this->id;
$this->login = htmlspecialchars($this->login); $this->login = htmlspecialchars($this->login);
$this->email = htmlspecialchars($this->email);
$this->display_name = htmlspecialchars($this->display_name); $this->display_name = htmlspecialchars($this->display_name);
$this->admin = (int) $this->admin; $this->admin = (int) $this->admin;
$this->json_token = htmlspecialchars($this->json_token); $this->json_token = htmlspecialchars($this->json_token);
$this->notifications = (int) $this->notifications;
return $this; return $this;
} }

View File

@ -12,7 +12,8 @@
'unauthorized'=>array('fr'=>'Vous n\'avez pas le droit de faire cette action.', 'en'=>'You are not authorized to do that.'), 'unauthorized'=>array('fr'=>'Vous n\'avez pas le droit de faire cette action.', 'en'=>'You are not authorized to do that.'),
'no_users'=>array('fr'=>'Vous devez ajouter au moins un autre utilisateur.', 'en'=>'You must add at least one more user beside you.'), 'no_users'=>array('fr'=>'Vous devez ajouter au moins un autre utilisateur.', 'en'=>'You must add at least one more user beside you.'),
'what_unknown,'=>array('fr'=>'Vous devez renseigner un objet pour la dépense.', 'en'=>'You must add something to describe this invoice in "what" field.'), 'what_unknown,'=>array('fr'=>'Vous devez renseigner un objet pour la dépense.', 'en'=>'You must add something to describe this invoice in "what" field.'),
'incorrect_amount'=>array('fr'=>'Montant incorrect ou nul.', 'en'=>'Incorrect amount or amount is zero.') 'incorrect_amount'=>array('fr'=>'Montant incorrect ou nul.', 'en'=>'Incorrect amount or amount is zero.'),
'email_invalid'=>array('fr'=>'L\'adresse e-mail est invalide.', 'en'=>'Incorrect e-mail address.')
); );
// Include necessary files // Include necessary files
@ -162,23 +163,35 @@
break; break;
case 'password': case 'password':
if(!empty($_POST['email'])) {
if(check_token(600, 'password')) {
if(!empty($_POST['password']) && !empty($_POST['password_confirm'])) { if(!empty($_POST['password']) && !empty($_POST['password_confirm'])) {
if($_POST['password'] == $_POST['password_confirm']) { if($_POST['password'] == $_POST['password_confirm']) {
if(check_token(600, 'password')) {
$current_user->setPassword($current_user->encrypt($_POST['password'])); $current_user->setPassword($current_user->encrypt($_POST['password']));
}
else {
$error = true;
$tpl->assign('error', $errors['password_mismatch'][LANG]);
}
}
if($current_user->setEmail($_POST['email']) === false) {
$error = true;
$tpl->assign('error', $errors['email_invalid'][LANG]);
}
$current_user->save(); $current_user->save();
if(!empty($error)) {
header('location: index.php?'.$get_redir); header('location: index.php?'.$get_redir);
exit(); exit();
} }
}
else { else {
$tpl->assign('error', $errors['token_error'][LANG]); $tpl->assign('error', $errors['token_error'][LANG]);
} }
} }
else {
$tpl->assign('error', $errors['password_mismatch'][LANG]);
}
}
$tpl->assign('view', 'password'); $tpl->assign('view', 'password');
$tpl->assign('json_token', htmlspecialchars($current_user->getJsonToken())); $tpl->assign('json_token', htmlspecialchars($current_user->getJsonToken()));
$tpl->assign('token', generate_token('password')); $tpl->assign('token', generate_token('password'));
@ -192,7 +205,7 @@
exit(); exit();
} }
if(!empty($_POST['login']) && !empty($_POST['display_name']) && (!empty($_POST['password']) || !empty($_POST['user_id'])) && isset($_POST['admin'])) { if(!empty($_POST['login']) && !empty($_POST['display_name']) && !empty($_POST['email']) && (!empty($_POST['password']) || !empty($_POST['user_id'])) && isset($_POST['admin'])) {
if(check_token(600, 'edit_users')) { if(check_token(600, 'edit_users')) {
$user = new User(); $user = new User();
if(!empty($_POST['user_id'])) { if(!empty($_POST['user_id'])) {
@ -208,6 +221,7 @@
} }
$user->setAdmin($_POST['admin']); $user->setAdmin($_POST['admin']);
if($user->setEmail($_POST['email']) !== false) {
if(!empty($_POST['user_id']) || $user->isUnique()) { if(!empty($_POST['user_id']) || $user->isUnique()) {
$user->save(); $user->save();
@ -222,6 +236,10 @@
$tpl->assign('error', $errors['user_already_exists'][LANG]); $tpl->assign('error', $errors['user_already_exists'][LANG]);
} }
} }
else {
$tpl->assign('error', $errors['email_invalid'][LANG]);
}
}
else { else {
$tpl->assign('error', $errors['token_error'][LANG]); $tpl->assign('error', $errors['token_error'][LANG]);
} }
@ -245,6 +263,7 @@
$tpl->assign('view', 'list_users'); $tpl->assign('view', 'list_users');
} }
$tpl->assign('login_post', (!empty($_POST['login']) ? htmlspecialchars($_POST['login']) : '')); $tpl->assign('login_post', (!empty($_POST['login']) ? htmlspecialchars($_POST['login']) : ''));
$tpl->assign('email_post', (!empty($_POST['email']) ? htmlspecialchars($_POST['email']) : ''));
$tpl->assign('display_name_post', (!empty($_POST['display_name']) ? htmlspecialchars($_POST['display_name']) : '')); $tpl->assign('display_name_post', (!empty($_POST['display_name']) ? htmlspecialchars($_POST['display_name']) : ''));
$tpl->assign('admin_post', (isset($_POST['admin']) ? (int) $_POST['admin'] : -1)); $tpl->assign('admin_post', (isset($_POST['admin']) ? (int) $_POST['admin'] : -1));
$tpl->assign('token', generate_token('edit_users')); $tpl->assign('token', generate_token('edit_users'));

View File

@ -8,6 +8,7 @@
<th>Id</th> <th>Id</th>
<th>Login</th> <th>Login</th>
<th>Display Name</th> <th>Display Name</th>
<th>E-mail address</th>
<th>Is admin ?</th> <th>Is admin ?</th>
<th>Edit</th> <th>Edit</th>
<th>Delete</th> <th>Delete</th>
@ -17,6 +18,7 @@
<td>{$value->getId()}</td> <td>{$value->getId()}</td>
<td>{$value->getLogin()}</td> <td>{$value->getLogin()}</td>
<td>{$value->getDisplayName()}</td> <td>{$value->getDisplayName()}</td>
<td>{$value->getEmail()}</td>
<td>{$value->getAdmin() ? "Yes" : "No"}</td> <td>{$value->getAdmin() ? "Yes" : "No"}</td>
<td><a href="index.php?do=edit_users&user_id={$value->getId()}">Edit</a></td> <td><a href="index.php?do=edit_users&user_id={$value->getId()}">Edit</a></td>
<td>{if condition="$value->getId() != $current_user->getId()"}<a href="index.php?do=delete_user&amp;user_id={$value->getId()}&amp;token={$token}">Delete</a>{/if}</td> <td>{if condition="$value->getId() != $current_user->getId()"}<a href="index.php?do=delete_user&amp;user_id={$value->getId()}&amp;token={$token}">Delete</a>{/if}</td>
@ -32,6 +34,17 @@
<p> <p>
<label for="display_name" class="label-block">Displayed name : </label><input type="text" name="display_name" id="display_name" {if condition="$display_name_post != ''"} value="{$display_name_post}" {else} {$user_id != -1 ? 'value="'.$user_data->getDisplayName().'"' : ''} {/if}/> <label for="display_name" class="label-block">Displayed name : </label><input type="text" name="display_name" id="display_name" {if condition="$display_name_post != ''"} value="{$display_name_post}" {else} {$user_id != -1 ? 'value="'.$user_data->getDisplayName().'"' : ''} {/if}/>
</p> </p>
<p>
<label for="email" class="label-block">E-mail address : </label><input type="text" name="email" id="email" {if condition="$email_post != ''"} value="{$email_post}" {else} {$user_id != -1 ? 'value="'.$user_data->getEmail().'"' : ''} {/if}/>
</p>
<p>
<label for="notifications" class="label-block">Notifications for </label>
<select name="notifications" id="notifications">
<option value="1" {if condition="$user_data->getNotifications() == 1"}selected="selected"{/if}>nothing.</option>
<option value="2" {if condition="$user_data->getNotifications() == 2"}selected="selected"{/if}>global paybacks only.</option>
<option value="3" {if condition="$user_data->getNotifications() == 3"}selected="selected"{/if}>everything involving this user.</option>
</select>
</p>
<p> <p>
<label for="password" class="label-block">Password : </label><input type="password" name="password" id="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Toggle visible"/></a> <label for="password" class="label-block">Password : </label><input type="password" name="password" id="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Toggle visible"/></a>
{if condition="$user_id != -1"} {if condition="$user_id != -1"}
@ -60,6 +73,18 @@
<form method="post" action="index.php?do=password" id="edit_password_form"> <form method="post" action="index.php?do=password" id="edit_password_form">
<p><label for="password" class="label-block">New password : </label><input type="password" id="password" name="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Toggle visible"/></a></p> <p><label for="password" class="label-block">New password : </label><input type="password" id="password" name="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Toggle visible"/></a></p>
<p><label for="password_confirm" class="label-block">Confirm new password : </label><input type="password" id="password_confirm" name="password_confirm"/> <a href="" onclick="toggle_password('password_confirm'); return false;"><img src="img/toggleVisible.png" alt="Toggle visible"/></a></p> <p><label for="password_confirm" class="label-block">Confirm new password : </label><input type="password" id="password_confirm" name="password_confirm"/> <a href="" onclick="toggle_password('password_confirm'); return false;"><img src="img/toggleVisible.png" alt="Toggle visible"/></a></p>
<p>
<label for="email" class="label-block">E-mail address : </label><input type="text" name="email" id="email" value="{$current_user->getEmail()}"/>
</p>
<p>
<label for="notifications" class="label-block">Notifications for </label>
<select name="notifications" id="notifications">
<option value="1" {if condition="$current_user->getNotifications() == 1"}selected="selected"{/if}>nothing.</option>
<option value="2" {if condition="$current_user->getNotifications() == 2"}selected="selected"{/if}>global paybacks only.</option>
<option value="3" {if condition="$current_user->getNotifications() == 3"}selected="selected"{/if}>everything involving you.</option>
</select>
</p>
<p><em>Note :</em> Leave blank the password fields if you don't want to edit password.</p>
<p class="center"><input type="submit" value="Update"/><input type="hidden" name="token" value="{$token}"</p> <p class="center"><input type="submit" value="Update"/><input type="hidden" name="token" value="{$token}"</p>
</form> </form>

View File

@ -8,6 +8,7 @@
<th>Id</th> <th>Id</th>
<th>Identifiant</th> <th>Identifiant</th>
<th>Nom affiché</th> <th>Nom affiché</th>
<th>Adresse e-mail</th>
<th>Administrateur ?</th> <th>Administrateur ?</th>
<th>Modifier</th> <th>Modifier</th>
<th>Supprimer</th> <th>Supprimer</th>
@ -17,6 +18,7 @@
<td>{$value->getId()}</td> <td>{$value->getId()}</td>
<td>{$value->getLogin()}</td> <td>{$value->getLogin()}</td>
<td>{$value->getDisplayName()}</td> <td>{$value->getDisplayName()}</td>
<td>{$value->getEmail()}</td>
<td>{$value->getAdmin() ? "Oui" : "Non"}</td> <td>{$value->getAdmin() ? "Oui" : "Non"}</td>
<td><a href="index.php?do=edit_users&user_id={$value->getId()}">Modifier</a></td> <td><a href="index.php?do=edit_users&user_id={$value->getId()}">Modifier</a></td>
<td>{if condition="$value->getId() != $current_user->getId()"}<a href="index.php?do=delete_user&amp;user_id={$value->getId()}&amp;token={$token}">Supprimer</a>{/if}</td> <td>{if condition="$value->getId() != $current_user->getId()"}<a href="index.php?do=delete_user&amp;user_id={$value->getId()}&amp;token={$token}">Supprimer</a>{/if}</td>
@ -32,6 +34,17 @@
<p> <p>
<label for="display_name" class="label-block">Nom affiché : </label><input type="text" name="display_name" id="display_name" {if condition="$display_name_post != ''"} value="{$display_name_post}" {else} {$user_id != -1 ? 'value="'.$user_data->getDisplayName().'"' : ''} {/if}/> <label for="display_name" class="label-block">Nom affiché : </label><input type="text" name="display_name" id="display_name" {if condition="$display_name_post != ''"} value="{$display_name_post}" {else} {$user_id != -1 ? 'value="'.$user_data->getDisplayName().'"' : ''} {/if}/>
</p> </p>
<p>
<label for="email" class="label-block">Adresse e-mail : </label><input type="text" name="email" id="email" {if condition="$email_post != ''"} value="{$email_post}" {else} {$user_id != -1 ? 'value="'.$user_data->getEmail().'"' : ''} {/if}/>
</p>
<p>
<label for="notifications" class="label-block">Notifications pour </label>
<select name="notifications" id="notifications">
<option value="1" {if condition="$user_data->getNotifications() == 1"}selected="selected"{/if}>rien.</option>
<option value="2" {if condition="$user_data->getNotifications() == 2"}selected="selected"{/if}>les remboursements globaux uniquement.</option>
<option value="3" {if condition="$user_data->getNotifications() == 3"}selected="selected"{/if}>tout ce qui concerne cet utilisateur.</option>
</select>
</p>
<p> <p>
<label for="password" class="label-block">Mot de passe : </label><input type="password" name="password" id="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Afficher / Masquer"/></a> <label for="password" class="label-block">Mot de passe : </label><input type="password" name="password" id="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Afficher / Masquer"/></a>
{if condition="$user_id != -1"} {if condition="$user_id != -1"}
@ -60,6 +73,19 @@
<form method="post" action="index.php?do=password" id="edit_password_form"> <form method="post" action="index.php?do=password" id="edit_password_form">
<p><label for="password" class="label-block">Nouveau mot de passe : </label><input type="password" id="password" name="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Afficher / Masquer"/></a></p> <p><label for="password" class="label-block">Nouveau mot de passe : </label><input type="password" id="password" name="password"/> <a href="" onclick="toggle_password('password'); return false;"><img src="img/toggleVisible.png" alt="Afficher / Masquer"/></a></p>
<p><label for="password_confirm" class="label-block">Confirmation : </label><input type="password" id="password_confirm" name="password_confirm"/> <a href="" onclick="toggle_password('password_confirm'); return false;"><img src="img/toggleVisible.png" alt="Afficher / Masquer"/></a></p> <p><label for="password_confirm" class="label-block">Confirmation : </label><input type="password" id="password_confirm" name="password_confirm"/> <a href="" onclick="toggle_password('password_confirm'); return false;"><img src="img/toggleVisible.png" alt="Afficher / Masquer"/></a></p>
<p>
<label for="email" class="label-block">Adresse e-mail : </label><input type="text" name="email" id="email" value="{$current_user->getEmail()}"/>
</p>
<p>
<label for="notifications" class="label-block">Notifications pour </label>
<select name="notifications" id="notifications">
<option value="1" {if condition="$current_user->getNotifications() == 1"}selected="selected"{/if}>rien.</option>
<option value="2" {if condition="$current_user->getNotifications() == 2"}selected="selected"{/if}>les remboursements globaux uniquement.</option>
<option value="3" {if condition="$current_user->getNotifications() == 3"}selected="selected"{/if}>tout ce qui vous concerne.</option>
</select>
</p>
<p><em>Note :</em> Laissez les champs mot de passe vides pour ne pas modifier le mot de passe.</p>
<p class="center"><input type="submit" value="Enregistrer"/><input type="hidden" name="token" value="{$token}"</p> <p class="center"><input type="submit" value="Enregistrer"/><input type="hidden" name="token" value="{$token}"</p>
</form> </form>