Move to raspisms dir

This commit is contained in:
osaajani 2020-02-18 04:29:48 +01:00
parent 34a6f7de65
commit 40fccf133c
278 changed files with 109 additions and 2020 deletions

View file

@ -1,119 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
/**
* Class to interact with adapters.
*/
class Adapter extends \descartes\InternalController
{
private const ADAPTERS_FILES_END = 'Adapter.php';
private const ADAPTERS_META_START = 'meta_';
/**
* List adapters using internal metas.
*
* @return array
*/
public function list_adapters()
{
$adapters = [];
$files = $this->list_files();
if (!$files)
{
return $adapters;
}
foreach ($files as $file)
{
$metas = $this->read_adapter_metas($file);
if (!$metas)
{
continue;
}
$adapters[] = $metas;
}
return $adapters;
}
/**
* List Adapters files.
*
* @return mixed (false|array) : array of adapters files path
*/
public function list_files()
{
if (!is_readable(PWD_ADAPTERS))
{
return false;
}
$adapters_files = [];
$files = scandir(PWD_ADAPTERS);
foreach ($files as $filename)
{
$len = mb_strlen(self::ADAPTERS_FILES_END);
$end = mb_substr($filename, -$len);
if (self::ADAPTERS_FILES_END !== $end)
{
continue;
}
$adapters_files[] = PWD_ADAPTERS . '/' . $filename;
}
return $adapters_files;
}
/**
* Read constants of an adapter.
*
* @param mixed $adapter_file
*
* @return mixed(array|bool) : False on error, array of constants name => value
*/
public function read_adapter_metas($adapter_file)
{
$metas = [];
if (!is_readable($adapter_file))
{
return false;
}
$adapter_classname = pathinfo($adapter_file, PATHINFO_FILENAME);
$reflection_class = new \ReflectionClass('\adapters\\' . $adapter_classname);
if (!$reflection_class)
{
return false;
}
$methods = $reflection_class->getMethods(\ReflectionMethod::IS_STATIC);
foreach ($methods as $method)
{
$start_with = mb_substr($method->getName(), 0, mb_strlen(self::ADAPTERS_META_START));
if (self::ADAPTERS_META_START !== $start_with)
{
continue;
}
$metas[$method->getName()] = $method->invoke(null);
}
return $metas;
}
}

View file

@ -1,151 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Command extends StandardController
{
protected $model;
/**
* Create a new command.
*
* @param int $id_user : User id
* @param string $name : Command name
* @param string $script : Script file
* @param bool $admin : Is command admin only
*
* @return mixed bool|int : False if cannot create command, id of the new command else
*/
public function create(int $id_user, string $name, string $script, bool $admin)
{
$command = [
'id_user' => $id_user,
'name' => $name,
'script' => $script,
'admin' => $admin,
];
$result = $this->get_model()->insert($command);
if (!$result)
{
return false;
}
$internal_event = new Event($this->bdd);
$internal_event->create($id_user, 'COMMAND_ADD', 'Ajout commande : ' . $name . ' => ' . $script);
return $result;
}
/**
* Update a command.
*
* @param int $id_user : User id
* @param int $id : Command id
* @param string $name : Command name
* @param string $script : Script file
* @param bool $admin : Is command admin only
*
* @return mixed bool|int : False if cannot create command, id of the new command else
*/
public function update_for_user(int $id_user, int $id, string $name, string $script, bool $admin)
{
$datas = [
'name' => $name,
'script' => $script,
'admin' => $admin,
];
return $this->get_model()->update_for_user($id_user, $id, $datas);
}
/**
* Analyse a message to check if it's a command and extract it.
*
* @param int $id_user : User id to search a command for
* @param string $message : Text of the message to analyse
*
* @return mixed : false on error, array with new text and command to execute ['updated_text' => string, 'command' => string]
*/
public function check_for_command(int $id_user, string $message)
{
$extracted_command = [];
$decode_message = json_decode(trim($message), true);
if (null === $decode_message)
{
return false;
}
if (!isset($decode_message['login'], $decode_message['password'], $decode_message['command']))
{
return false;
}
//Check for user
$internal_user = new \controllers\internals\User($this->bdd);
$user = $internal_user->check_credentials($decode_message['login'], $decode_message['password']);
if (!$user || $user['id'] !== $id_user)
{
return false;
}
//Find command
$commands = $this->gets_for_user($user['id']);
$find_command = false;
foreach ($commands as $command)
{
if ($decode_message['command'] === $command['name'])
{
$find_command = $command;
break;
}
}
if (false === $find_command)
{
return false;
}
//Check for admin rights
if ($find_command['admin'] && !$user['admin'])
{
return false;
}
//Forge command and return
$decode_message['password'] = '******';
$updated_text = json_encode($decode_message);
$generated_command = PWD_SCRIPTS . '/' . $find_command['script'];
$args = $decode_message['args'] ?? '';
$generated_command .= ' ' . escapeshellcmd($args);
return [
'updated_text' => $updated_text,
'command' => $generated_command,
];
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Command($this->bdd);
return $this->model;
}
}

View file

@ -1,142 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class ConditionalGroup extends StandardController
{
protected $model;
/**
* Create a new group for a user.
*
* @param int $id_user : user id
* @param string $name : Group name
* @param string $condition : Condition for forming group content
*
* @return mixed bool|int : false on error, new group id
*/
public function create(int $id_user, string $name, string $condition)
{
$conditional_group = [
'id_user' => $id_user,
'name' => $name,
'condition' => $condition,
];
$internal_ruler = new Ruler();
$valid_condition = $internal_ruler->validate_condition($condition, ['contact' => (object) ['datas' => (object) null]]);
if (!$valid_condition)
{
return false;
}
$id_group = $this->get_model()->insert($conditional_group);
if (!$id_group)
{
return false;
}
$internal_event = new Event($this->bdd);
$internal_event->create($id_user, 'CONDITIONAL_GROUP_ADD', 'Ajout du groupe conditionnel : ' . $name);
return $id_group;
}
/**
* Update a group for a user.
*
* @param int $id_user : User id
* @param int $id_group : Group id
* @param string $name : Group name
* @param string $condition : Condition for forming group content
*
* @return bool : False on error, true on success
*/
public function update_for_user(int $id_user, int $id_group, string $name, string $condition)
{
$conditional_group = [
'name' => $name,
'condition' => $condition,
];
$internal_ruler = new Ruler();
$valid_condition = $internal_ruler->validate_condition($condition, ['contact' => (object) ['datas' => (object) null]]);
if (!$valid_condition)
{
return false;
}
$result = $this->get_model()->update_for_user($id_user, $id_group, $conditional_group);
if (!$result)
{
return false;
}
return true;
}
/**
* Return a group by his name for a user.
*
* @param int $id_user : User id
* @param string $name : Group name
*
* @return array
*/
public function get_by_name_for_user(int $id_user, string $name)
{
return $this->get_model()->get_by_name_for_user($id_user, $name);
}
/**
* Gets the user's contacts that respects a condition.
*
* @param int $id_user : User id
* @param string $condition : Condition string to verify
*
* @return array
*/
public function get_contacts_for_condition_and_user(int $id_user, string $condition): array
{
$internal_contacts = new Contact($this->bdd);
$contacts = $internal_contacts->gets_for_user($id_user);
$ruler = new Ruler();
foreach ($contacts as $key => $contact)
{
$contact['datas'] = json_decode($contact['datas']);
$contact = (object) $contact;
$datas = ['contact' => $contact];
$is_valid = $ruler->evaluate_condition($condition, $datas);
if (!$is_valid)
{
unset($contacts[$key]);
}
}
return $contacts;
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\ConditionalGroup($this->bdd);
return $this->model;
}
}

View file

@ -1,102 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
/**
* Class to call the console scripts.
*/
class Console extends \descartes\InternalController
{
/**
* Start launcher daemon.
*/
public function launcher()
{
new \daemons\Launcher();
}
/**
* Start sender daemon.
*/
public function sender()
{
new \daemons\Sender();
}
/**
* Start webhook daemon.
*/
public function webhook()
{
new \daemons\Webhook();
}
/**
* Start a phone daemon.
*
* @param $id_phone : Phone id
*/
public function phone($id_phone)
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, 'UTF8');
$internal_phone = new \controllers\internals\Phone($bdd);
$phone = $internal_phone->get($id_phone);
if (!$phone)
{
return false;
}
new \daemons\Phone($phone);
}
/**
* Cette fonction retourne la fenetre de connexion.
*
* @param mixed $id_phone
*/
public function test($id_phone)
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, 'UTF8');
$internal_phone = new \controllers\internals\Phone($bdd);
$phone = $internal_phone->get($id_phone);
if (!$phone)
{
echo "No phone for id : {$id_phone}\n";
return false;
}
echo "Found phone for id : {$id_phone}\n";
$adapter_classname = $phone['adapter'];
$adapter = new $adapter_classname($phone['number'], $phone['adapter_datas']);
//Try send a message
/*
$destination = '+33669529042';
$text = "Coucou c'est pour un test !";
$flash = false;
$uid = $adapter->send($destination, $text, $flash);
if (!$uid)
{
echo "Cannot send message to $destination\n";
return false;
}
echo "Send a message to $destination with uid $uid \n";
*/
$smss = $adapter->read();
var_dump($smss);
}
}

View file

@ -1,351 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Contact extends StandardController
{
protected $model;
/**
* Return a contact for a user by a number.
*
* @param int $id_user : user id
* @param string $number : Contact number
*
* @return array
*/
public function get_by_number_and_user(int $id_user, string $number)
{
return $this->get_model()->get_by_number_and_user($id_user, $number);
}
/**
* Return a contact by his name for a user.
*
* @param int $id_user : User id
* @param string $name : Contact name
*
* @return array
*/
public function get_by_name_and_user(int $id_user, string $name)
{
return $this->get_model()->get_by_name_and_user($id_user, $name);
}
/**
* Return all contacts of a user.
*
* @param int $id_user : user id
*
* @return array
*/
public function gets_for_user(int $id_user)
{
return $this->get_model()->gets_for_user($id_user);
}
/**
* Create a new contact.
*
* @param int $id_user : User id
* @param string $number : Contact number
* @param string $name : Contact name
* @param string $datas : Contact datas
*
* @return mixed bool|int : False if cannot create contact, id of the new contact else
*/
public function create($id_user, $number, $name, $datas)
{
$contact = [
'id_user' => $id_user,
'number' => $number,
'name' => $name,
'datas' => $datas,
];
$result = $this->get_model()->insert($contact);
if (!$result)
{
return $result;
}
$internal_event = new Event($this->bdd);
$internal_event->create($id_user, 'CONTACT_ADD', 'Ajout contact : ' . $name . ' (' . \controllers\internals\Tool::phone_format($number) . ')');
return $result;
}
/**
* Update a contact.
*
* @param int $id_user : User id
* @param int $id : Contact id
* @param string $number : Contact number
* @param string $name : Contact name
* @param ?string $datas : Contact datas
*
* @return int : number of modified rows
*/
public function update_for_user(int $id_user, int $id, string $number, string $name, string $datas)
{
$contact = [
'number' => $number,
'name' => $name,
'datas' => $datas,
];
return $this->get_model()->update_for_user($id_user, $id, $contact);
}
/**
* Import a list of contacts as csv.
*
* @param resource $file_handler : File handler to import contacts from
* @param int $id_user : User id
*
* @return mixed : False on error, number of inserted contacts else
*/
public function import_csv(int $id_user, $file_handler)
{
if (!\is_resource($file_handler))
{
return false;
}
$nb_insert = 0;
$head = null;
while ($line = fgetcsv($file_handler))
{
if (null === $head)
{
$head = $line;
continue;
}
$line = array_combine($head, $line);
if (false === $line)
{
continue;
}
if (!isset($line['name'], $line['number']))
{
continue;
}
$datas = [];
foreach ($line as $key => $value)
{
if ('name' === $key || 'number' === $key)
{
continue;
}
if ('' === $value)
{
continue;
}
$key = mb_ereg_replace('[\W]', '', $key);
$datas[$key] = $value;
}
$datas = json_encode($datas);
$success = $this->create($id_user, $line['number'], $line['name'], $datas);
if ($success)
{
++$nb_insert;
}
}
return $nb_insert;
}
/**
* Import a list of contacts as json.
*
* @param resource $file_handler : File handler to import contacts from
* @param int $id_user : User id
*
* @return mixed : False on error, number of inserted contacts else
*/
public function import_json(int $id_user, $file_handler)
{
if (!\is_resource($file_handler))
{
return false;
}
$file_content = '';
while ($line = fgets($file_handler))
{
$file_content .= $line;
}
try
{
$contacts = json_decode($file_content, true);
if (!\is_array($contacts))
{
return false;
}
$nb_insert = 0;
foreach ($contacts as $contact)
{
if (!\is_array($contact))
{
continue;
}
if (!isset($contact['name'], $contact['number']))
{
continue;
}
$datas = $contact['datas'] ?? [];
$datas = json_encode($datas);
$success = $this->create($id_user, $contact['number'], $contact['name'], $datas);
if ($success)
{
++$nb_insert;
}
}
return $nb_insert;
}
catch (\Exception $e)
{
return false;
}
}
/**
* Export the contacts of a user as csv.
*
* @param int $id_user : User id
*
* @return array : ['headers' => array of headers to return, 'content' => the generated file]
*/
public function export_csv(int $id_user): array
{
$contacts = $this->get_model()->gets_for_user($id_user);
$columns = [
'name',
'number',
];
foreach ($contacts as $contact)
{
$datas = json_decode($contact['datas'], true);
foreach ($datas as $key => $value)
{
$columns[] = $key;
}
}
$columns = array_unique($columns);
$lines = [];
foreach ($contacts as $contact)
{
$datas = json_decode($contact['datas'], true);
$line = [];
foreach ($columns as $column)
{
if (isset($contact[$column]))
{
$line[] = $contact[$column];
continue;
}
if (isset($datas[$column]))
{
$line[] = $datas[$column];
continue;
}
$line[] = null;
}
$lines[] = $line;
}
//Php only support csv formatting to file. To get it in string we need to create a tmp in memory file, write in it, and then read the file into a var
// output up to 5MB is kept in memory, if it becomes bigger it will automatically be written to a temporary file
$csv_tmp_file = fopen('php://temp/maxmemory:' . (5 * 1024 * 1024), 'r+');
fputcsv($csv_tmp_file, $columns);
foreach ($lines as $line)
{
fputcsv($csv_tmp_file, $line);
}
rewind($csv_tmp_file);
$csv_string = stream_get_contents($csv_tmp_file);
return [
'headers' => [
'Content-Disposition: attachment; filename=contacts.csv',
'Content-Type: text/csv',
'Content-Length: ' . mb_strlen($csv_string),
],
'content' => $csv_string,
];
}
/**
* Export the contacts of a user as json.
*
* @param int $id_user : User id
*
* @return array : ['headers' => array of headers to return, 'content' => the generated file]
*/
public function export_json(int $id_user): array
{
$contacts = $this->get_model()->gets_for_user($id_user);
foreach ($contacts as &$contact)
{
unset($contact['id'], $contact['id_user']);
$contact['datas'] = json_decode($contact['datas']);
}
$content = json_encode($contacts);
return [
'headers' => [
'Content-Disposition: attachment; filename=contacts.json',
'Content-Type: application/json',
'Content-Length: ' . mb_strlen($content),
],
'content' => $content,
];
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Contact($this->bdd);
return $this->model;
}
}

View file

@ -1,70 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Event extends StandardController
{
protected $model;
/**
* Disabled methods.
*/
public function update_for_user()
{
return false;
}
/**
* Gets lasts x events for a user order by date.
*
* @param int $id_user : User id
* @param int $nb_entry : Number of events to return
*
* @return array
*/
public function get_lasts_by_date_for_user(int $id_user, int $nb_entry)
{
return $this->get_model()->get_lasts_by_date_for_user($id_user, $nb_entry);
}
/**
* Create a new event.
*
* @param int $id_user : user id
* @param mixed $type
* @param mixed $text
*
* @return mixed bool : false on fail, new event id else
*/
public function create($id_user, $type, $text)
{
$event = [
'id_user' => $id_user,
'type' => $type,
'text' => $text,
];
return $this->get_model()->insert($event);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Event($this->bdd);
return $this->model;
}
}

View file

@ -1,30 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
class ExpressionProvider implements ExpressionFunctionProviderInterface
{
public function getFunctions()
{
return [
ExpressionFunction::fromPhp('is_null', 'exists'),
ExpressionFunction::fromPhp('mb_strtolower', 'lower'),
ExpressionFunction::fromPhp('mb_strtoupper', 'upper'),
ExpressionFunction::fromPhp('mb_substr', 'substr'),
ExpressionFunction::fromPhp('abs', 'abs'),
ExpressionFunction::fromPhp('strtotime', 'date'),
];
}
}

View file

@ -1,141 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
/**
* Classe des groups.
*/
class Group extends StandardController
{
protected $model;
/**
* Create a new group for a user.
*
* @param int $id_user : user id
* @param stirng $name : Group name
* @param array $contacts_ids : Ids of the contacts of the group
*
* @return mixed bool|int : false on error, new group id
*/
public function create(int $id_user, string $name, array $contacts_ids)
{
$group = [
'id_user' => $id_user,
'name' => $name,
];
$id_group = $this->get_model()->insert($group);
if (!$id_group)
{
return false;
}
$internal_contact = new Contact($this->bdd);
foreach ($contacts_ids as $contact_id)
{
$contact = $internal_contact->get_for_user($id_user, $contact_id);
if (!$contact)
{
continue;
}
$this->get_model()->insert_group_contact_relation($id_group, $contact_id);
}
$internal_event = new Event($this->bdd);
$internal_event->create($id_user, 'GROUP_ADD', 'Ajout group : ' . $name);
return $id_group;
}
/**
* Update a group for a user.
*
* @param int $id_user : User id
* @param int $id_group : Group id
* @param stirng $name : Group name
* @param array $contacts_ids : Ids of the contacts of the group
*
* @return bool : False on error, true on success
*/
public function update_for_user(int $id_user, int $id_group, string $name, array $contacts_ids)
{
$group = [
'name' => $name,
];
$result = $this->get_model()->update_for_user($id_user, $id_group, $group);
$this->get_model()->delete_group_contact_relations($id_group);
$internal_contact = new Contact($this->bdd);
$nb_contact_insert = 0;
foreach ($contacts_ids as $contact_id)
{
$contact = $internal_contact->get_for_user($id_user, $contact_id);
if (!$contact)
{
continue;
}
if ($this->get_model()->insert_group_contact_relation($id_group, $contact_id))
{
++$nb_contact_insert;
}
}
if (!$result && $nb_contact_insert !== \count($contacts_ids))
{
return false;
}
return true;
}
/**
* Return a group by his name for a user.
*
* @param int $id_user : User id
* @param string $name : Group name
*
* @return array
*/
public function get_by_name_for_user(int $id_user, string $name)
{
return $this->get_model()->get_by_name_for_user($id_user, $name);
}
/**
* Get groups contacts.
*
* @param int $id_group : Group id
*
* @return array : Contacts of the group
*/
public function get_contacts($id_group)
{
return $this->get_model()->get_contacts($id_group);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Group($this->bdd);
return $this->model;
}
}

View file

@ -1,141 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Media extends StandardController
{
protected $model;
/**
* Create a media.
*
* @param int $id_user : Id of the user
* @param int $id_scheduled : Id of the scheduled
* @param array $media : $_FILES media array
*
* @return bool : false on error, new media id else
*/
public function create(int $id_user, int $id_scheduled, array $media): bool
{
$internal_scheduled = new Scheduled($this->bdd);
$scheduled = $internal_scheduled->get_for_user($id_user, $id_scheduled);
if (!$scheduled)
{
return false;
}
$result_upload_media = \controllers\internals\Tool::upload_file($media);
if (false === $result_upload_media['success'])
{
return false;
}
$datas = [
'id_scheduled' => $id_scheduled,
'path' => $result_upload_media['content'],
];
return (bool) $this->get_model()->insert($datas);
}
/**
* Update a media for a user.
*
* @param int $id_user : user id
* @param int $id_media : Media id
* @param int $id_scheduled : Id of the scheduled
* @param string $path : Path of the file
*
* @return bool : false on error, true on success
*/
public function update_for_user(int $id_user, int $id_media, int $id_scheduled, string $path): bool
{
$media = [
'id_scheduled' => $id_scheduled,
'path' => $path,
];
$internal_scheduled = new Scheduled($this->bdd);
$scheduled = $this->get_for_user($id_user, $id_scheduled);
if (!$scheduled)
{
return false;
}
return (bool) $this->get_model()->update_for_user($id_user, $id_media, $media);
}
/**
* Delete a media for a user.
*
* @param int $id_user : User id
* @param int $id : Entry id
*
* @return int : Number of removed rows
*/
public function delete_for_user(int $id_user, int $id_media): bool
{
$media = $this->get_model()->get_for_user($id_user, $id_media);
if (!$media)
{
return false;
}
unlink($media['path']);
return $this->get_model()->delete_for_user($id_user, $id_media);
}
/**
* Delete a media for a scheduled and a user.
*
* @param int $id_user : User id
* @param int $id_scheduled : Scheduled id to delete medias for
*
* @return int : Number of removed rows
*/
public function delete_for_scheduled_and_user(int $id_user, int $id_scheduled): bool
{
$media = $this->get_model()->get_for_scheduled_and_user($id_user, $id_scheduled);
if ($media)
{
unlink($media['path']);
}
return $this->get_model()->delete_for_scheduled_and_user($id_user, $id_scheduled);
}
/**
* Find medias for a scheduled and a user.
*
* @param int $id_user : User id
* @param int $id_scheduled : Scheduled id to delete medias for
*
* @return mixed : Medias || false
*/
public function get_for_scheduled_and_user(int $id_user, int $id_scheduled)
{
return $this->get_model()->get_for_scheduled_and_user($id_user, $id_scheduled);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Media($this->bdd);
return $this->model;
}
}

View file

@ -1,111 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Phone extends StandardController
{
protected $model;
/**
* Return all phones of a user.
*
* @param int $id_user : user id
*
* @return array
*/
public function gets_for_user(int $id_user)
{
return $this->get_model()->gets_for_user($id_user);
}
/**
* Return a phone by his number.
*
* @param string $number : Phone number
*
* @return array
*/
public function get_by_number(string $number)
{
return $this->get_model()->get_by_number($number);
}
/**
* Return a phone for a user by a number.
*
* @param int $id_user : user id
* @param string $number : Phone number
*
* @return array
*/
public function get_by_number_and_user(int $id_user, string $number)
{
return $this->get_model()->get_by_number_and_user($id_user, $number);
}
/**
* Create a phone.
*
* @param int $id_user : User to insert phone for
* @param string $number : The number of the phone
* @param string $adapter : The adapter to use the phone
* @param string json $adapter_datas : A JSON string representing adapter's datas (for example credentials for an api)
*
* @return bool : false on error, true on success
*/
public function create(int $id_user, string $number, string $adapter, string $adapter_datas): bool
{
$phone = [
'id_user' => $id_user,
'number' => $number,
'adapter' => $adapter,
'adapter_datas' => $adapter_datas,
];
return (bool) $this->get_model()->insert($phone);
}
/**
* Update a phone.
*
* @param int $id_user : User to insert phone for
* @param int $id : Phone id
* @param string $number : The number of the phone
* @param string $adapter : The adapter to use the phone
* @param array $adapter_datas : An array of the datas of the adapter (for example credentials for an api)
*
* @return bool : false on error, true on success
*/
public function update_for_user(int $id_user, int $id, string $number, string $adapter, array $adapter_datas): bool
{
$phone = [
'id_user' => $id_user,
'number' => $number,
'adapter' => $adapter,
'adapter_datas' => json_encode($adapter_datas),
];
return (bool) $this->get_model()->update_for_user($id_user, $id, $phone);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Phone($this->bdd);
return $this->model;
}
}

View file

@ -1,242 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Received extends StandardController
{
protected $model;
/**
* Return the list of unread messages for a user.
*
* @param int $id_user : User id
* @param ?int $nb_entry : Number of entry to return
* @param ?int $page : Pagination, used to calcul offset, $nb_entry * $page
*
* @return array : Entrys list
*/
public function list_unread_for_user(int $id_user, ?int $nb_entry = null, ?int $page = null)
{
return $this->get_model()->list_unread_for_user($id_user, $nb_entry, $nb_entry * $page);
}
/**
* Create a received.
*
* @param $at : Reception date
* @param $text : Text of the message
* @param string $origin : Number of the sender
* @param string $destination : Number of the receiver
* @param string $status : Status of the received message
* @param bool $command : Is the sms a command
*
* @return bool : false on error, new received id else
*/
public function create($at, string $text, string $origin, string $destination, string $status = 'unread', bool $command = false): bool
{
$received = [
'at' => $at,
'text' => $text,
'origin' => $origin,
'destination' => $destination,
'status' => $status,
'command' => $command,
];
return (bool) $this->get_model()->insert($received);
}
/**
* Update a received for a user.
*
* @param int $id_user : user id
* @param int $id_received : received id
* @param $at : Reception date
* @param $text : Text of the message
* @param string $origin : Number of the sender
* @param string $destination : Number of the receiver
* @param string $status : Status of the received message
* @param bool $command : Is the sms a command
*
* @return bool : false on error, true on success
*/
public function update_for_user(int $id_user, int $id_received, $at, string $text, string $origin, string $destination, string $status = 'unread', bool $command = false): bool
{
$received = [
'at' => $at,
'text' => $text,
'origin' => $origin,
'destination' => $destination,
'status' => $status,
'command' => $command,
];
return (bool) $this->get_model()->update_for_user($id_user, $id_received, $received);
}
/**
* Update a received message for a user to mark the message as read.
*
* @param int $id_user : user id
* @param int $id_received : received id
*
* @return bool : false on error, true on success
*/
public function mark_as_read_for_user(int $id_user, int $id_received): bool
{
$received = [
'status' => 'read',
];
return (bool) $this->get_model()->update_for_user($id_user, $id_received, $received);
}
/**
* Update a received message for a user to mark the message as unread.
*
* @param int $id_user : user id
* @param int $id_received : received id
*
* @return bool : false on error, true on success
*/
public function mark_as_unread_for_user(int $id_user, int $id_received): bool
{
$received = [
'status' => 'unread',
];
return (bool) $this->get_model()->update_for_user($id_user, $id_received, $received);
}
/**
* Return number of unread messages for a user.
*
* @param int $id_user : User id
*
* @return array
*/
public function count_unread_for_user(int $id_user)
{
return $this->get_model()->count_unread_for_user($id_user);
}
/**
* Return x last receiveds message for a user, order by date.
*
* @param int $id_user : User id
* @param int $nb_entry : Number of receiveds messages to return
*
* @return array
*/
public function get_lasts_by_date_for_user(int $id_user, int $nb_entry)
{
return $this->get_model()->get_lasts_by_date_for_user($id_user, $nb_entry);
}
/**
* Return receiveds for an origin and a user.
*
* @param int $id_user : User id
* @param string $origin : Number who sent the message
*
* @return array
*/
public function gets_by_origin_and_user(int $id_user, string $origin)
{
return $this->get_model()->gets_by_origin_and_user($id_user, $origin);
}
/**
* Get number of sended SMS for every date since a date for a specific user.
*
* @param int $id_user : user id
* @param \DateTime $date : Date since which we want the messages
*
* @return array
*/
public function count_by_day_since_for_user(int $id_user, $date)
{
$counts_by_day = $this->get_model()->count_by_day_since_for_user($id_user, $date);
$return = [];
foreach ($counts_by_day as $count_by_day)
{
$return[$count_by_day['at_ymd']] = $count_by_day['nb'];
}
return $return;
}
/**
* Return all discussions (ie : numbers we have a message received from or sended to) for a user.
*
* @param int $id_user : User id
*
* @return array
*/
public function get_discussions_for_user(int $id_user)
{
return $this->get_model()->get_discussions_for_user($id_user);
}
/**
* Get SMS received since a date for a user.
*
* @param int $id_user : User id
* @param $date : La date depuis laquelle on veux les SMS (au format 2014-10-25 20:10:05)
*
* @return array : Tableau avec tous les SMS depuis la date
*/
public function get_since_by_date_for_user(int $id_user, $date)
{
return $this->get_model()->get_since_by_date_for_user($id_user, $date);
}
/**
* Find messages received since a date for a certain origin and user.
*
* @param int $id_user : User id
* @param $date : Date we want messages sinces
* @param string $origin : Origin number
*
* @return array
*/
public function get_since_by_date_for_origin_and_user(int $id_user, $date, string $origin)
{
return $this->get_model()->get_since_by_date_for_origin_and_user($id_user, $date, $origin);
}
/**
* Find destination of last received message for an origin and user.
*
* @param int $id_user : User id
* @param string $origin : Origin number
*
* @return array
*/
public function get_last_for_origin_and_user(int $id_user, string $origin)
{
return $this->get_model()->get_last_for_origin_and_user($id_user, $origin);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Received($this->bdd);
return $this->model;
}
}

View file

@ -1,77 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
/**
* Class to analyse rules used by conditional groups.
*/
class Ruler extends \descartes\InternalController
{
private $expression_language;
/**
* Constructor.
*/
public function __construct()
{
$this->expression_language = new ExpressionLanguage();
//Add custom functions
$this->expression_language->registerProvider(new ExpressionProvider());
}
/**
* Verify if a condition is valid. i.e we can evaluate it without error.
*
* @param string $condition : The condition to evaluate
* @param array $datas : The datas to made available to condition
*
* @return bool : false if invalid, true else
*/
public function validate_condition(string $condition, array $datas = []): bool
{
try
{
$this->expression_language->evaluate($condition, $datas);
return true;
}
catch (\Exception $e)
{
return false;
}
}
/**
* Evaluate a condition.
*
* @param string $condition : The condition to evaluate
* @param array $datas : The datas to made available to condition
*
* @return ?bool : false if invalid, true else, null only on error
*/
public function evaluate_condition(string $condition, array $datas = []): ?bool
{
try
{
$result = $this->expression_language->evaluate($condition, $datas);
return (bool) $result;
}
catch (\Exception $e)
{
return null;
}
}
}

View file

@ -1,427 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Scheduled extends StandardController
{
protected $model;
/**
* Create a scheduled.
*
* @param int $id_user : User to insert scheduled for
* @param $at : Scheduled date to send
* @param string $text : Text of the message
* @param ?string $origin : Origin number of the message, null by default
* @param bool $flash : Is the sms a flash sms, by default false
* @param array $numbers : Numbers to send message to
* @param array $contacts_ids : Contact ids to send message to
* @param array $groups_ids : Group ids to send message to
* @param array $conditional_group_ids : Conditional Groups ids to send message to
*
* @return bool : false on error, new id on success
*/
public function create(int $id_user, $at, string $text, ?string $origin = null, bool $flash = false, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [])
{
$scheduled = [
'id_user' => $id_user,
'at' => $at,
'text' => $text,
'origin' => $origin,
'flash' => $flash,
];
if ($origin)
{
$internal_phone = new Phone($this->bdd);
$find_phone = $internal_phone->get_by_number_and_user($id_user, $origin);
if (!$find_phone)
{
return false;
}
}
$id_scheduled = $this->get_model()->insert($scheduled);
if (!$id_scheduled)
{
$date = date('Y-m-d H:i:s');
$internal_event = new Event($this->bdd);
$internal_event->create($id_user, 'SCHEDULED_ADD', 'Ajout d\'un Sms pour le ' . $date . '.');
return false;
}
foreach ($numbers as $number)
{
$this->get_model()->insert_scheduled_number($id_scheduled, $number);
}
$internal_contact = new Contact($this->bdd);
foreach ($contacts_ids as $contact_id)
{
$find_contact = $internal_contact->get_for_user($id_user, $contact_id);
if (!$find_contact)
{
continue;
}
$this->get_model()->insert_scheduled_contact_relation($id_scheduled, $contact_id);
}
$internal_group = new Group($this->bdd);
foreach ($groups_ids as $group_id)
{
$find_group = $internal_group->get_for_user($id_user, $group_id);
if (!$find_group)
{
continue;
}
$this->get_model()->insert_scheduled_group_relation($id_scheduled, $group_id);
}
$internal_conditional_group = new ConditionalGroup($this->bdd);
foreach ($conditional_group_ids as $conditional_group_id)
{
$find_group = $internal_conditional_group->get_for_user($id_user, $conditional_group_id);
if (!$find_group)
{
continue;
}
$this->get_model()->insert_scheduled_conditional_group_relation($id_scheduled, $conditional_group_id);
}
return $id_scheduled;
}
/**
* Update a scheduled.
*
* @param int $id_user : User to insert scheduled for
* @param int $id_scheduled : Scheduled id
* @param $at : Scheduled date to send
* @param string $text : Text of the message
* @param ?string $origin : Origin number of the message, null by default
* @param bool $flash : Is the sms a flash sms, by default false
* @param array $numbers : Numbers to send message to
* @param array $contacts_ids : Contact ids to send message to
* @param array $groups_ids : Group ids to send message to
* @param array $conditional_group_ids : Conditional Groups ids to send message to
*
* @return bool : false on error, new id on success
*/
public function update_for_user(int $id_user, int $id_scheduled, $at, string $text, ?string $origin = null, bool $flash = false, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [])
{
$scheduled = [
'id_user' => $id_user,
'at' => $at,
'text' => $text,
'origin' => $origin,
'flash' => $flash,
];
if ($origin)
{
$internal_phone = new Phone($this->bdd);
$find_phone = $internal_phone->get_by_number_and_user($id_user, $origin);
if (!$find_phone)
{
return false;
}
}
$success = (bool) $this->get_model()->update_for_user($id_user, $id_scheduled, $scheduled);
$this->get_model()->delete_scheduled_numbers($id_scheduled);
$this->get_model()->delete_scheduled_contact_relations($id_scheduled);
$this->get_model()->delete_scheduled_group_relations($id_scheduled);
$this->get_model()->delete_scheduled_conditional_group_relations($id_scheduled);
foreach ($numbers as $number)
{
$this->get_model()->insert_scheduled_number($id_scheduled, $number);
}
$internal_contact = new Contact($this->bdd);
foreach ($contacts_ids as $contact_id)
{
$find_contact = $internal_contact->get_for_user($id_user, $contact_id);
if (!$find_contact)
{
continue;
}
$this->get_model()->insert_scheduled_contact_relation($id_scheduled, $contact_id);
}
$internal_group = new Group($this->bdd);
foreach ($groups_ids as $group_id)
{
$find_group = $internal_group->get_for_user($id_user, $group_id);
if (!$find_group)
{
continue;
}
$this->get_model()->insert_scheduled_group_relation($id_scheduled, $group_id);
}
$internal_conditional_group = new ConditionalGroup($this->bdd);
foreach ($conditional_group_ids as $conditional_group_id)
{
$find_group = $internal_conditional_group->get_for_user($id_user, $conditional_group_id);
if (!$find_group)
{
continue;
}
$this->get_model()->insert_scheduled_conditional_group_relation($id_scheduled, $conditional_group_id);
}
return true;
}
/**
* Get messages scheduled before a date for a number and a user.
*
* @param int $id_user : User id
* @param $date : Date before which we want messages
* @param string $number : Number for which we want messages
*
* @return array
*/
public function gets_before_date_for_number_and_user(int $id_user, $date, string $number)
{
return $this->get_model()->gets_before_date_for_number_and_user($id_user, $date, $number);
}
/**
* Get all messages to send and the number to use to send theme.
*
* @return array : [['id_scheduled', 'text', 'origin', 'destination', 'flash'], ...]
*/
public function get_smss_to_send()
{
$smss_to_send = [];
$internal_templating = new \controllers\internals\Templating();
$internal_setting = new \controllers\internals\Setting($this->bdd);
$internal_group = new \controllers\internals\Group($this->bdd);
$internal_conditional_group = new \controllers\internals\ConditionalGroup($this->bdd);
$internal_phone = new \controllers\internals\Phone($this->bdd);
$users_settings = [];
$users_phones = [];
$now = new \DateTime();
$now = $now->format('Y-m-d H:i:s');
$scheduleds = $this->get_model()->gets_before_date($now);
foreach ($scheduleds as $scheduled)
{
if (!isset($users_settings[$scheduled['id_user']]))
{
$users_settings[$scheduled['id_user']] = [];
$settings = $internal_setting->gets_for_user($scheduled['id_user']);
foreach ($settings as $name => $value)
{
$users_settings[$scheduled['id_user']][$name] = $value;
}
}
if (!isset($users_phones[$scheduled['id_user']]))
{
$phones = $internal_phone->gets_for_user($scheduled['id_user']);
$users_phones[$scheduled['id_user']] = $phones ? $phones : [];
}
$messages = [];
//Add messages for numbers
$numbers = $this->get_numbers($scheduled['id']);
foreach ($numbers as $number)
{
$message = [
'id_user' => $scheduled['id_user'],
'id_scheduled' => $scheduled['id'],
'origin' => $scheduled['origin'],
'destination' => $number['number'],
'flash' => $scheduled['flash'],
];
if (null === $message['origin'])
{
$k = array_rand($users_phones[$scheduled['id_user']]);
$rnd_phone = $users_phones[$scheduled['id_user']][$k];
$message['origin'] = $rnd_phone['number'];
}
if ((int) ($users_settings[$scheduled['id_user']]['templating'] ?? false))
{
$render = $internal_templating->render($scheduled['text']);
if (!$render['success'])
{
continue;
}
$message['text'] = $render['result'];
}
else
{
$message['text'] = $scheduled['text'];
}
$messages[] = $message;
}
//Add messages for contacts
$contacts = $this->get_contacts($scheduled['id']);
$groups = $this->get_groups($scheduled['id']);
foreach ($groups as $group)
{
$contacts_to_add = $internal_group->get_contacts($group['id']);
$contacts = array_merge($contacts, $contacts_to_add);
}
$conditional_groups = $this->get_conditional_groups($scheduled['id']);
foreach ($conditional_groups as $conditional_group)
{
$contacts_to_add = $internal_conditional_group->get_contacts_for_condition_and_user($scheduled['id_user'], $conditional_group['condition']);
$contacts = array_merge($contacts, $contacts_to_add);
}
$added_contacts = [];
foreach ($contacts as $contact)
{
if ($added_contacts[$contact['id']] ?? false)
{
continue;
}
$added_contacts[$contact['id']] = true;
$message = [
'id_user' => $scheduled['id_user'],
'id_scheduled' => $scheduled['id'],
'origin' => $scheduled['origin'],
'destination' => $number['number'],
'flash' => $scheduled['flash'],
];
if (null === $message['origin'])
{
$k = array_rand($users_phones[$scheduled['id_user']]);
$rnd_phone = $users_phones[$scheduled['id_user']][$k];
$message['origin'] = $rnd_phone['number'];
}
if ((int) ($users_settings[$scheduled['id_user']]['templating'] ?? false))
{
$contact['datas'] = json_decode($contact['datas'], true);
$datas = ['contact' => $contact];
$render = $internal_templating->render($scheduled['text'], $datas);
if (!$render['success'])
{
continue;
}
$message['text'] = $render['result'];
}
else
{
$message['text'] = $scheduled['text'];
}
$messages[] = $message;
}
foreach ($messages as $message)
{
//Remove empty messages
if ('' === trim($message['text']))
{
continue;
}
$smss_to_send[] = $message;
}
}
return $smss_to_send;
}
/**
* Return numbers for a scheduled message.
*
* @param int $id_scheduled : Scheduled id
*
* @return array
*/
public function get_numbers(int $id_scheduled)
{
return $this->get_model()->get_numbers($id_scheduled);
}
/**
* Return contacts for a scheduled message.
*
* @param int $id_scheduled : Scheduled id
*
* @return array
*/
public function get_contacts(int $id_scheduled)
{
return $this->get_model()->get_contacts($id_scheduled);
}
/**
* Return groups for a scheduled message.
*
* @param int $id_scheduled : Scheduled id
*
* @return array
*/
public function get_groups(int $id_scheduled)
{
return $this->get_model()->get_groups($id_scheduled);
}
/**
* Return conditional groups for a scheduled message.
*
* @param int $id_scheduled : Scheduled id
*
* @return array
*/
public function get_conditional_groups(int $id_scheduled)
{
return $this->get_model()->get_conditional_groups($id_scheduled);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Scheduled($this->bdd);
return $this->model;
}
}

View file

@ -1,199 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Sended extends StandardController
{
protected $model;
/**
* Create a sended.
*
* @param $at : Reception date
* @param $text : Text of the message
* @param string $origin : Number of the sender
* @param string $destination : Number of the receiver
* @param string $uid : Uid of the sms on the adapter service used
* @param string $adapter : Name of the adapter service used to send the message
* @param bool $flash : Is the sms a flash
* @param string $status : Status of a the sms. By default 'unknown'
*
* @return bool : false on error, new sended id else
*/
public function create($at, string $text, string $origin, string $destination, string $uid, string $adapter, bool $flash = false, ?string $status = 'unknown'): bool
{
$sended = [
'at' => $at,
'text' => $text,
'origin' => $origin,
'destination' => $destination,
'uid' => $uid,
'adapter' => $adapter,
'flash' => $flash,
'status' => $status,
];
return (bool) $this->get_model()->insert($sended);
}
/**
* Update a sended for a user.
*
* @param int $id_user : user id
* @param int $id_sended : Sended id
* @param $at : Reception date
* @param $text : Text of the message
* @param string $origin : Number of the sender
* @param string $destination : Number of the receiver
* @param string $uid : Uid of the sms on the adapter service used
* @param string $adapter : Name of the adapter service used to send the message
* @param bool $flash : Is the sms a flash
* @param ?string $status : Status of a the sms. By default null -> unknown
*
* @return bool : false on error, true on success
*/
public function update_for_user(int $id_user, int $id_sended, $at, string $text, string $origin, string $destination, string $uid, string $adapter, bool $flash = false, ?string $status = null): bool
{
$sended = [
'at' => $at,
'text' => $text,
'origin' => $origin,
'destination' => $destination,
'uid' => $uid,
'adapter' => $adapter,
'flash' => $flash,
'status' => $status,
];
return (bool) $this->get_model()->update_for_user($id_user, $id_sended, $sended);
}
/**
* Update a sended status for a user.
*
* @param int $id_user : user id
* @param int $id_sended : Sended id
* @param string $status : Status of a the sms (unknown, delivered, failed)
*
* @return bool : false on error, true on success
*/
public function update_status_for_user(int $id_user, int $id_sended, string $status): bool
{
$sended = [
'status' => $status,
];
return (bool) $this->get_model()->update_for_user($id_user, $id_sended, $sended);
}
/**
* Update a sended status for a sended.
*
* @param int $id_sended : Sended id
* @param string $status : Status of a the sms (unknown, delivered, failed)
*
* @return bool : false on error, true on success
*/
public function update_status(int $id_sended, string $status): bool
{
$sended = [
'status' => $status,
];
return (bool) $this->get_model()->update($id_sended, $sended);
}
/**
* Return x last sendeds message for a user, order by date.
*
* @param int $id_user : User id
* @param int $nb_entry : Number of sendeds messages to return
*
* @return array
*/
public function get_lasts_by_date_for_user(int $id_user, int $nb_entry)
{
return $this->get_model()->get_lasts_by_date_for_user($id_user, $nb_entry);
}
/**
* Return sendeds for a destination and a user.
*
* @param int $id_user : User id
* @param string $origin : Number who sent the message
*
* @return array
*/
public function gets_by_destination_and_user(int $id_user, string $origin)
{
return $this->get_model()->gets_by_destination_and_user($id_user, $origin);
}
/**
* Return sended for an uid and an adapter.
*
* @param string $uid : Uid of the sended
* @param string $adapter : Adapter used to send the message
*
* @return array
*/
public function get_by_uid_and_adapter(string $uid, string $adapter)
{
return $this->get_model()->get_by_uid_and_adapter($uid, $adapter);
}
/**
* Get number of sended SMS for every date since a date for a specific user.
*
* @param int $id_user : user id
* @param \DateTime $date : Date since which we want the messages
*
* @return array
*/
public function count_by_day_since_for_user(int $id_user, $date)
{
$counts_by_day = $this->get_model()->count_by_day_since_for_user($id_user, $date);
$return = [];
foreach ($counts_by_day as $count_by_day)
{
$return[$count_by_day['at_ymd']] = $count_by_day['nb'];
}
return $return;
}
/**
* Find last sended message for a destination and user.
*
* @param int $id_user : User id
* @param string $destination : Destination number
*
* @return array
*/
public function get_last_for_destination_and_user(int $id_user, string $destination)
{
return $this->get_model()->get_last_for_destination_and_user($id_user, $destination);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Sended($this->bdd);
return $this->model;
}
}

View file

@ -1,102 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Setting extends StandardController
{
protected $model;
/**
* Return all settings of a user.
*
* @param int $id_user : user id
*
* @return array
*/
public function gets_for_user(int $id_user)
{
$settings = $this->get_model()->gets_for_user($id_user);
$settings_array = [];
foreach ($settings as $setting)
{
$settings_array[$setting['name']] = $setting['value'];
}
return $settings_array;
}
/**
* Update a setting by his name and user id.
*
* @param int $id_user : user id
* @param string $name : setting name
* @param mixed $value
*
* @return int : number of modified lines
*/
public function update_for_user(int $id_user, string $name, $value): bool
{
return (bool) $this->get_model()->update_by_name_for_user($id_user, $name, $value);
}
/**
* Create a new setting.
*
* @param int $id_user : user id
* @param string $name : setting name
* @param mixed $value : value of the setting
*
* @return bool
*/
public function create(int $id_user, string $name, $value): bool
{
$setting = [
'id_user' => $id_user,
'name' => $name,
'value' => $value,
];
return (bool) $this->get_model()->insert($setting);
}
/**
* Generate and insert default settings for a user.
*
* @param int $id_user : user id
*
* @return bool
*/
public function create_defaults_for_user(int $id_user)
{
$all_success = true;
foreach (USER_DEFAULT_SETTINGS as $name => $value)
{
$success = $this->create($id_user, $name, $value);
$all_success = ($all_success && $success);
}
return $all_success;
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Setting($this->bdd);
return $this->model;
}
}

View file

@ -1,78 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class SmsStop extends StandardController
{
protected $model;
/**
* Create a new smsstop.
*
* @param int $id_user : User id
* @param string $number : Number to stop smss for
*
* @return mixed bool|int : False if cannot create smsstop, id of the new smsstop else
*/
public function create(int $id_user, string $number)
{
$smsstop = [
'id_user' => $id_user,
'number' => $number,
];
return $this->get_model()->insert($smsstop);
}
/**
* Update a smsstop.
*
* @param int $id_user : User id
* @param int $id_smsstop : SmsStop id
* @param string $number : Number to stop smss for
*
* @return mixed bool|int : False if cannot create smsstop, id of the new smsstop else
*/
public function update_for_user(int $id_user, int $id_smsstop, string $number)
{
$datas = [
'number' => $number,
];
return $this->get_model()->update_for_user($id_user, $id_smsstop, $datas);
}
/**
* Return a smsstop by his number and user.
*
* @param int $id_user : user id
* @param string $number : phone number
*
* @return array
*/
public function get_by_number_for_user(int $id_user, string $number)
{
return $this->get_model()->get_by_number_for_user($id_user, $number);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\SmsStop($this->bdd);
return $this->model;
}
}

View file

@ -1,140 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
abstract class StandardController extends \descartes\InternalController
{
protected $bdd;
public function __construct(\PDO $bdd)
{
$this->bdd = $bdd;
}
/**
* Return all the entries.
*
* @return array
*/
public function get_all()
{
return $this->get_model()->get_all();
}
/**
* Return a entry by his id.
*
* @param int $id : Entry id
*
* @return array
*/
public function get(int $id)
{
return $this->get_model()->get($id);
}
/**
* Return a entry by his id and a user.
*
* @param int $id_user : Entry id
* @param int $id : Entry id
*
* @return array
*/
public function get_for_user(int $id_user, int $id)
{
return $this->get_model()->get_for_user($id_user, $id);
}
/**
* Return all entries for a user.
*
* @param int $id_user : Entry id
*
* @return array
*/
public function gets_for_user(int $id_user)
{
return $this->get_model()->gets_for_user($id_user);
}
/**
* Return the list of entries for a user.
*
* @param int $id_user : User id
* @param ?int $nb_entry : Number of entry to return
* @param ?int $page : Pagination, used to calcul offset, $nb_entry * $page
*
* @return array : Entrys list
*/
public function list_for_user(int $id_user, ?int $nb_entry = null, ?int $page = null)
{
return $this->get_model()->list_for_user($id_user, $nb_entry, $nb_entry * $page);
}
/**
* Return a list of entries in a group of ids and for a user.
*
* @param int $id_user : user id
* @param array $ids : ids of entries to find
*
* @return array
*/
public function gets_in_for_user(int $id_user, array $ids)
{
return $this->get_model()->gets_in_for_user($id_user, $ids);
}
/**
* Delete a entry by his id for a user.
*
* @param int $id_user : User id
* @param int $id : Entry id
*
* @return int : Number of removed rows
*/
public function delete_for_user(int $id_user, int $id)
{
return $this->get_model()->delete_for_user($id_user, $id);
}
/**
* Delete a entry by his id.
*
* @param int $id : Entry id
*
* @return int : Number of removed rows
*/
public function delete(int $id)
{
return $this->get_model()->delete($id);
}
/**
* Count number of entry for a user.
*
* @param int $id_user : User id
*
* @return int : number of entries
*/
public function count_for_user(int $id_user)
{
return $this->get_model()->count_for_user($id_user);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
abstract protected function get_model(): \descartes\Model;
}

View file

@ -1,87 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
/**
* Templating questions relative class
* Not a standard controller as it's not linked to a model in any way.
*/
class Templating
{
/**
* Twig environment.
*/
private $sandbox;
public function __construct()
{
$tags = [
'if',
'for',
'apply',
];
$filters = [
'abs', 'capitalize', 'country_name', 'currency_name',
'currency_symbol', 'date', 'date_modify', 'default',
'first', 'format', 'format_currency', 'format_datetime',
'format_number', 'join', 'keys', 'language_name',
'last', 'length', 'locale_name', 'lower', 'number_format',
'replace', 'reverse', 'round', 'slice',
'sort', 'spaceless', 'split', 'timezone_name',
'title', 'trim', 'upper', 'url_encode',
];
$methods = [];
$properties = [];
$functions = [
'date', 'max', 'min', 'random',
'range',
];
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
$this->sandbox = new \Twig\Extension\SandboxExtension($policy, true);
}
/**
* Render a string as a twig template.
*
* @param string $template : Template string
* @param array $datas : Datas to pass to the template
*
* @return array : keys, success, error, result
*/
public function render(string $template, array $datas = [])
{
try
{
$loader = new \Twig\Loader\ArrayLoader([
'template' => $template,
]);
$twig = new \Twig\Environment($loader);
$result = $twig->render('template', $datas);
return [
'success' => true,
'result' => $result,
];
}
catch (\Exception $e)
{
return [
'success' => false,
'result' => $e->getMessage(),
];
}
}
}

View file

@ -1,365 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
/**
* Some tools frequently used.
* Not a standard controller as it's not linked to a model in any way.
*/
class Tool extends \descartes\InternalController
{
/**
* Cette fonction parse un numéro pour le retourner sans espaces, etc.
*
* @param string $number : Le numéro de téléphone à parser
*
* @return mixed : Si le numéro est bien un numéro de téléphone, on retourne le numéro parsé. Sinon, on retourne faux
*/
public static function parse_phone($number)
{
try
{
$phone_number_util = \libphonenumber\PhoneNumberUtil::getInstance();
$phone_number_o = $phone_number_util->parse($number, null);
$valid = $phone_number_util->isValidNumber($phone_number_o);
if (!$valid)
{
return false;
}
return $phone_number_util->format($phone_number_o, \libphonenumber\PhoneNumberFormat::E164);
}
catch (\Exception $e)
{
return false;
}
}
/**
* Cette fonction parse un numéro pour le retourner avec des espaces, etc.
*
* @param string $number : Le numéro de téléphone à parser
*
* @return mixed : Si le numéro est bien un numéro de téléphone, on retourne le numéro parsé. Sinon, on retourne faux
*/
public static function phone_format($number)
{
try
{
$phone_number_util = \libphonenumber\PhoneNumberUtil::getInstance();
$phone_number_o = $phone_number_util->parse($number, null);
return $phone_number_util->format($phone_number_o, \libphonenumber\PhoneNumberFormat::INTERNATIONAL);
}
catch (\Exception $e)
{
return $number;
}
}
/**
* Format a number and make a link to a discussion with this number.
*
* @param string $number : Number to format and make a link for
*
* @return string : Link to the number
*/
public static function phone_link($number)
{
$number_format = self::phone_format($number);
$url = \descartes\Router::url('Discussion', 'show', ['number' => $number]);
return '<a href="' . self::s($url, false, true, false) . '">' . self::s($number_format, false, true, false) . '</a>';
}
/**
* Cette fonction fait la correspondance entre un type d'evenement et une icone font awesome.
*
* @param string $type : Le type de l'évenement à analyser
*
* @return string : Le nom de l'icone à afficher (ex : fa-user)
*/
public static function event_type_to_icon($type)
{
switch ($type) {
case 'USER_ADD':
$logo = 'fa-user';
break;
case 'CONTACT_ADD':
$logo = 'fa-user';
break;
case 'GROUP_ADD':
$logo = 'fa-group';
break;
case 'SCHEDULED_ADD':
$logo = 'fa-calendar';
break;
case 'COMMAND_ADD':
$logo = 'fa-terminal';
break;
default:
$logo = 'fa-question';
}
return $logo;
}
/**
* Cette fonction vérifie une date.
*
* @param string $date : La date a valider
* @param string $format : Le format de la date
*
* @return bool : Vrai si la date et valide, faux sinon
*/
public static function validate_date($date, $format)
{
$objectDate = \DateTime::createFromFormat($format, $date);
return $objectDate && $objectDate->format($format) === $date;
}
/**
* Cette fonction retourne un mot de passe généré aléatoirement.
*
* @param int $length : Taille du mot de passe à générer
*
* @return string : Le mot de passe aléatoire
*/
public static function generate_password($length)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-@()?.:!%*$&/';
$password = '';
$chars_length = mb_strlen($chars) - 1;
$i = 0;
while ($i < $length)
{
++$i;
$password .= $chars[rand(0, $chars_length)];
}
return $password;
}
/**
* Cette fonction vérifie si un utilisateur et connecté, et si il ne l'est pas, redirige sur la page de connexion.
*/
public static function verifyconnect()
{
if (!isset($_SESSION['connect']) || !$_SESSION['connect'])
{
header('Location: /');
die();
}
}
/**
* Check if the user connected.
*
* @return bool : True if connected, False else
*/
public static function is_connected()
{
return (bool) ($_SESSION['connect'] ?? false);
}
/**
* Check if the user is admin.
*
* @return bool : True if admin, False else
*/
public static function is_admin()
{
return (bool) ($_SESSION['user']['admin'] ?? false);
}
/**
* Cette fonction s'occupe d'envoyer les emails.
*
* @param string $to : L'adresse mail à laquelle envoyer le mail
* @param array $settings : Les settings du mail, type, sujet, template
* @param array $datas : Les données à fournir au template du mail
*/
public static function send_email($to, $settings, $datas = [])
{
$controller = new \descartes\Controller();
ob_start();
$controller->render($settings['template'], $datas);
$content = ob_get_clean();
return @mail($to, $settings['subject'], $content);
}
/**
* Allow to read an uploaded file.
*
* @param array $file : The array extracted from $_FILES['file']
*
* @return array : ['success' => bool, 'content' => file handler | error message, 'error_code' => $file['error']]
*/
public static function read_uploaded_file(array $file)
{
$result = [
'success' => false,
'content' => 'Une erreur inconnue est survenue.',
'error_code' => $file['error'] ?? 99,
'mime_type' => false,
];
if (UPLOAD_ERR_OK !== $file['error'])
{
switch ($file['error'])
{
case UPLOAD_ERR_INI_SIZE:
$result['content'] = 'Impossible de télécharger le fichier car il dépasse les ' . ini_get('upload_max_filesize') / (1000 * 1000) . ' Mégaoctets.';
break;
case UPLOAD_ERR_FORM_SIZE:
$result['content'] = 'Le fichier dépasse la limite de taille.';
break;
case UPLOAD_ERR_PARTIAL:
$result['content'] = 'L\'envoi du fichier a été interrompu.';
break;
case UPLOAD_ERR_NO_FILE:
$result['content'] = 'Aucun fichier n\'a été envoyé.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$result['content'] = 'Le serveur ne dispose pas de fichier temporaire permettant l\'envoi de fichiers.';
break;
case UPLOAD_ERR_CANT_WRITE:
$result['content'] = 'Impossible d\'envoyer le fichier car il n\'y a plus de place sur le serveur.';
break;
case UPLOAD_ERR_EXTENSION:
$result['content'] = 'Le serveur a interrompu l\'envoi du fichier.';
break;
}
return $result;
}
$tmp_filename = $file['tmp_name'] ?? false;
if (!$tmp_filename || !is_readable($tmp_filename))
{
return $result;
}
$result['mime_type'] = 'text/plain' === mime_content_type($tmp_filename) ? $file['type'] : mime_content_type($tmp_filename);
$file_handler = fopen($tmp_filename, 'r');
$result['success'] = true;
$result['content'] = $file_handler;
return $result;
}
/**
* Allow to upload file.
*
* @param array $file : The array extracted from $_FILES['file']
*
* @return array : ['success' => bool, 'content' => file path | error message, 'error_code' => $file['error']]
*/
public static function upload_file(array $file)
{
$result = [
'success' => false,
'content' => 'Une erreur inconnue est survenue.',
'error_code' => $file['error'] ?? 99,
];
if (UPLOAD_ERR_OK !== $file['error'])
{
switch ($file['error'])
{
case UPLOAD_ERR_INI_SIZE:
$result['content'] = 'Impossible de télécharger le fichier car il dépasse les ' . ini_get('upload_max_filesize') / (1000 * 1000) . ' Mégaoctets.';
break;
case UPLOAD_ERR_FORM_SIZE:
$result['content'] = 'Le fichier dépasse la limite de taille.';
break;
case UPLOAD_ERR_PARTIAL:
$result['content'] = 'L\'envoi du fichier a été interrompu.';
break;
case UPLOAD_ERR_NO_FILE:
$result['content'] = 'Aucun fichier n\'a été envoyé.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$result['content'] = 'Le serveur ne dispose pas de fichier temporaire permettant l\'envoi de fichiers.';
break;
case UPLOAD_ERR_CANT_WRITE:
$result['content'] = 'Impossible d\'envoyer le fichier car il n\'y a plus de place sur le serveur.';
break;
case UPLOAD_ERR_EXTENSION:
$result['content'] = 'Le serveur a interrompu l\'envoi du fichier.';
break;
}
return $result;
}
$tmp_filename = $file['tmp_name'] ?? false;
if (!$tmp_filename || !is_readable($tmp_filename))
{
return $result;
}
$md5_filename = md5_file($tmp_filename);
if (!$md5_filename)
{
return $result;
}
$new_file_path = PWD_DATAS . '/' . $md5_filename;
if (file_exists($new_file_path))
{
$result['success'] = true;
$result['content'] = $new_file_path;
return $result;
}
$success = move_uploaded_file($tmp_filename, $new_file_path);
if (!$success)
{
$result['content'] = 'Impossible d\'écrire le fichier sur le serveur.';
return $result;
}
$result['success'] = true;
$result['content'] = $new_file_path;
return $result;
}
}

View file

@ -1,235 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
/**
* Methods to manage user. Not a standard controller as it has nothing to do with user based restrictions and must be usable only by admin.
*/
class User extends \descartes\InternalController
{
private $model_user;
private $internal_event;
private $internal_setting;
public function __construct(\PDO $bdd)
{
$this->model_user = new \models\User($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
$this->internal_setting = new \controllers\internals\Setting($bdd);
}
/**
* Return list of users as an array.
*
* @param mixed(int|bool) $nb_entry : Number of entry to return
* @param mixed(int|bool) $page : Numero of page
*
* @return array|bool : List of user or false
*/
public function list(?int $nb_entry = null, ?int $page = null)
{
return $this->model_user->list($nb_entry, $page * $nb_entry);
}
/**
* Delete a user.
*
* @param array $ids : Les id des useres à supprimer
* @param mixed $id
*
* @return int : Number of users deleted
*/
public function delete($id)
{
return $this->model_user->remove($id);
}
/**
* Check user credentials.
*
* @param string $email : User email
* @param string $password : User password
*
* @return mixed false | array : False if no user for thoses credentials, the user else
*/
public function check_credentials($email, $password)
{
$user = $this->model_user->get_by_email($email);
if (!$user)
{
return false;
}
if (!password_verify($password, $user['password']))
{
return false;
}
return $user;
}
/**
* Update a user password.
*
* @param string $id : User id
* @param string $password : New password
*
* @return bool;
*/
public function update_password(int $id, string $password): bool
{
$password = password_hash($password, PASSWORD_DEFAULT);
return (bool) $this->model_user->update_password($id, $password);
}
/**
* Update user email.
*
* @param string $id : user id
* @param string $email : new mail
*
* @return boolean;
*/
public function update_email($id, $email)
{
return (bool) $this->model_user->update_email($id, $email);
}
/**
* Update user api key.
*
* @param string $id : user id
* @param ?string $api_key : new api key
*
* @return mixed : false on error, else new api key;
*/
public function update_api_key($id, ?string $api_key = null)
{
$api_key = $api_key ?? $this->generate_random_api_key();
$success = $this->model_user->update($id, ['api_key' => $api_key]);
if (!$success)
{
return false;
}
return $api_key;
}
/**
* Get a user by his email address.
*
* @param string $email : User email
*
* @return mixed boolean | array : false if cannot find user for this email, the user else
*/
public function get_by_email($email)
{
return $this->model_user->get_by_email($email);
}
/**
* Find a user by his id.
*
* @param string $id : User id
*
* @return mixed array
*/
public function get($id)
{
return $this->model_user->get($id);
}
/**
* Get a user by his api_key address.
*
* @param string $api_key : User api key
*
* @return mixed boolean | array : false if cannot find user for this api key, the user else
*/
public function get_by_api_key(string $api_key)
{
return $this->model_user->get_by_api_key($api_key);
}
/**
* Update a user by his id.
*
* @param mixed $id
* @param mixed $email
* @param mixed $password
* @param mixed $admin
* @param mixed $api_key
*
* @return int : Number of modified user
*/
public function update($id, $email, $password, $admin, $api_key)
{
$user = [
'email' => $email,
'password' => password_hash($password, PASSWORD_DEFAULT),
'admin' => $admin,
'api_key' => $api_key,
];
return $this->model_user->update($id, $user);
}
/**
* Create a new user.
*
* @param mixed $email
* @param mixed $password
* @param mixed $admin
* @param ?string $api_key : The api key of the user, if null generate randomly
*
* @return mixed bool|int : false on error, id of the new user else
*/
public function create($email, $password, $admin, ?string $api_key = null)
{
$user = [
'email' => $email,
'password' => password_hash($password, PASSWORD_DEFAULT),
'admin' => $admin,
'api_key' => $api_key ?? $this->generate_random_api_key(),
];
$new_user_id = $this->model_user->insert($user);
if (!$new_user_id)
{
return false;
}
$success = $this->internal_setting->create_defaults_for_user($new_user_id);
if (!$success)
{
$this->delete($new_user_id);
return false;
}
return $new_user_id;
}
/**
* Generate a random api key.
*
* @return string : The api key
*/
public function generate_random_api_key(): string
{
return bin2hex(random_bytes(16));
}
}

View file

@ -1,89 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
class Webhook extends StandardController
{
protected $bdd;
protected $model;
/**
* Create a new webhook.
*
* @param int $id_user : User id
* @param string $url : Webhook url
* @param string $type : Webhook type
*
* @return mixed bool|int : False if cannot create webhook, id of the new webhook else
*/
public function create(int $id_user, string $url, string $type)
{
$webhook = [
'id_user' => $id_user,
'url' => $url,
'type' => $type,
];
$result = $this->get_model()->insert($webhook);
if (!$result)
{
return false;
}
return $result;
}
/**
* Update a webhook.
*
* @param int $id_user : User id
* @param int $id : Webhook id
* @param string $url : Webhook url
* @param string $type : Webhook type
*
* @return mixed bool|int : False if cannot create webhook, id of the new webhook else
*/
public function update_for_user(int $id_user, int $id, string $url, string $type)
{
$datas = [
'url' => $url,
'type' => $type,
];
return $this->get_model()->update_for_user($id_user, $id, $datas);
}
/**
* Find all webhooks for a user and for a type of webhook.
*
* @param int $id_user : User id
* @param string $type : Webhook type
*
* @return array
*/
public function gets_for_type_and_user(int $id_user, string $type)
{
return $this->get_model()->gets_for_type_and_user($id_user, $type);
}
/**
* Get the model for the Controller.
*
* @return \descartes\Model
*/
protected function get_model(): \descartes\Model
{
$this->model = $this->model ?? new \models\Webhook($this->bdd);
return $this->model;
}
}

View file

@ -1,196 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
class Account extends \descartes\Controller
{
public $internal_user;
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_user = new \controllers\internals\User($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Show profile page.
*/
public function show()
{
$this->render('account/show');
}
/**
* Update connected user password.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['password'] : The new password
*
* @return void;
*/
public function update_password($csrf)
{
$password = $_POST['password'] ?? false;
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
if (!$password)
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez renseigner un mot de passe.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$update_password_result = $this->internal_user->update_password($_SESSION['user']['id'], $password);
if (!$update_password_result)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de mettre à jour le mot de passe.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
\FlashMessage\FlashMessage::push('success', 'Le mot de passe a bien été mis à jour.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
/**
* Update user email.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['email'] : User new email
* @param string $_POST['verif_email'] : Verif email
*/
public function update_email($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$email = $_POST['email'] ?? false;
if (!$email)
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez fournir une adresse e-mail !');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL))
{
\FlashMessage\FlashMessage::push('danger', 'L\'adresse e-mail n\'est pas une adresse valide.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$update_email_result = $this->internal_user->update_email($_SESSION['user']['id'], $email);
if (!$update_email_result)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de mettre à jour.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$_SESSION['user']['email'] = $email;
\FlashMessage\FlashMessage::push('success', 'L\'email a bien été mis à jour.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
/**
* Update user api key.
*
* @param $csrf : Le jeton CSRF
*/
public function update_api_key($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$new_api_key = $this->internal_user->update_api_key($_SESSION['user']['id']);
if (!$new_api_key)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de mettre à jour.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$_SESSION['user']['api_key'] = $new_api_key;
\FlashMessage\FlashMessage::push('success', 'Votre ancienne clef API a été désactivée et une nouvelle clef générée.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
/**
* Delete a user.
*
* @param string $_POST['delete_account'] : Boolean to see if we want to delete
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$delete_account = $_POST['delete_account'] ?? false;
if (!$delete_account)
{
\FlashMessage\FlashMessage::push('danger', 'Pour supprimer le compte, vous devez cocher la case correspondante.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
$delete_account_result = $this->internal_user->delete_for_user($_SESSION['user']['id'], $_SESSION['user']['id']);
if (!$delete_account_result)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de supprimer le compte.');
return $this->redirect(\descartes\Router::url('Account', 'show'));
}
return $this->logout();
}
/**
* Logout a user and redirect to login page.
*/
public function logout()
{
session_unset();
session_destroy();
return $this->redirect(\descartes\Router::url('Connect', 'login'));
}
}

View file

@ -1,281 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Api to interact with raspisms.
*/
class Api extends \descartes\ApiController
{
const DEFAULT_RETURN = [
'error' => 0, //Error code
'message' => null, //Any message to describe a potential error
'response' => null, //The content of the response
'next' => null, //Link to the next results
'prev' => null, //Link to the previous results
];
const ERROR_CODES = [
'NONE' => 0,
'INVALID_CREDENTIALS' => 1,
'INVALID_PARAMETER' => 2,
'MISSING_PARAMETER' => 4,
'CANNOT_CREATE' => 8,
];
const ERROR_MESSAGES = [
'INVALID_CREDENTIALS' => 'Invalid API Key. Please provide a valid API as GET parameter "api_key".',
'INVALID_PARAMETER' => 'You have specified an invalid parameter : ',
'MISSING_PARAMETER' => 'One require parameter is missing : ',
'CANNOT_CREATE' => 'Cannot create a new entry.',
];
private $internal_user;
private $internal_phone;
private $internal_received;
private $internal_sended;
private $internal_scheduled;
private $internal_contact;
private $internal_group;
private $internal_conditional_group;
private $user;
/**
* Construct the object and quit if failed authentication.
*
* @return void;
*/
public function __construct()
{
parent::__construct();
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_user = new \controllers\internals\User($bdd);
$this->internal_phone = new \controllers\internals\Phone($bdd);
$this->internal_received = new \controllers\internals\Received($bdd);
$this->internal_sended = new \controllers\internals\Sended($bdd);
$this->internal_scheduled = new \controllers\internals\Scheduled($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_group = new \controllers\internals\Group($bdd);
$this->internal_conditional_group = new \controllers\internals\ConditionalGroup($bdd);
//If no user, quit with error
$this->user = false;
$api_key = $_GET['api_key'] ?? false;
if ($api_key)
{
$this->user = $this->internal_user->get_by_api_key($api_key);
}
if (!$this->user)
{
$return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['INVALID_CREDENTIALS'];
$return['message'] = self::ERROR_MESSAGES['INVALID_CREDENTIALS'];
$this->auto_http_code(false);
$this->json($return);
exit(self::ERROR_CODES['INVALID_CREDENTIALS']);
}
}
/**
* List all entries of a certain type for the current user, sorted by id.
*
* @param string $entry_type : Type of entries we want to list ['sended', 'received', 'scheduled', 'contact', 'group', 'conditional_group', 'phone']
* @param int $page : Pagination number, Default = 0. Group of 25 results.
*
* @return : List of entries
*/
public function get_entries(string $entry_type, int $page = 0)
{
$entry_types = ['sended', 'received', 'scheduled', 'contact', 'group', 'conditional_group', 'phone'];
if (!\in_array($entry_type, $entry_types, true))
{
$return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'entry_type must be one of : ' . implode(', ', $entry_types) . '.';
$this->auto_http_code(false);
$this->json($return);
return false;
}
$controller_str = 'internal_' . $entry_type;
$controller = $this->{$controller_str};
$page = (int) $page;
$limit = 25;
$entries = $controller->list_for_user($this->user['id'], $limit, $page);
//Special case for scheduled, we must add numbers because its a join
if ('scheduled' === $entry_type)
{
foreach ($entries as $key => $entry)
{
$entries[$key]['numbers'] = $this->internal_scheduled->get_numbers($entry['id']);
$entries[$key]['contacts'] = $this->internal_scheduled->get_contacts($entry['id']);
$entries[$key]['groups'] = $this->internal_scheduled->get_groups($entry['id']);
$entries[$key]['conditional_groups'] = $this->internal_scheduled->get_conditional_groups($entry['id']);
}
}
//Special case for group we must add contact because its a join
elseif ('group' === $entry_type)
{
foreach ($entries as $key => $entry)
{
$entries[$key]['contacts'] = $this->internal_group->get_contacts($entry['id']);
}
}
$return = self::DEFAULT_RETURN;
$return['response'] = $entries;
if (\count($entries) === $limit)
{
$return['next'] = \descartes\Router::url('Api', __FUNCTION__, ['entry_type' => $entry_type, 'page' => $page + 1], ['api_key' => $this->user['api_key']]);
}
if ($page > 0)
{
$return['next'] = \descartes\Router::url('Api', __FUNCTION__, ['entry_type' => $entry_type, 'page' => $page - 1], ['api_key' => $this->user['api_key']]);
}
$this->auto_http_code(true);
$this->json($return);
}
/**
* Schedule a message to be send.
*
* @param string $_POST['at'] : Date to send message at format Y-m-d H:i:s
* @param string $_POST['text'] : Text of the message to send
* @param string $_POST['origin'] : Default null. Number to send the message from. If null use a random phone
* @param string $_POST['flash'] : Default false. Is the sms a flash sms.
* @param string $_POST['numbers'] : Array of numbers to send message to
* @param string $_POST['contacts'] : Array of ids of contacts to send message to
* @param string $_POST['groups'] : Array of ids of groups to send message to
* @param string $_POST['conditional_groups'] : Array of ids of conditional groups to send message to
*
* @return : Id of scheduled created
*/
public function post_scheduled()
{
$at = $_POST['at'] ?? false;
$text = $_POST['text'] ?? false;
$origin = empty($_POST['origin']) ? null : $_POST['origin'];
$flash = (bool) ($_POST['flash'] ?? false);
$numbers = $_POST['numbers'] ?? [];
$contacts = $_POST['contacts'] ?? [];
$groups = $_POST['groups'] ?? [];
$conditional_groups = $_POST['conditional_groups'] ?? [];
if (!$at || !$text)
{
$return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['MISSING_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['MISSING_PARAMETER'] . ($at ? '' : 'at ') . ($text ? '' : 'text');
$this->auto_http_code(false);
$this->json($return);
return false;
}
if (!\controllers\internals\Tool::validate_date($at, 'Y-m-d H:i:s'))
{
$return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'at must be a date of format "Y-m-d H:i:s".';
$this->auto_http_code(false);
$this->json($return);
return false;
}
foreach ($numbers as $key => $number)
{
$number = \controllers\internals\Tool::parse_phone($number);
if (!$number)
{
unset($numbers[$key]);
continue;
}
$numbers[$key] = $number;
}
if (!$numbers && !$contacts && !$groups && !$conditional_groups)
{
$return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['MISSING_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['MISSING_PARAMETER'] . 'You must specify at least one valid number, contact, group or conditional_group.';
$this->auto_http_code(false);
$this->json($return);
return false;
}
if ($origin && !$this->internal_phone->get_by_number_and_user($this->user['id'], $origin))
{
$return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'origin : You must specify an origin number among thoses of user phones.';
$this->auto_http_code(false);
$this->json($return);
return false;
}
$scheduled_id = $this->internal_scheduled->create($this->user['id'], $at, $text, $origin, $flash, $numbers, $contacts, $groups, $conditional_groups);
if (!$scheduled_id)
{
$return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['CANNOT_CREATE'];
$return['message'] = self::ERROR_MESSAGES['CANNOT_CREATE'];
$this->auto_http_code(false);
$this->json($return);
return false;
}
$return = self::DEFAULT_RETURN;
$return['response'] = $scheduled_id;
$this->auto_http_code(true);
$this->json($return);
}
/**
* Delete a scheduled message.
*
* @param int $id : Id of scheduled message to delete
*
* @return bool : void
*/
public function delete_scheduled(int $id)
{
$success = $this->internal_scheduled->delete_for_user($this->user['id'], $id);
if (!$success)
{
$this->auto_http_code(false);
return false;
}
$this->auto_http_code(true);
return true;
}
}

View file

@ -1,88 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Controller of callback pages, like sms status update notification.
*/
class Callback extends \descartes\Controller
{
private $internal_user;
private $internal_sended;
private $internal_adapter;
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_user = new \controllers\internals\User($bdd);
$this->internal_sended = new \controllers\internals\Sended($bdd);
$this->internal_adapter = new \controllers\internals\Adapter();
}
/**
* Function call on a sended sms status change notification reception.
*
* @param string $adapter_name : Name of the adapter to use
*
* @return false : We must always return false, and we respect a random usleep before returning anything
* in order to prevent bruteforce api key guessing and time guessing
*/
public function update_sended_status(string $adapter_name)
{
//Wait between 0.5 and 1.03s in order to counter time guessing bruteforce attack against api key
usleep(mt_rand(5, 10) / 10 * 1000000 + mt_rand(0, 30000));
//Search for an adapter
$find_adapter = false;
$adapters = $this->internal_adapter->list_adapters();
foreach ($adapters as $adapter)
{
if (mb_strtolower($adapter['meta_name']) === mb_strtolower($adapter_name))
{
$find_adapter = $adapter;
}
}
if (false === $find_adapter)
{
return false;
}
//Instanciate adapter, check if status change is supported and if so call status change callback
$adapter_classname = $find_adapter['meta_classname'];
if (!$find_adapter['meta_support_status_change'])
{
return false;
}
$callback_return = $adapter_classname::status_change_callback();
var_dump($callback_return);
if (!$callback_return)
{
return false;
}
$sended = $this->internal_sended->get_by_uid_and_adapter($callback_return['uid'], $adapter_classname);
if (!$sended)
{
return false;
}
$this->internal_sended->update_status($sended['id'], $callback_return['status']);
return false;
}
}

View file

@ -1,172 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des commandes.
*/
class Command extends \descartes\Controller
{
private $internal_command;
private $internal_event;
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_command = new \controllers\internals\Command($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les users, sous forme d'un tableau permettant l'administration de ces users.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$commands = $this->internal_command->list_for_user($_SESSION['user']['id'], 25, $page);
$this->render('command/list', ['commands' => $commands]);
}
/**
* Cette fonction va supprimer une liste de commands.
*
* @param array int $_GET['ids'] : Les id des commandes à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
$this->redirect(\descartes\Router::url('Command', 'list'));
return false;
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_command->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Command', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'une commande.
*/
public function add()
{
$this->render('command/add');
}
/**
* Cette fonction retourne la page d'édition des commandes.
*
* @param array int $_GET['ids'] : Les id des commandes à editer
*/
public function edit()
{
$ids = $_GET['ids'] ?? [];
$commands = $this->internal_command->gets_in_for_user($_SESSION['user']['id'], $ids);
$this->render('command/edit', [
'commands' => $commands,
]);
}
/**
* Cette fonction insert une nouvelle commande.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['name'] : Le nom de la commande
* @param string $_POST['script'] : Le script a appeler
* @param bool $_POST['admin'] : Si la commande necessite les droits d'admin (par défaut non)
*
* @return boolean;
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Command', 'list'));
}
$name = $_POST['name'] ?? false;
$script = $_POST['script'] ?? false;
$admin = $_POST['admin'] ?? false;
if (!$name || !$script)
{
\FlashMessage\FlashMessage::push('danger', 'Renseignez au moins un nom et un script.');
return $this->redirect(\descartes\Router::url('Command', 'list'));
}
if (!$this->internal_command->create($_SESSION['user']['id'], $name, $script, $admin))
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer cette commande.');
return $this->redirect(\descartes\Router::url('commands', 'add'));
}
\FlashMessage\FlashMessage::push('success', 'La commande a bien été crée.');
return $this->redirect(\descartes\Router::url('Command', 'list'));
}
/**
* Cette fonction met à jour une commande.
*
* @param $csrf : Le jeton CSRF
* @param array $_POST['commands'] : Un tableau des commandes avec leur nouvelle valeurs
*
* @return boolean;
*/
public function update($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Command', 'list'));
}
$nb_commands_update = 0;
foreach ($_POST['commands'] as $command)
{
$update_command = $this->internal_command->update_for_user($_SESSION['user']['id'], $command['id'], $command['name'], $command['script'], $command['admin']);
$nb_commands_update += (int) $update_command;
}
if ($nb_commands_update !== \count($_POST['commands']))
{
\FlashMessage\FlashMessage::push('danger', 'Certaines commandes n\'ont pas pu êtres mises à jour.');
return $this->redirect(\descartes\Router::url('Command', 'list'));
}
\FlashMessage\FlashMessage::push('success', 'Toutes les commandes ont été modifiées avec succès.');
return $this->redirect(\descartes\Router::url('Command', 'list'));
}
}

View file

@ -1,245 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des groups.
*/
class ConditionalGroup extends \descartes\Controller
{
private $internal_conditional_group;
private $internal_contact;
private $internal_ruler;
private $internal_event;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_conditional_group = new \controllers\internals\ConditionalGroup($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
$this->internal_ruler = new \controllers\internals\Ruler();
\controllers\internals\Tool::verifyconnect();
}
/**
* Return all conditionnals groups for administration.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$groups = $this->internal_conditional_group->list_for_user($_SESSION['user']['id'], 25, $page);
$this->render('conditional_group/list', ['groups' => $groups]);
}
/**
* Cette fonction va supprimer une liste de groups.
*
* @param array int $_GET['ids'] : Les id des groups à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_conditional_group->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'un group.
*/
public function add()
{
$this->render('conditional_group/add');
}
/**
* Cette fonction retourne la page d'édition des groups.
*
* @param int... $ids : Les id des groups à supprimer
*/
public function edit()
{
$ids = $_GET['ids'] ?? [];
$groups = $this->internal_conditional_group->gets_in_for_user($_SESSION['user']['id'], $ids);
$this->render('conditional_group/edit', [
'groups' => $groups,
]);
}
/**
* Cette fonction insert un nouveau group.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['name'] : Le nom du group
* @param array $_POST['condition'] : The condition to used
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'add'));
}
$name = $_POST['name'] ?? false;
$condition = $_POST['condition'] ?? false;
if (!$name || !$condition)
{
\FlashMessage\FlashMessage::push('danger', 'Des champs sont manquants !');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'add'));
}
$id_group = $this->internal_conditional_group->create($_SESSION['user']['id'], $name, $condition);
if (!$id_group)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce groupe.');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'add'));
}
\FlashMessage\FlashMessage::push('success', 'Le groupe a bien été créé.');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
}
/**
* Cette fonction met à jour une group.
*
* @param $csrf : Le jeton CSRF
* @param array $_POST['groups'] : Un tableau des groups avec leur nouvelle valeurs & une entrée 'contacts_id' avec les ids des contacts pour chaque group
*
* @return boolean;
*/
public function update($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
}
$groups = $_POST['groups'] ?? [];
$nb_groups_update = 0;
foreach ($groups as $id => $group)
{
$nb_groups_update += (int) $this->internal_conditional_group->update_for_user($_SESSION['user']['id'], $id, $group['name'], $group['condition']);
}
if ($nb_groups_update !== \count($groups))
{
\FlashMessage\FlashMessage::push('danger', 'Certains groupes n\'ont pas pu êtres mis à jour.');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
}
\FlashMessage\FlashMessage::push('success', 'Tous les groupes ont été modifiés avec succès.');
return $this->redirect(\descartes\Router::url('ConditionalGroup', 'list'));
}
/**
* Try to get the preview of contacts for a conditionnal group.
*
* @param string $_POST['condition'] : Condition to apply
*
* @return mixed : False on error, json string ['success' => bool, 'result' => String with contacts]
*/
public function contacts_preview()
{
$return = [
'success' => false,
'result' => 'Une erreur inconnue est survenue.',
];
$condition = $_POST['condition'] ?? false;
if (!$condition)
{
$return['result'] = 'Vous devez renseigner une condition.';
echo json_encode($return);
return false;
}
$internal_ruler = new \controllers\internals\Ruler();
$valid_condition = $internal_ruler->validate_condition($condition, ['contact' => (object) ['datas' => (object) null]]);
if (!$valid_condition)
{
$return['result'] = 'Syntaxe de la condition invalide.';
echo json_encode($return);
return false;
}
$contacts = $this->internal_conditional_group->get_contacts_for_condition_and_user($_SESSION['user']['id'], $condition);
if (!$contacts)
{
$return['result'] = 'Aucun contact dans le groupe.';
echo json_encode($return);
return false;
}
$contacts_name = [];
foreach ($contacts as $contact)
{
$contacts_name[] = $contact['name'];
}
$return['result'] = 'Contacts du groupe : ' . implode(', ', $contacts_name);
$return['success'] = true;
echo json_encode($return);
return true;
}
/**
* Return the list of groups as JSON.
*/
public function json_list()
{
header('Content-Type: application/json');
echo json_encode($this->internal_conditional_group->list_for_user($_SESSION['user']['id']));
}
}

View file

@ -1,159 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page de connexion.
*/
class Connect extends \descartes\Controller
{
private $internal_user;
private $internal_setting;
/**
* Cette fonction est appelée avant toute les autres :.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_user = new \controllers\internals\User($bdd);
$this->internal_setting = new \controllers\internals\Setting($bdd);
}
/**
* Cette fonction retourne la fenetre de connexion.
*/
public function login()
{
if (\controllers\internals\Tool::is_connected())
{
return $this->redirect(\descartes\Router::url('Dashboard', 'show'));
}
return $this->render('connect/login');
}
/**
* Cette fonction connecte un utilisateur, et le redirige sur la page d'accueil.
*
* @param string $_POST['mail'] : L'email de l'utilisateur
* @param string $_POST['password'] : Le mot de passe de l'utilisateur
*/
public function connection()
{
$email = $_POST['mail'] ?? false;
$password = $_POST['password'] ?? false;
$user = $this->internal_user->check_credentials($email, $password);
if (!$user)
{
\FlashMessage\FlashMessage::push('danger', 'Email ou mot de passe invalide.');
return $this->redirect(\descartes\Router::url('Connect', 'login'));
}
$settings = $this->internal_setting->gets_for_user($user['id']);
$user['settings'] = $settings;
$_SESSION['connect'] = true;
$_SESSION['user'] = $user;
return $this->redirect(\descartes\Router::url('Dashboard', 'show'));
}
/**
* Cette fonction retourne la fenetre de changement de password.
*
* @return void;
*/
public function forget_password()
{
$this->render('connect/forget-password');
}
/**
* Cette fonction envoi un email contenant un lien pour re-générer un password oublié.
*
* @param string $csrf : jeton csrf
* @param string $_POST['email'] : L'email pour lequel on veut envoyer un nouveau password
*/
public function send_reset_password($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Connect', 'forget_password'));
}
$email = $_POST['email'] ?? false;
$user = $this->internal_user->get_by_email($email);
if (!$email || !$user)
{
\FlashMessage\FlashMessage::push('danger', 'Aucun utilisateur n\'existe pour cette adresse mail.');
return $this->redirect(\descartes\Router::url('Connect', 'forget_password'));
}
$Tokenista = new \Ingenerator\Tokenista(APP_SECRET);
$token = $Tokenista->generate(3600, ['user_id' => $user['id']]);
$reset_link = \descartes\Router::url('Connect', 'reset_password', ['user_id' => $user['id'], 'token' => $token]);
\controllers\internals\Tool::send_email($email, EMAIL_RESET_PASSWORD, ['reset_link' => $reset_link]);
return $this->render('connect/send-reset-password');
}
/**
* Cette fonction permet à un utilisateur de re-définir son mot de passe.
*
* @param int $user_id : L'id du user dont on veut modifier le password
* @param string $token : Le token permetttant de vérifier que l'opération est légitime
* @param optionnal $_POST['password'] : Le nouveau password à utiliser
*/
public function reset_password($user_id, $token)
{
$password = $_POST['password'] ?? false;
$Tokenista = new \Ingenerator\Tokenista(APP_SECRET);
if (!$Tokenista->isValid($token, ['user_id' => $user_id]))
{
return $this->render('connect/reset-password-invalid');
}
if (!$password)
{
return $this->render('connect/reset-password');
}
$this->internal_user->update_password($user_id, $password);
return $this->render('connect/reset-password-done');
}
/**
* Cette fonction déconnecte un utilisateur et le renvoie sur la page d'accueil.
*/
public function logout()
{
session_destroy();
$_SESSION = [];
return $this->redirect(\descartes\Router::url('Connect', 'login'));
}
}

View file

@ -1,376 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des contacts.
*/
class Contact extends \descartes\Controller
{
private $internal_contact;
private $internal_event;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les contacts, sous forme d'un tableau permettant l'administration de ces contacts.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$contacts = $this->internal_contact->list_for_user($_SESSION['user']['id'], 25, $page);
return $this->render('contact/list', ['contacts' => $contacts]);
}
/**
* Cette fonction va supprimer une liste de contacts.
*
* @param array int $_GET['ids'] : Les id des contactes à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_contact->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'un contact.
*/
public function add()
{
$this->render('contact/add');
}
/**
* Cette fonction retourne la page d'édition des contacts.
*
* @param int... $ids : Les id des contactes à supprimer
*/
public function edit()
{
$ids = $_GET['ids'] ?? [];
$id_user = $_SESSION['user']['id'];
$contacts = $this->internal_contact->gets_in_for_user($id_user, $ids);
if (!$contacts)
{
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
foreach ($contacts as &$contact)
{
if ($contact['datas'])
{
$contact['datas'] = json_decode($contact['datas']);
}
}
$this->render('contact/edit', [
'contacts' => $contacts,
]);
}
/**
* Cette fonction insert un nouveau contact.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['name'] : Le nom du contact
* @param string $_POST['phone'] : Le numero de téléphone du contact
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Contact', 'add'));
}
$name = $_POST['name'] ?? false;
$number = $_POST['number'] ?? false;
$id_user = $_SESSION['user']['id'];
$datas = $_POST['datas'] ?? [];
if (!$name || !$number)
{
\FlashMessage\FlashMessage::push('danger', 'Des champs sont manquants !');
return $this->redirect(\descartes\Router::url('Contact', 'add'));
}
$number = \controllers\internals\Tool::parse_phone($number);
if (!$number)
{
\FlashMessage\FlashMessage::push('danger', 'Numéro de téléphone incorrect.');
return $this->redirect(\descartes\Router::url('Contact', 'add'));
}
$clean_datas = [];
foreach ($datas as $key => $value)
{
if ('' === $value)
{
continue;
}
$key = mb_ereg_replace('[\W]', '', $key);
$clean_datas[$key] = (string) $value;
}
$clean_datas = json_encode($clean_datas);
if (!$this->internal_contact->create($id_user, $number, $name, $clean_datas))
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce contact.');
return $this->redirect(\descartes\Router::url('Contact', 'add'));
}
\FlashMessage\FlashMessage::push('success', 'Le contact a bien été créé.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
/**
* Cette fonction met à jour une contacte.
*
* @param $csrf : Le jeton CSRF
* @param array $_POST['contacts'] : Un tableau des contactes avec leur nouvelle valeurs
*
* @return boolean;
*/
public function update($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
if (![$_POST['contacts']])
{
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$nb_contacts_update = 0;
foreach ($_POST['contacts'] as $id_contact => $contact)
{
$name = $contact['name'] ?? false;
$number = $contact['number'] ?? false;
$id_user = $_SESSION['user']['id'];
$datas = $contact['datas'] ?? [];
if (!$name || !$number)
{
continue;
}
$number = \controllers\internals\Tool::parse_phone($number);
if (!$number)
{
continue;
}
$clean_datas = [];
foreach ($datas as $key => $value)
{
if ('' === $value)
{
continue;
}
$key = mb_ereg_replace('[\W]', '', $key);
$clean_datas[$key] = (string) $value;
}
$clean_datas = json_encode($clean_datas);
$nb_contacts_update += (int) $this->internal_contact->update_for_user($id_user, $id_contact, $number, $name, $clean_datas);
}
if ($nb_contacts_update !== \count($_POST['contacts']))
{
\FlashMessage\FlashMessage::push('danger', 'Certains contacts n\'ont pas pu êtres mis à jour.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
\FlashMessage\FlashMessage::push('success', 'Tous les contacts ont été modifiés avec succès.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
/**
* Allow to import a contacts list.
*
* @param string $csrf : Csrf token
* @param $_FILES['contacts_list_file'] : A csv file of the contacts to import
*/
public function import(string $csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$id_user = $_SESSION['user']['id'];
$upload_array = $_FILES['contacts_list_file'] ?? false;
if (!$upload_array)
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez fournir un fichier de contacts à importer.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$read_file = \controllers\internals\Tool::read_uploaded_file($upload_array);
if (!$read_file['success'])
{
\FlashMessage\FlashMessage::push('danger', $read_file['content']);
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
//Try to import file
$invalid_type = false;
switch ($read_file['mime_type'])
{
case 'text/csv':
$result = $this->internal_contact->import_csv($id_user, $read_file['content']);
break;
case 'application/json':
$result = $this->internal_contact->import_json($id_user, $read_file['content']);
break;
default:
$invalid_type = true;
}
if ($invalid_type)
{
\FlashMessage\FlashMessage::push('danger', 'Le type de fichier n\'est pas valide.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
if (false === $result)
{
\FlashMessage\FlashMessage::push('danger', 'Le fichier contient des erreurs. Impossible d\'importer les contacts.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$msg = $result . ' nouveau contact a été inséré.';
if ($result > 1)
{
$msg = $result . ' nouveaux contacts ont été insérés.';
}
\FlashMessage\FlashMessage::push('success', $msg);
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
/**
* Allow to export a contacts list.
*
* @param $format : Format to export contacts to
*/
public function export(string $format)
{
$id_user = $_SESSION['user']['id'];
//Try to export contacts
$invalid_type = false;
switch ($format)
{
case 'csv':
$result = $this->internal_contact->export_csv($id_user);
break;
case 'json':
$result = $this->internal_contact->export_json($id_user);
break;
default:
$invalid_type = true;
}
if ($invalid_type)
{
\FlashMessage\FlashMessage::push('danger', 'Le format demandé n\'est pas supporté.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
if (false === $result)
{
\FlashMessage\FlashMessage::push('danger', 'Nous ne sommes par parveu à exporté les contacts.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$result['headers'] = $result['headers'] ?? [];
foreach ($result['headers'] as $header)
{
header($header);
}
echo $result['content'];
}
/**
* Cette fonction retourne la liste des contacts sous forme JSON.
*/
public function json_list()
{
header('Content-Type: application/json');
echo json_encode($this->internal_contact->list_for_user($_SESSION['user']['id']));
}
}

View file

@ -1,135 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page d'index, qui gère l'affichage par défaut temporairement.
*/
class Dashboard extends \descartes\Controller
{
private $internal_sended;
private $internal_received;
private $internal_contact;
private $internal_group;
private $internal_scheduled;
private $internal_event;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_sended = new \controllers\internals\Sended($bdd);
$this->internal_received = new \controllers\internals\Received($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_group = new \controllers\internals\Group($bdd);
$this->internal_scheduled = new \controllers\internals\Scheduled($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction est un alias de show.
*
* @return void;
*/
public function show()
{
$id_user = $_SESSION['user']['id'];
//Recupération des nombres des 4 panneaux d'accueil
$nb_contacts = $this->internal_contact->count_for_user($id_user);
$nb_groups = $this->internal_group->count_for_user($id_user);
$nb_scheduleds = $this->internal_scheduled->count_for_user($id_user);
$nb_unreads = $this->internal_received->count_unread_for_user($id_user);
$nb_sendeds = $this->internal_sended->count_for_user($id_user);
$nb_receiveds = $this->internal_received->count_for_user($id_user);
//Création de la date d'il y a une semaine
$now = new \DateTime();
$one_week = new \DateInterval('P7D');
$date = $now->sub($one_week);
$formated_date = $date->format('Y-m-d');
//Récupération des 10 derniers Sms envoyés, Sms reçus et evenements enregistrés. Par date.
$sendeds = $this->internal_sended->get_lasts_by_date_for_user($id_user, 10);
$receiveds = $this->internal_received->get_lasts_by_date_for_user($id_user, 10);
$events = $this->internal_event->get_lasts_by_date_for_user($id_user, 10);
//Récupération du nombre de Sms envoyés et reçus depuis les 7 derniers jours
$nb_sendeds_by_day = $this->internal_sended->count_by_day_since_for_user($id_user, $formated_date);
$nb_receiveds_by_day = $this->internal_received->count_by_day_since_for_user($id_user, $formated_date);
//On va traduire ces données pour les afficher en graphique
$array_area_chart = [];
$today_less_7_day = new \DateTime();
$today_less_7_day->sub(new \DateInterval('P7D'));
$increment_day = new \DateInterval('P1D');
$i = 0;
//On va construire un tableau avec la date en clef, et les données pour chaque date
while ($i < 7)
{
$today_less_7_day->add($increment_day);
++$i;
$date_f = $today_less_7_day->format('Y-m-d');
$array_area_chart[$date_f] = [
'period' => $date_f,
'sendeds' => 0,
'receiveds' => 0,
];
}
$total_sendeds = 0;
$total_receiveds = 0;
//0n remplie le tableau avec les données adaptées
foreach ($nb_sendeds_by_day as $date => $nb_sended)
{
$array_area_chart[$date]['sendeds'] = $nb_sended;
$total_sendeds += $nb_sended;
}
foreach ($nb_receiveds_by_day as $date => $nb_received)
{
$array_area_chart[$date]['receiveds'] = $nb_received;
$total_receiveds += $nb_received;
}
$avg_sendeds = round($total_sendeds / 7, 2);
$avg_receiveds = round($total_receiveds / 7, 2);
$array_area_chart = array_values($array_area_chart);
$this->render('dashboard/show', [
'nb_contacts' => $nb_contacts,
'nb_groups' => $nb_groups,
'nb_scheduleds' => $nb_scheduleds,
'nb_sendeds' => $nb_sendeds,
'nb_receiveds' => $nb_receiveds,
'nb_unreads' => $nb_unreads,
'avg_sendeds' => $avg_sendeds,
'avg_receiveds' => $avg_receiveds,
'sendeds' => $sendeds,
'receiveds' => $receiveds,
'events' => $events,
'datas_area_chart' => json_encode($array_area_chart),
]);
}
}

View file

@ -1,290 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des discussions.
*/
class Discussion extends \descartes\Controller
{
private $internal_sended;
private $internal_scheduled;
private $internal_received;
private $internal_contact;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_sended = new \controllers\internals\Sended($bdd);
$this->internal_scheduled = new \controllers\internals\Scheduled($bdd);
$this->internal_received = new \controllers\internals\Received($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne toutes les discussions, sous forme d'un tableau permettant l'administration de ces contacts.
*/
public function list()
{
$discussions = $this->internal_received->get_discussions_for_user($_SESSION['user']['id']);
foreach ($discussions as $key => $discussion)
{
if (!$contact = $this->internal_contact->get_by_number_and_user($_SESSION['user']['id'], $discussion['number']))
{
continue;
}
$discussions[$key]['contact'] = $contact['name'];
}
$this->render('discussion/list', [
'discussions' => $discussions,
]);
}
/**
* Cette fonction permet d'afficher la discussion avec un numero.
*
* @param string $number : La numéro de téléphone avec lequel on discute
*/
public function show($number)
{
$contact = $this->internal_contact->get_by_number_and_user($_SESSION['user']['id'], $number);
$last_sended = $this->internal_sended->get_last_for_destination_and_user($_SESSION['user']['id'], $number);
$last_received = $this->internal_received->get_last_for_origin_and_user($_SESSION['user']['id'], $number);
$response_number = ($last_received['destination'] ?? $last_sended['origin'] ?? false);
$this->render('discussion/show', [
'number' => $number,
'contact' => $contact,
'response_number' => $response_number,
]);
}
/**
* Cette fonction récupère l'ensemble des messages pour un numéro, recçus, envoyés, en cours.
*
* @param string $number : Le numéro cible
* @param string $transaction_id : Le numéro unique de la transaction ajax (sert à vérifier si la requete doit être prise en compte)
*/
public function get_messages($number, $transaction_id)
{
$now = new \DateTime();
$now = $now->format('Y-m-d H:i:s');
$id_user = $_SESSION['user']['id'];
$sendeds = $this->internal_sended->gets_by_destination_and_user($id_user, $number);
$receiveds = $this->internal_received->gets_by_origin_and_user($id_user, $number);
$scheduleds = $this->internal_scheduled->gets_before_date_for_number_and_user($id_user, $now, $number);
$messages = [];
foreach ($sendeds as $sended)
{
$messages[] = [
'date' => htmlspecialchars($sended['at']),
'text' => htmlspecialchars($sended['text']),
'type' => 'sended',
'status' => $sended['status'],
];
}
foreach ($receiveds as $received)
{
if ('read' !== $received['status'])
{
$this->internal_received->mark_as_read_for_user($id_user, $received['id']);
}
$messages[] = [
'date' => htmlspecialchars($received['at']),
'text' => htmlspecialchars($received['text']),
'type' => 'received',
'md5' => md5($received['at'] . $received['text']),
];
}
foreach ($scheduleds as $scheduled)
{
$messages[] = [
'date' => htmlspecialchars($scheduled['at']),
'text' => htmlspecialchars($scheduled['text']),
'type' => 'inprogress',
];
}
//On va trier le tableau des messages
usort($messages, function ($a, $b)
{
return strtotime($a['date']) - strtotime($b['date']);
});
//On récupère uniquement les 25 derniers messages sur l'ensemble
$messages = \array_slice($messages, -25);
echo json_encode(['transaction_id' => $transaction_id, 'messages' => $messages]);
return true;
}
/**
* Cette fonction permet d'envoyer facilement un sms à un numéro donné.
*
* @param string $csrf : Le jeton csrf
* @param string $_POST['text'] : Le contenu du Sms
* @param string $_POST['destination'] : Number to send sms to
* @param string $_POST['origin'] : Number to send sms with
*
* @return string : json string Le statut de l'envoi
*/
public function send($csrf)
{
$return = ['success' => true, 'message' => ''];
//On vérifie que le jeton csrf est bon
if (!$this->verify_csrf($csrf))
{
$return['success'] = false;
$return['message'] = 'Jeton CSRF invalide';
echo json_encode($return);
return false;
}
$now = new \DateTime();
$now = $now->format('Y-m-d H:i:s');
$id_user = $_SESSION['user']['id'];
$at = $now;
$text = $_POST['text'] ?? '';
$destination = $_POST['destination'] ?? false;
$origin = $_POST['origin'] ?? false;
if (!$destination)
{
$return['success'] = false;
$return['message'] = 'Vous devez renseigner un numéro valide';
echo json_encode($return);
return false;
}
if (!$origin)
{
$origin = null;
}
//Destinations must be an array of number
$destinations = [$destination];
if (!$this->internal_scheduled->create($id_user, $at, $text, $origin, false, $destinations))
{
$return['success'] = false;
$return['message'] = 'Impossible de créer le Sms';
echo json_encode($return);
return false;
}
echo json_encode($return);
return true;
}
/**
* Cette fonction retourne les id des sms qui sont envoyés.
*
* @return string : json string Tableau des ids des sms qui sont envoyés
*/
public function checksendeds()
{
$_SESSION['discussion_wait_progress'] = isset($_SESSION['discussion_wait_progress']) ? $_SESSION['discussion_wait_progress'] : [];
$scheduleds = $this->internal_scheduled->gets_in_for_user($_SESSION['user']['id'], $_SESSION['discussion_wait_progress']);
//On va chercher à chaque fois si on a trouvé le sms. Si ce n'est pas le cas c'est qu'il a été envoyé
$sendeds = [];
foreach ($_SESSION['discussion_wait_progress'] as $key => $id_scheduled)
{
$found = false;
foreach ($scheduleds as $scheduled)
{
if ($id_scheduled === $scheduled['id'])
{
$found = true;
}
}
if (!$found)
{
unset($_SESSION['discussion_wait_progress'][$key]);
$sendeds[] = $id_scheduled;
}
}
echo json_encode($sendeds);
return true;
}
/**
* Cette fonction retourne les messages reçus pour un numéro après la date $_SESSION['discussion_last_checkreceiveds'].
*
* @param string $number : Le numéro de téléphone pour lequel on veux les messages
*
* @return string : json string Un tableau avec les messages
*/
public function checkreceiveds($number)
{
$now = new \DateTime();
$now = $now->format('Y-m-d H:i');
$_SESSION['discussion_last_checkreceiveds'] = isset($_SESSION['discussion_last_checkreceiveds']) ? $_SESSION['discussion_last_checkreceiveds'] : $now;
$receiveds = $this->internal_received->get_since_for_number_by_date($_SESSION['discussion_last_checkreceiveds'], $number);
//On va gérer le cas des messages en double en stockant ceux déjà reçus et en eliminant les autres
$_SESSION['discussion_already_receiveds'] = isset($_SESSION['discussion_already_receiveds']) ? $_SESSION['discussion_already_receiveds'] : [];
foreach ($receiveds as $key => $received)
{
//Sms jamais recu
if (false === array_search($received['id'], $_SESSION['discussion_already_receiveds'], true))
{
$_SESSION['discussion_already_receiveds'][] = $received['id'];
continue;
}
//Sms déjà reçu => on le supprime des resultats
unset($receiveds[$key]);
}
//On met à jour la date de dernière verif
$_SESSION['discussion_last_checkreceiveds'] = $now;
echo json_encode($receiveds);
}
}

View file

@ -1,74 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des events.
*/
class Event extends \descartes\Controller
{
private $internal_event;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_event = new \controllers\internals\Event($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les events, sous forme d'un tableau permettant l'administration de ces events.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$limit = 25;
$events = $this->internal_event->list_for_user($_SESSION['user']['id'], $limit, $page);
$this->render('event/list', ['events' => $events, 'limit' => $limit, 'page' => $page, 'nb_results' => \count($events)]);
}
/**
* Cette fonction va supprimer une liste de events.
*
* @param array int $_GET['ids'] : Les id des eventes à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Event', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_event->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Event', 'list'));
}
}

View file

@ -1,198 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des groups.
*/
class Group extends \descartes\Controller
{
private $internal_group;
private $internal_contact;
private $internal_event;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_group = new \controllers\internals\Group($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les groups, sous forme d'un tableau permettant l'administration de ces groups.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$groups = $this->internal_group->list_for_user($_SESSION['user']['id'], 25, $page);
foreach ($groups as $key => $group)
{
$contacts = $this->internal_group->get_contacts($group['id']);
$groups[$key]['nb_contacts'] = \count($contacts);
}
$this->render('group/list', ['groups' => $groups]);
}
/**
* Cette fonction va supprimer une liste de groups.
*
* @param array int $_GET['ids'] : Les id des groups à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Group', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_group->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Group', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'un group.
*/
public function add()
{
$this->render('group/add');
}
/**
* Cette fonction retourne la page d'édition des groups.
*
* @param int... $ids : Les id des groups à supprimer
*/
public function edit()
{
$ids = $_GET['ids'] ?? [];
$groups = $this->internal_group->gets_in_for_user($_SESSION['user']['id'], $ids);
foreach ($groups as $key => $group)
{
$groups[$key]['contacts'] = $this->internal_group->get_contacts($group['id']);
}
$this->render('group/edit', [
'groups' => $groups,
]);
}
/**
* Cette fonction insert un nouveau group.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['name'] : Le nom du group
* @param array $_POST['contacts'] : Les ids des contacts à mettre dans le group
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Group', 'add'));
}
$name = $_POST['name'] ?? false;
$contacts_ids = $_POST['contacts'] ?? false;
if (!$name || !$contacts_ids)
{
\FlashMessage\FlashMessage::push('danger', 'Des champs sont manquants !');
return $this->redirect(\descartes\Router::url('Group', 'add'));
}
$id_group = $this->internal_group->create($_SESSION['user']['id'], $name, $contacts_ids);
if (!$id_group)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce groupe.');
return $this->redirect(\descartes\Router::url('Group', 'add'));
}
\FlashMessage\FlashMessage::push('success', 'Le groupe a bien été créé.');
return $this->redirect(\descartes\Router::url('Group', 'list'));
}
/**
* Cette fonction met à jour une group.
*
* @param $csrf : Le jeton CSRF
* @param array $_POST['groups'] : Un tableau des groups avec leur nouvelle valeurs & une entrée 'contacts_id' avec les ids des contacts pour chaque group
*
* @return boolean;
*/
public function update($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Group', 'list'));
}
$groups = $_POST['groups'] ?? [];
$nb_groups_update = 0;
foreach ($groups as $id => $group)
{
$nb_groups_update += (int) $this->internal_group->update_for_user($_SESSION['user']['id'], $id, $group['name'], $group['contacts_ids']);
}
if ($nb_groups_update !== \count($groups))
{
\FlashMessage\FlashMessage::push('danger', 'Certains groupes n\'ont pas pu êtres mis à jour.');
return $this->redirect(\descartes\Router::url('Group', 'list'));
}
\FlashMessage\FlashMessage::push('success', 'Tous les groupes ont été modifiés avec succès.');
return $this->redirect(\descartes\Router::url('Group', 'list'));
}
/**
* Cette fonction retourne la liste des groups sous forme JSON.
*/
public function json_list()
{
header('Content-Type: application/json');
echo json_encode($this->internal_group->list_for_user($_SESSION['user']['id']));
}
}

View file

@ -1,208 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des phones.
*/
class Phone extends \descartes\Controller
{
private $internal_phone;
private $internal_adapter;
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_phone = new \controllers\internals\Phone($bdd);
$this->internal_adapter = new \controllers\internals\Adapter();
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les phones, sous forme d'un tableau permettant l'administration de ces phones.
*
* @param mixed $page
*/
public function list($page = 0)
{
$id_user = $_SESSION['user']['id'];
$page = (int) $page;
$phones = $this->internal_phone->list_for_user($id_user, 25, $page);
$adapters = [];
$adapters_metas = $this->internal_adapter->list_adapters();
foreach ($adapters_metas as $adapter_metas)
{
$adapters[$adapter_metas['meta_classname']] = $adapter_metas['meta_name'];
}
foreach ($phones as &$phone)
{
$phone['adapter'] = $adapters[$phone['adapter']] ?? 'Inconnu';
}
$this->render('phone/list', ['phones' => $phones]);
}
/**
* Cette fonction va supprimer une liste de phones.
*
* @param array int $_GET['ids'] : Les id des phonees à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Phone', 'list'));
}
if (!\controllers\internals\Tool::is_admin())
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez être administrateur pour supprimer un utilisateur !');
return $this->redirect(\descartes\Router::url('Phone', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_phone->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Phone', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'un phone.
*/
public function add()
{
$adapters = $this->internal_adapter->list_adapters();
return $this->render('phone/add', ['adapters' => $adapters]);
}
/**
* Create a new phone.
*
* @param $csrf : CSRF token
* @param string $_POST['number'] : Phone number
* @param string $_POST['adapter'] : Phone adapter
* @param array $_POST['adapter_datas'] : Phone adapter datas
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$id_user = $_SESSION['user']['id'];
$number = $_POST['number'] ?? false;
$adapter = $_POST['adapter'] ?? false;
$adapter_datas = !empty($_POST['adapter_datas']) ? $_POST['adapter_datas'] : [];
if (!$number || !$adapter)
{
\FlashMessage\FlashMessage::push('danger', 'Des champs obligatoires sont manquants.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$number = \controllers\internals\Tool::parse_phone($number);
if (!$number)
{
\FlashMessage\FlashMessage::push('danger', 'Numéro de téléphone incorrect.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$number_exist = $this->internal_phone->get_by_number($number);
if ($number_exist)
{
\FlashMessage\FlashMessage::push('danger', 'Ce numéro de téléphone est déjà utilisé.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$adapters = $this->internal_adapter->list_adapters();
$find_adapter = false;
foreach ($adapters as $metas)
{
if ($metas['meta_classname'] === $adapter)
{
$find_adapter = $metas;
break;
}
}
if (!$find_adapter)
{
\FlashMessage\FlashMessage::push('danger', 'Cet adaptateur n\'existe pas.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
//If missing required data fields, error
foreach ($find_adapter['meta_datas_fields'] as $field)
{
if (false === $field['required'])
{
continue;
}
if (!empty($adapter_datas[$field['name']]))
{
continue;
}
\FlashMessage\FlashMessage::push('danger', 'Vous n\'avez pas rempli certains champs obligatoires pour l\'adaptateur choisis.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$adapter_datas = json_encode($adapter_datas);
//Check adapter is working correctly with thoses numbers and datas
$adapter_classname = $find_adapter['meta_classname'];
$adapter_instance = new $adapter_classname($number, $adapter_datas);
$adapter_working = $adapter_instance->test();
if (!$adapter_working)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible d\'utiliser l\'adaptateur choisis avec les données fournies. Vérifiez le numéro de téléphone et les réglages.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$success = $this->internal_phone->create($id_user, $number, $adapter, $adapter_datas);
if (!$success)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce téléphone.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
\FlashMessage\FlashMessage::push('success', 'Le téléphone a bien été créé.');
return $this->redirect(\descartes\Router::url('Phone', 'list'));
}
}

View file

@ -1,155 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des receiveds.
*/
class Received extends \descartes\Controller
{
private $internal_received;
private $internal_contact;
private $internal_phone;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_received = new \controllers\internals\Received($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_phone = new \controllers\internals\Phone($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les receiveds, sous forme d'un tableau permettant l'administration de ces receiveds.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$limit = 25;
$receiveds = $this->internal_received->list_for_user($_SESSION['user']['id'], $limit, $page);
foreach ($receiveds as $key => $received)
{
if ('read' !== $received['status'])
{
$this->internal_received->mark_as_read_for_user($_SESSION['user']['id'], $received['id']);
}
if (!$contact = $this->internal_contact->get_by_number_and_user($_SESSION['user']['id'], $received['origin']))
{
continue;
}
$receiveds[$key]['origin'] = $contact['name'] . ' (' . $received['origin'] . ')';
}
$this->render('received/list', ['receiveds' => $receiveds, 'page' => $page, 'limit' => $limit, 'nb_results' => \count($receiveds)]);
}
/**
* Return all unread receiveds messages.
*
* @param mixed $page
*/
public function list_unread($page = 0)
{
$page = (int) $page;
$limit = 25;
$receiveds = $this->internal_received->list_unread_for_user($_SESSION['user']['id'], $limit, $page);
foreach ($receiveds as $key => $received)
{
$this->internal_received->mark_as_read_for_user($_SESSION['user']['id'], $received['id']);
if (!$contact = $this->internal_contact->get_by_number_and_user($_SESSION['user']['id'], $received['origin']))
{
continue;
}
$receiveds[$key]['origin'] = $contact['name'] . ' (' . $received['origin'] . ')';
}
$this->render('received/list_unread', ['receiveds' => $receiveds, 'page' => $page, 'limit' => $limit, 'nb_results' => \count($receiveds)]);
}
/**
* Delete Receiveds.
*
* @param array int $_GET['ids'] : Ids of receiveds to delete
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Received', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_received->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Received', 'list'));
}
/**
* Cette fonction retourne tous les Sms reçus aujourd'hui pour la popup.
*
* @return string : A JSON Un tableau des Sms reçus
*/
public function popup()
{
$now = new \DateTime();
$receiveds = $this->internal_received->get_since_by_date_for_user($_SESSION['user']['id'], $now->format('Y-m-d'));
foreach ($receiveds as $key => $received)
{
if (!$contact = $this->internal_contact->get_by_number_and_user($_SESSION['user']['id'], $received['origin']))
{
continue;
}
$receiveds[$key]['origin'] = $this->s($contact['name'], false, true, false) . ' (' . \controllers\internals\Tool::phone_link($received['origin']) . ')';
}
$nb_received = \count($receiveds);
if (!isset($_SESSION['popup_nb_receiveds']) || $_SESSION['popup_nb_receiveds'] > $nb_received)
{
$_SESSION['popup_nb_receiveds'] = $nb_received;
}
$newly_receiveds = \array_slice($receiveds, $_SESSION['popup_nb_receiveds']);
$_SESSION['popup_nb_receiveds'] = $nb_received;
echo json_encode($newly_receiveds);
return true;
}
}

View file

@ -1,427 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des scheduleds.
*/
class Scheduled extends \descartes\Controller
{
private $internal_scheduled;
private $internal_phone;
private $internal_contact;
private $internal_group;
private $internal_conditional_group;
private $internal_media;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_scheduled = new \controllers\internals\Scheduled($bdd);
$this->internal_phone = new \controllers\internals\Phone($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_group = new \controllers\internals\Group($bdd);
$this->internal_conditional_group = new \controllers\internals\ConditionalGroup($bdd);
$this->internal_media = new \controllers\internals\Media($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les scheduleds, sous forme d'un tableau permettant l'administration de ces scheduleds.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$scheduleds = $this->internal_scheduled->list_for_user($_SESSION['user']['id'], 25, $page);
$this->render('scheduled/list', ['scheduleds' => $scheduleds]);
}
/**
* Cette fonction va supprimer une liste de scheduleds.
*
* @param array int $_GET['ids'] : Les id des scheduledes à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$scheduled = $this->internal_scheduled->get($id);
if (!$scheduled || $scheduled['id_user'] !== $_SESSION['user']['id'])
{
continue;
}
$this->internal_scheduled->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'un scheduled.
*
* @param $prefilled : If we have prefilled some fields (possible values : 'contacts', 'groups', 'conditional_groups', false)
*/
public function add($prefilled = false)
{
$now = new \DateTime();
$less_one_minute = new \DateInterval('PT1M');
$now->sub($less_one_minute);
$id_user = $_SESSION['user']['id'];
$contacts = $this->internal_contact->gets_for_user($id_user);
$phones = $this->internal_phone->gets_for_user($id_user);
$prefilled_contacts = [];
$prefilled_groups = [];
$prefilled_conditional_groups = [];
if ($prefilled)
{
$ids = $_GET['ids'] ?? [];
}
if ('contacts' === $prefilled)
{
foreach ($this->internal_contact->gets_in_for_user($id_user, $ids) as $contact)
{
$prefilled_contacts[] = $contact['id'];
}
}
elseif ('groups' === $prefilled)
{
foreach ($this->internal_group->gets_in_for_user($id_user, $ids) as $group)
{
$prefilled_groups[] = $group['id'];
}
}
elseif ('conditional_groups' === $prefilled)
{
foreach ($this->internal_conditional_group->gets_in_for_user($id_user, $ids) as $conditional_group)
{
$prefilled_conditional_groups[] = $conditional_group['id'];
}
}
$this->render('scheduled/add', [
'now' => $now->format('Y-m-d H:i'),
'contacts' => $contacts,
'phones' => $phones,
'prefilled_contacts' => $prefilled_contacts,
'prefilled_groups' => $prefilled_groups,
'prefilled_conditional_groups' => $prefilled_conditional_groups,
]);
}
/**
* Cette fonction retourne la page d'édition des scheduleds.
*
* @param int... $ids : Les id des scheduledes à supprimer
*/
public function edit()
{
$ids = $_GET['ids'] ?? [];
if (!$ids)
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez choisir des messages à mettre à jour !');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
$id_user = $_SESSION['user']['id'];
$all_contacts = $this->internal_contact->gets_for_user($_SESSION['user']['id']);
$phones = $this->internal_phone->gets_for_user($_SESSION['user']['id']);
$scheduleds = $this->internal_scheduled->gets_in_for_user($_SESSION['user']['id'], $ids);
//Pour chaque message on ajoute les numéros, les contacts & les groups
foreach ($scheduleds as $key => $scheduled)
{
if (!$scheduled || $scheduled['id_user'] !== $_SESSION['user']['id'])
{
continue;
}
$scheduleds[$key]['numbers'] = [];
$scheduleds[$key]['contacts'] = [];
$scheduleds[$key]['groups'] = [];
$scheduleds[$key]['conditional_groups'] = [];
$numbers = $this->internal_scheduled->get_numbers($scheduled['id']);
foreach ($numbers as $number)
{
$scheduleds[$key]['numbers'][] = $number['number'];
}
$contacts = $this->internal_scheduled->get_contacts($scheduled['id']);
foreach ($contacts as $contact)
{
$scheduleds[$key]['contacts'][] = (int) $contact['id'];
}
$groups = $this->internal_scheduled->get_groups($scheduled['id']);
foreach ($groups as $group)
{
$scheduleds[$key]['groups'][] = (int) $group['id'];
}
$media = $this->internal_media->get_for_scheduled_and_user($id_user, $scheduled['id']);
$scheduleds[$key]['media'] = $media;
$conditional_groups = $this->internal_scheduled->get_conditional_groups($scheduled['id']);
foreach ($conditional_groups as $conditional_group)
{
$scheduleds[$key]['conditional_groups'][] = (int) $conditional_group['id'];
}
}
$this->render('scheduled/edit', [
'scheduleds' => $scheduleds,
'phones' => $phones,
'contacts' => $all_contacts,
]);
}
/**
* Cette fonction insert un nouveau scheduled.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['name'] : Le nom du scheduled
* @param string $_POST['date'] : La date d'envoie du scheduled
* @param string $_POST['numbers'] : Les numeros de téléphone du scheduled
* @param string $_POST['contacts'] : Les contacts du scheduled
* @param string $_POST['groups'] : Les groups du scheduled
* @param array $_FILES['media'] : The media to link to a scheduled
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Scheduled', 'add'));
}
$id_user = $_SESSION['user']['id'];
$at = $_POST['at'] ?? false;
$text = $_POST['text'] ?? false;
$flash = (bool) ($_POST['flash'] ?? false);
$origin = empty($_POST['origin']) ? null : $_POST['origin'];
$numbers = $_POST['numbers'] ?? [];
$contacts = $_POST['contacts'] ?? [];
$groups = $_POST['groups'] ?? [];
$conditional_groups = $_POST['conditional_groups'] ?? [];
if (empty($text))
{
\FlashMessage\FlashMessage::push('danger', 'Vous ne pouvez pas créer un Sms sans message.');
return $this->redirect(\descartes\Router::url('Scheduled', 'add'));
}
if (!\controllers\internals\Tool::validate_date($at, 'Y-m-d H:i:s') && !\controllers\internals\Tool::validate_date($at, 'Y-m-d H:i'))
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez fournir une date valide.');
return $this->redirect(\descartes\Router::url('Scheduled', 'add'));
}
foreach ($numbers as $key => $number)
{
$number = \controllers\internals\Tool::parse_phone($number);
if (!$number)
{
unset($numbers[$key]);
continue;
}
$numbers[$key] = $number;
}
if (!$numbers && !$contacts && !$groups && !$conditional_groups)
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez renseigner au moins un destinataire pour le Sms.');
return $this->redirect(\descartes\Router::url('Scheduled', 'add'));
}
if ($origin && !$this->internal_phone->get_by_number_and_user($id_user, $origin))
{
\FlashMessage\FlashMessage::push('danger', 'Ce numéro n\'existe pas ou vous n\'en êtes pas propriétaire.');
return $this->redirect(\descartes\Router::url('Scheduled', 'add'));
}
$scheduled_id = $this->internal_scheduled->create($id_user, $at, $text, $origin, $flash, $numbers, $contacts, $groups, $conditional_groups);
if (!$scheduled_id)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer le Sms.');
return $this->redirect(\descartes\Router::url('Scheduled', 'add'));
}
//If mms is enabled, try to process a media to link to the scheduled
$media = $_FILES['media'] ?? false;
if (!($_SESSION['user']['settings']['mms'] ?? false) || !$media)
{
\FlashMessage\FlashMessage::push('success', 'Le Sms a bien été créé pour le ' . $at . '.');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
$success = $this->internal_media->create($id_user, $scheduled_id, $media);
if (!$success)
{
\FlashMessage\FlashMessage::push('success', 'Le SMS a bien été créé mais le média n\'as pas pu être enregistré.');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
\FlashMessage\FlashMessage::push('success', 'Le Sms a bien été créé pour le ' . $at . '.');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
/**
* Cette fonction met à jour un scheduled.
*
* @param $csrf : Le jeton CSRF
* @param array $_POST['scheduleds'] : Un tableau des scheduledes avec leur nouvelle valeurs + les numbers, contacts et groups liées
*
* @return boolean;
*/
public function update($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
$scheduleds = $_POST['scheduleds'] ?? [];
$nb_update = 0;
foreach ($scheduleds as $id_scheduled => $scheduled)
{
$id_user = $_SESSION['user']['id'];
$at = $scheduled['at'] ?? false;
$text = $scheduled['text'] ?? false;
$origin = empty($scheduled['origin']) ? null : $scheduled['origin'];
$flash = (bool) ($scheduled['flash'] ?? false);
$numbers = $scheduled['numbers'] ?? [];
$contacts = $scheduled['contacts'] ?? [];
$groups = $scheduled['groups'] ?? [];
$conditional_groups = $scheduled['conditional_groups'] ?? [];
$scheduled = $this->internal_scheduled->get($id_scheduled);
if (!$scheduled || $scheduled['id_user'] !== $id_user)
{
continue;
}
if (empty($text))
{
continue;
}
if (!\controllers\internals\Tool::validate_date($at, 'Y-m-d H:i:s') && !\controllers\internals\Tool::validate_date($at, 'Y-m-d H:i'))
{
continue;
}
foreach ($numbers as $key => $number)
{
$number = \controllers\internals\Tool::parse_phone($number);
if (!$number)
{
unset($numbers[$key]);
continue;
}
$numbers[$key] = $number;
}
if (!$numbers && !$contacts && !$groups && !$conditional_groups)
{
continue;
}
if ($origin && !$this->internal_phone->get_by_number_and_user($id_user, $origin))
{
continue;
}
$success = $this->internal_scheduled->update_for_user($id_user, $id_scheduled, $at, $text, $origin, $flash, $numbers, $contacts, $groups, $conditional_groups);
//Check for media
/*
$current_media = $scheduled['current_media'] ?? false;
if (!$current_media)
{
$this->internal_media->delete_for_scheduled_and_user($id_user, $id_scheduled);
}
$media = $_FILES['media_' . $id_scheduled] ?? false;
if (!$media)
{
$nb_update += (int) $success;
continue;
}
$success = $this->internal_media->create($id_user, $id_scheduled, $media);
if (!$success)
{
continue;
}
*/
++$nb_update;
}
if ($nb_update !== \count($scheduleds))
{
\FlashMessage\FlashMessage::push('danger', 'Certains SMS n\'ont pas été mis à jour.');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
\FlashMessage\FlashMessage::push('success', 'Tous les SMS ont été mis à jour.');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
}

View file

@ -1,75 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des sendeds.
*/
class Sended extends \descartes\Controller
{
private $internal_sended;
private $internal_phone;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_sended = new \controllers\internals\Sended($bdd);
$this->internal_phone = new \controllers\internals\Phone($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les sendeds, sous forme d'un tableau permettant l'administration de ces sendeds.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$limit = 25;
$sendeds = $this->internal_sended->list_for_user($_SESSION['user']['id'], $limit, $page);
$this->render('sended/list', ['sendeds' => $sendeds, 'page' => $page, 'limit' => $limit, 'nb_results' => \count($sendeds)]);
}
/**
* Cette fonction va supprimer une liste de sendeds.
*
* @param array int $_GET['ids'] : Les id des sendedes à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Sended', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_sended->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Sended', 'list'));
}
}

View file

@ -1,79 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des settings.
*/
class Setting extends \descartes\Controller
{
private $internal_setting;
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_setting = new \controllers\internals\Setting($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Return all settings to administrate them.
*/
public function show()
{
return $this->render('setting/show');
}
/**
* Update a setting value identified by his name.
*
* @param string $setting_name : Name of the setting to modify
* @param $csrf : CSRF token
* @param string $_POST['setting_value'] : Setting's new value
*
* @return boolean;
*/
public function update(string $setting_name, string $csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Setting', 'show'));
}
$setting_value = $_POST['setting_value'] ?? false;
if (false === $setting_value)
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez renseigner une valeure pour le réglage.');
return $this->redirect(\descartes\Router::url('Setting', 'show'));
}
$update_setting_result = $this->internal_setting->update_for_user($_SESSION['user']['id'], $setting_name, $setting_value);
if (false === $update_setting_result)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de mettre à jour ce réglage.');
return $this->redirect(\descartes\Router::url('Setting', 'show'));
}
$settings = $this->internal_setting->gets_for_user($_SESSION['user']['id']);
$_SESSION['user']['settings'] = $settings;
\FlashMessage\FlashMessage::push('success', 'Le réglage a bien été mis à jour.');
return $this->redirect(\descartes\Router::url('Setting', 'show'));
}
}

View file

@ -1,80 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des smsstops.
*/
class SmsStop extends \descartes\Controller
{
private $internal_sms_stop;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_sms_stop = new \controllers\internals\SmsStop($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Cette fonction retourne tous les smsstops, sous forme d'un tableau permettant l'administration de ces smsstops.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$limit = 25;
$smsstops = $this->internal_sms_stop->list_for_user($_SESSION['user']['id'], $limit, $page);
$this->render('smsstop/list', ['page' => $page, 'smsstops' => $smsstops, 'limit' => $limit, 'nb_results' => \count($smsstops)]);
}
/**
* Cette fonction va supprimer une liste de smsstops.
*
* @param array int $_GET['ids'] : Les id des smsstopes à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('SmsStop', 'list'));
}
if (!\controllers\internals\Tool::is_admin())
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez être administrateur pour pouvoir supprimer un "STOP Sms" !');
return $this->redirect(\descartes\Router::url('SmsStop', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_sms_stop->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('SmsStop', 'list'));
}
}

View file

@ -1,86 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
class Templating extends \descartes\Controller
{
private $internal_contact;
private $internal_templating;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_templating = new \controllers\internals\Templating();
\controllers\internals\Tool::verifyconnect();
}
/**
* Try to render a template as a message for preview.
*
* @param string $_POST['template'] : Template string
* @param int $_POST['id_contact'] : Id of the contact to render the template for
*
* @return mixed : False or json string ['success' => bool, 'result' => message]
*/
public function render_preview()
{
$return = [
'success' => false,
'result' => 'Une erreur inconnue est survenue.',
];
$template = $_POST['template'] ?? false;
$id_contact = $_POST['id_contact'] ?? false;
if (!$template || !$id_contact)
{
$return['result'] = 'Veuillez remplir un message.';
echo json_encode($return);
return false;
}
$contact = $this->internal_contact->get_for_user($_SESSION['user']['id'], $id_contact);
if (!$contact)
{
$return['result'] = 'Ce contact n\'existe pas.';
echo json_encode($return);
return false;
}
$contact['datas'] = json_decode($contact['datas'], true);
$datas = [
'contact' => $contact,
];
$result = $this->internal_templating->render($template, $datas);
$return = $result;
if (!trim($result['result']))
{
$return['result'] = 'Message vide, il ne sera pas envoyé.';
}
echo json_encode($return);
return true;
}
}

View file

@ -1,148 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des users.
*/
class User extends \descartes\Controller
{
private $internal_user;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_user = new \controllers\internals\User($bdd);
\controllers\internals\Tool::verifyconnect();
if (!\controllers\internals\Tool::is_admin())
{
return $this->redirect(\descartes\Router::url('Dashboard', 'show'));
}
}
/**
* Cette fonction retourne tous les users, sous forme d'un tableau permettant l'administration de ces users.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$users = $this->internal_user->list(25, $page);
$this->render('user/list', ['users' => $users]);
}
/**
* Cette fonction va supprimer une liste de users.
*
* @param array int $_GET['ids'] : Les id des useres à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('User', 'list'));
}
if (!\controllers\internals\Tool::is_admin())
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez être administrateur pour supprimer un utilisateur !');
return $this->redirect(\descartes\Router::url('User', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_user->delete($id);
}
return $this->redirect(\descartes\Router::url('User', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'un user.
*/
public function add()
{
return $this->render('user/add');
}
/**
* 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
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$email = $_POST['email'] ?? false;
$password = $_POST['password'] ?? \controllers\internals\Tool::generate_password(rand(6, 12));
$admin = $_POST['admin'] ?? false;
if (!$email)
{
\FlashMessage\FlashMessage::push('danger', 'Vous devez au moins fournir une adresse e-mail pour l\'utilisateur.');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL))
{
\FlashMessage\FlashMessage::push('danger', 'L\'adresse e-mail n\'est pas valide.');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$user_id = $this->internal_user->create($email, $password, $admin);
if (!$user_id)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce user.');
return $this->redirect(\descartes\Router::url('User', 'add'));
}
$email_send = \controllers\internals\Tool::send_email($email, EMAIL_CREATE_USER, ['email' => $email, 'password' => $password]);
if (!$email_send)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible d\'envoyer l\'e-mail à l\'utilisateur.');
}
\FlashMessage\FlashMessage::push('success', 'L\'utilisateur a bien été créé.');
return $this->redirect(\descartes\Router::url('User', 'list'));
}
}

View file

@ -1,178 +0,0 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
/**
* Page des webhooks.
*/
class Webhook extends \descartes\Controller
{
private $internal_webhook;
private $internal_event;
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_webhook = new \controllers\internals\Webhook($bdd);
$this->internal_event = new \controllers\internals\Event($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* List all webhooks.
*
* @param mixed $page
*/
public function list($page = 0)
{
$page = (int) $page;
$webhooks = $this->internal_webhook->list_for_user($_SESSION['user']['id'], 25, $page);
$this->render('webhook/list', ['webhooks' => $webhooks]);
}
/**
* Delete a list of webhooks.
*
* @param array int $_GET['ids'] : Les id des webhooks à supprimer
* @param mixed $csrf
*
* @return boolean;
*/
public function delete($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
$this->redirect(\descartes\Router::url('Webhook', 'list'));
return false;
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_webhook->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Webhook', 'list'));
}
/**
* Cette fonction retourne la page d'ajout d'une webhook.
*/
public function add()
{
$this->render('webhook/add');
}
/**
* Edit a list of webhooks.
*
* @param array int $_GET['ids'] : ids of webhooks to edit
*/
public function edit()
{
$ids = $_GET['ids'] ?? [];
$webhooks = $this->internal_webhook->gets_in_for_user($_SESSION['user']['id'], $ids);
$this->render('webhook/edit', [
'webhooks' => $webhooks,
]);
}
/**
* Insert a new webhook.
*
* @param $csrf : Le jeton CSRF
* @param string $_POST['url'] : URL to call on webhook release
* @param string $_POST['type'] : Type of webhook, either 'send_sms' or 'receive_sms'
*
* @return boolean;
*/
public function create($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Webhook', 'list'));
}
$url = $_POST['url'] ?? false;
$type = $_POST['type'] ?? false;
if (!$url || !$type)
{
\FlashMessage\FlashMessage::push('danger', 'Renseignez au moins une URL et un type de webhook.');
return $this->redirect(\descartes\Router::url('Webhook', 'list'));
}
if (!$this->internal_webhook->create($_SESSION['user']['id'], $url, $type))
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce webhook.');
return $this->redirect(\descartes\Router::url('webhooks', 'add'));
}
\FlashMessage\FlashMessage::push('success', 'La webhook a bien été créé.');
return $this->redirect(\descartes\Router::url('Webhook', 'list'));
}
/**
* Cette fonction met à jour une webhook.
*
* @param $csrf : Le jeton CSRF
* @param array $_POST['webhooks'] : Un tableau des webhooks avec leur nouvelle valeurs
*
* @return boolean;
*/
public function update($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Webhook', 'list'));
}
$nb_update = 0;
foreach ($_POST['webhooks'] as $webhook)
{
$url = $webhook['url'] ?? false;
$type = $webhook['type'] ?? false;
if (!$url || !$type)
{
continue;
}
$success = $this->internal_webhook->update_for_user($_SESSION['user']['id'], $webhook['id'], $url, $type);
$nb_update += (int) $success;
}
if ($nb_update !== \count($_POST['webhooks']))
{
\FlashMessage\FlashMessage::push('info', 'Certains webhooks n\'ont pas pu êtres mis à jour.');
return $this->redirect(\descartes\Router::url('Webhook', 'list'));
}
\FlashMessage\FlashMessage::push('success', 'Tous les webhooks ont été modifiés avec succès.');
return $this->redirect(\descartes\Router::url('Webhook', 'list'));
}
}