add capacity to modify user

This commit is contained in:
osaajani 2021-06-12 23:23:15 +02:00
parent f9e0312c89
commit 4a39865903
12 changed files with 687 additions and 143 deletions

View file

@ -103,7 +103,16 @@ namespace controllers\internals;
if ($user)
{
$api_key = $api_key ?? $internal_user->generate_random_api_key();
$success = $internal_user->update($user['id'], $email, $password, $admin, $api_key, $status, $encrypt_password);
$user = [
'email' => $email,
'password' => $encrypt_password ? password_hash($password, PASSWORD_DEFAULT) : $password,
'admin' => $admin,
'api_key' => $api_key,
'status' => $status,
];
$success = $internal_user->update($user['id'], $user);
echo json_encode(['id' => $user['id']]);
exit($success ? 0 : 1);

View file

@ -20,25 +20,25 @@ class Quota extends StandardController
*
* @param int $id_user : User id
* @param int $credit : Credit for this quota
* @param int $additional : Additionals credits
* @param bool $report_unused : Should unused credits be re-credited
* @param bool $report_unused_additional : Should unused additional credits be re-credited
* @param bool $auto_renew : Should the quota be automatically renewed after expiration_date
* @param string $renew_interval : Period to use for setting new expiration_date on renewal (format ISO_8601#Durations)
* @param \DateTime $start_date : Starting date for the quota
* @param ?\DateTime $expiration_date (optional) : Ending date for the quota
* @param bool $auto_renew (optional) : Should the quota be automatically renewed after expiration_date
* @param ?\DateInterval $renew_interval (optional) : Period to use for setting expiration_date on renewal
* @param int $additional (optional) : Additionals credits
* @param \DateTime $expiration_date : Ending date for the quota
*
* @return mixed bool|int : False if cannot create smsstop, id of the new smsstop else
* @return mixed bool|int : False if cannot create quota, id of the new quota else
*/
public function create(int $id_user, int $credit, bool $report_unused, bool $report_unused_additional, \DateTime $start_date, ?\DateTime $expiration_date = null, bool $auto_renew= false, ?\DateInterval $renew_interval = null, int $additional = 0)
public function create(int $id_user, int $credit, int $additional, bool $report_unused, bool $report_unused_additional, bool $auto_renew, string $renew_interval, \DateTime $start_date, \DateTime $expiration_date)
{
$quota = [
'id_user' => $id_user,
'credit' => $credit,
'report_unused' => $report_unused,
'report_unused_additional' => $report_unused_additional,
'start_date' => $start_date,
'expiration_date' => $expiration_date,
'start_date' => $start_date->format('Y-m-d H:i:s'),
'expiration_date' => $expiration_date->format('Y-m-d H:i:s'),
'auto_renew' => $auto_renew,
'renew_interval' => $renew_interval,
'additional' => $additional,
@ -52,35 +52,13 @@ class Quota extends StandardController
*
*
* @param int $id_user : User id
* @param int $id_quota : Id of the quota to update
* @param int $credit : Credit for this quota
* @param bool $report_unused : Should unused credits be re-credited
* @param bool $report_unused_additional : Should unused additional credits be re-credited
* @param \DateTime $start_date : Starting date for the quota
* @param ?\DateTime $expiration_date (optional) : Ending date for the quota
* @param bool $auto_renew (optional) : Should the quota be automatically renewed after expiration_date
* @param ?string $renew_interval (optional) : Period to use for setting expiration_date on renewal
* @param int $additional (optional) : Additionals credits
* @param int $consumed (optional) : Number of consumed credits
* @param int $id_quota : Quota to update id
* @param array $quota : Fields to update whith new values
*
* @return mixed bool|int : False if cannot create smsstop, id of the new smsstop else
* @return int : number of updated lines
*/
public function update_for_user(int $id_user, int $id_quota, int $credit, bool $report_unused, bool $report_unused_additional, \DateTime $start_date, ?\DateTime $expiration_date = null, bool $auto_renew= false, ?string $renew_interval = null, int $additional = 0, int $consumed = 0)
public function update_for_user(int $id_user, $id_quota, array $quota)
{
$expiration_date = $expiration_date === null ? $expiration_date : $expiration_date->format('Y-m-d H:i:s');
$quota = [
'credit' => $credit,
'report_unused' => $report_unused,
'report_unused_additional' => $report_unused_additional,
'start_date' => $start_date->format('Y-m-d H:i:s'),
'expiration_date' => $expiration_date,
'auto_renew' => $auto_renew,
'renew_interval' => $renew_interval,
'additional' => $additional,
'consumed' => $consumed,
];
return $this->get_model()->update_for_user($id_user, $id_quota, $quota);
}
@ -266,7 +244,14 @@ class Quota extends StandardController
$report += $unused_additional;
}
$success = $this->update_for_user($user['id'], $quota['id'], $quota['credit'], $quota['report_unused'], $quota['report_unused_additional'], $new_start_date, $new_expiration_date, $quota['auto_renew'], $quota['renew_interval'], $report, 0);
$updated_fields = [
'start_date' => $new_start_date->format('Y-m-d H:i:s'),
'expiration_date' => $new_expiration_date->format('Y-m-d H:i:s'),
'additional' => $report,
'consumed' => 0,
];
$success = $this->update_for_user($user['id'], $quota['id'], $updated_fields);
if (!$success)
{
@ -278,6 +263,18 @@ class Quota extends StandardController
$internal_event->create($quota['id_user'], 'QUOTA_RENEWAL', 'Renew quota ' . $quota['id'] . ' report ' . $report . ' credits.');
}
}
/**
* Return the quota for a user if it exists.
*
* @param int $id_user : user id
*
* @return array
*/
public function get_user_quota(int $id_user)
{
return $this->get_model()->get_user_quota($id_user);
}
/**
* Get the model for the Controller.

View file

@ -144,6 +144,27 @@ namespace controllers\internals;
return $objectDate && $objectDate->format($format) === $date;
}
/**
* Check if a sting represent a valid PHP period for creating an interval.
*
* @param string $period : Period string to check
*
* @return bool : True if valid period, false else
*/
public static function validate_period($period)
{
try
{
$interval = new \DateInterval($period);
}
catch (\Throwable $e)
{
return false;
}
return true;
}
/**
* Cette fonction retourne un mot de passe généré aléatoirement.

View file

@ -16,6 +16,7 @@ namespace controllers\internals;
*/
class User extends \descartes\InternalController
{
private $bdd;
private $model_user;
private $internal_event;
private $internal_setting;
@ -23,12 +24,25 @@ namespace controllers\internals;
public function __construct(\PDO $bdd)
{
$this->bdd = $bdd;
$this->model_user = new \models\User($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
$this->internal_setting = new \controllers\internals\Setting($bdd);
$this->internal_phone = new Phone($bdd);
}
/**
* Return a list of users by their ids
*
* @param array $ids : ids of entries to find
*
* @return array
*/
public function gets_in_by_id(array $ids)
{
return $this->model_user->gets_in_by_id($ids);
}
/**
* Return list of users as an array.
*
@ -180,27 +194,56 @@ namespace controllers\internals;
/**
* Update a user by his id.
*
* @param mixed $id
* @param mixed $email
* @param mixed $password
* @param mixed $admin
* @param mixed $api_key
* @param string $status : User status
* @param bool $encrypt_password : Should the password be encrypted, by default true
* @param mixed $id : User id
* @param array $user : Array of fields to update for user
* @param mixed (?array|bool) $quota : Quota to update for the user, by default null -> no update, if false, remove quota
*
* @return int : Number of modified user
* @return bool : True on success, false on error
*/
public function update($id, $email, $password, $admin, $api_key, $status, bool $encrypt_password = true)
public function update($id, array $user, $quota = null)
{
$user = [
'email' => $email,
'password' => $encrypt_password ? password_hash($password, PASSWORD_DEFAULT) : $password,
'admin' => $admin,
'api_key' => $api_key,
'status' => $status,
];
$internal_quota = new Quota($this->bdd);
$current_quota = $internal_quota->get_user_quota($id);
return $this->model_user->update($id, $user);
$this->bdd->beginTransaction();
$this->model_user->update($id, $user);
if ($current_quota && $quota === false)
{
$success = $internal_quota->delete_for_user($id, $current_quota['id']);
if (!$success)
{
$this->bdd->rollback();
return false;
}
}
if ($quota)
{
if ($current_quota)
{
$internal_quota->update_for_user($id, $current_quota['id'], $quota);
}
else
{
$success = $internal_quota->create($id, $quota['credit'], $quota['additional'], $quota['report_unused'], $quota['report_unused_additional'], $quota['auto_renew'], $quota['renew_interval'], new \DateTime($quota['start_date']), new \DateTime($quota['expiration_date']));
if (!$success)
{
$this->bdd->rollback();
return false;
}
}
}
if (!$this->bdd->commit())
{
return false;
}
return true;
}
/**
@ -212,10 +255,11 @@ namespace controllers\internals;
* @param ?string $api_key : The api key of the user, if null generate randomly
* @param string $status : User status, default \models\User::STATUS_ACTIVE
* @param bool $encrypt_password : Should the password be encrypted, by default true
* @param ?array $quota : Quota to create for the user, by default null -> no quota
*
* @return mixed bool|int : false on error, id of the new user else
*/
public function create($email, $password, $admin, ?string $api_key = null, string $status = \models\User::STATUS_ACTIVE, bool $encrypt_password = true)
public function create($email, $password, $admin, ?string $api_key = null, string $status = \models\User::STATUS_ACTIVE, bool $encrypt_password = true, ?array $quota = null)
{
$user = [
'email' => $email,
@ -225,22 +269,42 @@ namespace controllers\internals;
'status' => $status,
];
$new_id_user = $this->model_user->insert($user);
$this->bdd->beginTransaction();
$new_id_user = $this->model_user->insert($user);
if (!$new_id_user)
{
return false;
}
$success = $this->internal_setting->create_defaults_for_user($new_id_user);
$success = $this->internal_setting->create_defaults_for_user($new_id_user);
if (!$success)
{
$this->delete($new_id_user);
$this->bdd->rollback();
return false;
}
if ($quota !== null)
{
$internal_quota = new Quota($this->bdd);
$success = $internal_quota->create($new_id_user, $quota['credit'], $quota['additional'], $quota['report_unused'], $quota['report_unused_additional'], $quota['auto_renew'], $quota['renew_interval'], $quota['start_date'], $quota['expiration_date']);
if (!$success)
{
$this->bdd->rollback();
return false;
}
}
if (!$this->bdd->commit())
{
return false;
}
return $new_id_user;
}

View file

@ -17,6 +17,7 @@ namespace controllers\publics;
class User extends \descartes\Controller
{
private $internal_user;
private $internal_quota;
/**
* Cette fonction est appelée avant toute les autres :
@ -28,6 +29,7 @@ class User extends \descartes\Controller
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_user = new \controllers\internals\User($bdd);
$this->internal_quota = new \controllers\internals\Quota($bdd);
\controllers\internals\Tool::verifyconnect();
@ -58,7 +60,7 @@ class User extends \descartes\Controller
/**
* Update status of users.
*
* @param array int $_GET['ids'] : User ids
* @param array int $_GET['user_ids'] : User ids
* @param mixed $csrf
* @param int $status : 1 -> active, 0 -> suspended
*
@ -82,7 +84,7 @@ class User extends \descartes\Controller
$status = \models\User::STATUS_ACTIVE;
}
$ids = $_GET['ids'] ?? [];
$ids = $_GET['user_ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_user->update_status($id, $status);
@ -94,7 +96,7 @@ class User extends \descartes\Controller
/**
* Cette fonction va supprimer une liste de users.
*
* @param array int $_GET['ids'] : Les id des useres à supprimer
* @param array int $_GET['user_ids'] : Les id des useres à supprimer
* @param mixed $csrf
*
* @return boolean;
@ -115,7 +117,7 @@ class User extends \descartes\Controller
return $this->redirect(\descartes\Router::url('User', 'list'));
}
$ids = $_GET['ids'] ?? [];
$ids = $_GET['user_ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_user->delete($id);
@ -130,24 +132,27 @@ class User extends \descartes\Controller
public function add()
{
$now = new \DateTime();
$now_plus_one_month = clone $now;
$now_plus_one_month->add(new \DateInterval('P1M'));
$now = $now->format('Y-m-d H:i:00');
$now_plus_one_month = $now_plus_one_month->format('Y-m-d H:i:00');
return $this->render('user/add', ['now' => $now, 'now_plus_one_month' => $now_plus_one_month]);
return $this->render('user/add', ['now' => $now]);
}
/**
* Cette fonction insert un nouveau user.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['email'] : L'email de l'utilisateur
* @param string $_POST['email_confirm'] : Verif de l'email de l'utilisateur
* @param optional string $_POST['password'] : Le mot de passe de l'utilisateur (si vide, généré automatiquement)
* @param optional string $_POST['password_confirm'] : Confirmation du mot de passe de l'utilisateur
* @param optional boolean $_POST['admin'] : Si vrai, l'utilisateur est admin, si vide non
* @param string $_POST['email'] : User email
* @param optional string $_POST['password'] : User password, (if empty the password is randomly generated)
* @param optional boolean $_POST['admin'] : If true user is admin
* @param optional boolean $_POST['quota_enable'] : If true create a quota for the user
* @param boolean $_POST['quota_enable'] : If true create a quota for the user
* @param optional int $_POST['quota_credit'] : credit for quota
* @param optional int $_POST['quota_additional'] : additional credit
* @param optional string $_POST['quota_start_date'] : quota beginning date
* @param optional string $_POST['quota_renewal_interval'] : period to use on renewal to calculate new expiration date. Also use to calculate first expiration date.
* @param optional boolean $_POST['quota_auto_renew'] : Should the quota be automatically renewed on expiration
* @param optional boolean $_POST['quota_report_unused'] : Should unused credit be reported next month
* @param optional boolean $_POST['quota_report_unused_additional'] : Should unused additional credit be transfered next month
*/
public function create($csrf)
{
@ -162,6 +167,15 @@ class User extends \descartes\Controller
$password = !empty($_POST['password']) ? $_POST['password'] : \controllers\internals\Tool::generate_password(rand(6, 12));
$admin = $_POST['admin'] ?? false;
$status = 'active';
$quota_enable = $_POST['quota_enable'] ?? false;
$quota_credit = $_POST['quota_credit'] ?? false;
$quota_additional = $_POST['quota_additional'] ?? false;
$quota_start_date = $_POST['quota_start_date'] ?? false;
$quota_renew_interval = $_POST['quota_renew_interval'] ?? false;
$quota_auto_renew = $_POST['quota_auto_renew'] ?? false;
$quota_report_unused = $_POST['quota_report_unused'] ?? false;
$quota_report_unused_additional = $_POST['quota_report_unused_additional'] ?? false;
if (!$email)
{
@ -177,14 +191,49 @@ class User extends \descartes\Controller
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$id_user = $this->internal_user->create($email, $password, $admin);
//Forge quota for user if needed
$quota = null;
if ($quota_enable)
{
$quota = [];
$quota['credit'] = (int) $quota_credit;
$quota['additional'] = (int) $quota_additional;
if ($quota_start_date === false || !\controllers\internals\Tool::validate_date($quota_start_date, 'Y-m-d H:i:s'))
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez définir une date de début valide pour le quota.');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$quota['start_date'] = new \DateTime($quota_start_date);
if ($quota_renew_interval === false || !\controllers\internals\Tool::validate_period($quota_renew_interval))
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez définir une durée de quota parmis la liste proposée.');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$quota['renew_interval'] = $quota_renew_interval;
$quota['expiration_date'] = clone $quota['start_date'];
$quota['expiration_date']->add(new \DateInterval($quota_renew_interval));
$quota['auto_renew'] = (bool) $quota_auto_renew;
$quota['report_unused'] = (bool) $quota_report_unused;
$quota['report_unused_additional'] = (bool) $quota_report_unused_additional;
}
$id_user = $this->internal_user->create($email, $password, $admin, null, \models\User::STATUS_ACTIVE, true, $quota);
if (!$id_user)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce user.');
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer cet utilisateur.');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$mailer = new \controllers\internals\Mailer();
$email_send = $mailer->enqueue($email, EMAIL_CREATE_USER, ['email' => $email, 'password' => $password]);
if (!$email_send)
@ -196,4 +245,145 @@ class User extends \descartes\Controller
return $this->redirect(\descartes\Router::url('User', 'list'));
}
/**
* Return the edition page for the users
*
* @param int... $ids : users ids
*/
public function edit()
{
$ids = $_GET['user_ids'] ?? [];
$id_user = $_SESSION['user']['id'];
$users = $this->internal_user->gets_in_by_id($ids);
if (!$users)
{
return $this->redirect(\descartes\Router::url('User', 'list'));
}
foreach ($users as &$user)
{
$user['quota'] = $this->internal_quota->get_user_quota($user['id']);
}
$now = new \DateTime();
$now = $now->format('Y-m-d H:i:00');
$this->render('user/edit', [
'users' => $users,
'now' => $now,
]);
}
/**
* Update a list of users
*
* @param $csrf : Le jeton CSRF
* @param array $_POST['users'] : Array of the users and new values, id as key. Quota may also be defined.
*/
public function update($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$users = $_POST['users'] ?? [];
foreach ($users as $id_user => $user)
{
$email = $user['email'] ?? false;
$password = !empty($user['password']) ? $user['password'] : null;
$admin = $user['admin'] ?? false;
$quota_enable = $user['quota_enable'] ?? false;
$quota_consumed = $user['quota_consumed'] ?? false;
$quota_credit = $user['quota_credit'] ?? false;
$quota_additional = $user['quota_additional'] ?? false;
$quota_start_date = $user['quota_start_date'] ?? false;
$quota_renew_interval = $user['quota_renew_interval'] ?? false;
$quota_auto_renew = $user['quota_auto_renew'] ?? false;
$quota_report_unused = $user['quota_report_unused'] ?? false;
$quota_report_unused_additional = $user['quota_report_unused_additional'] ?? false;
if (!$email)
{
\FlashMessage\FlashMessage::push('danger', 'L\'utilisateur #' . (int) $id_user . ' n\'as pas pu être mis à jour car l\'adresse e-mail n\'as pas été fournie.');
continue;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL))
{
\FlashMessage\FlashMessage::push('danger', 'L\'utilisateur #' . (int) $id_user . ' n\'as pas pu être mis à jour car l\'adresse e-mail fournie n\'est pas valide.');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
//Forge quota for user if needed
$quota = false;
if ($quota_enable)
{
$quota = [];
$quota['credit'] = (int) $quota_credit;
$quota['consumed'] = (int) $quota_consumed;
$quota['additional'] = (int) $quota_additional;
if ($quota_start_date === false || !\controllers\internals\Tool::validate_date($quota_start_date, 'Y-m-d H:i:s'))
{
\FlashMessage\FlashMessage::push('danger', 'L\'utilisateur #' . (int) $id_user . ' n\'as pas pu être mis à jour car la date de début du quota associé n\'est pas valide.');
continue;
}
$quota['start_date'] = new \DateTime($quota_start_date);
if ($quota_renew_interval === false || !\controllers\internals\Tool::validate_period($quota_renew_interval))
{
\FlashMessage\FlashMessage::push('danger', 'L\'utilisateur #' . (int) $id_user . ' n\'as pas pu être mis à jour car la durée du quota associé n\'est pas valide.');
continue;
}
$quota['renew_interval'] = $quota_renew_interval;
$quota['expiration_date'] = clone $quota['start_date'];
$quota['expiration_date']->add(new \DateInterval($quota_renew_interval));
$quota['auto_renew'] = (bool) $quota_auto_renew;
$quota['report_unused'] = (bool) $quota_report_unused;
$quota['report_unused_additional'] = (bool) $quota_report_unused_additional;
//Format dates
$quota['start_date'] = $quota['start_date']->format('Y-m-d H:i:s');
$quota['expiration_date'] = $quota['expiration_date']->format('Y-m-d H:i:s');
}
$updated_user = [
'email' => $email,
'admin' => $admin,
];
if ($password)
{
$updated_user['password'] = $password;
}
$success = $this->internal_user->update($id_user, $updated_user, $quota);
if (!$success)
{
\FlashMessage\FlashMessage::push('danger', 'L\'utilisateur #' . (int) $id_user . ' n\'as pas pu être mis à jour.');
continue;
}
return $this->redirect(\descartes\Router::url('User', 'list'));
}
}
}