Use id_phone instead of number in scheduled, use ftok to generate queue id, improve adapter interface, add popup error

This commit is contained in:
osaajani 2020-03-04 01:40:47 +01:00
parent 66fa2ef434
commit 6f8c7d62b9
25 changed files with 195 additions and 180 deletions

3
.gitignore vendored
View File

@ -7,4 +7,7 @@ composer.lock
env.* env.*
phinx.* phinx.*
datas/test_write_sms.json
datas/test_read_sms.json
!*.dist !*.dist

View File

@ -45,11 +45,6 @@ namespace adapters;
*/ */
public static function meta_description(): string; public static function meta_description(): string;
/**
* Description of the datas expected by the adapter to help the user. (e.g : A list of expecteds Api credentials fields, with name and value).
*/
public static function meta_datas_help(): string;
/** /**
* List of entries we want in datas for the adapter. * List of entries we want in datas for the adapter.
* *

View File

@ -68,14 +68,6 @@ namespace adapters;
return 'Utilisation du logiciel Gammu qui doit être installé sur le serveur et configuré. Voir https://wammu.eu.'; return 'Utilisation du logiciel Gammu qui doit être installé sur le serveur et configuré. Voir https://wammu.eu.';
} }
/**
* Description of the datas expected by the adapter to help the user. (e.g : A list of expecteds Api credentials fields, with name and value).
*/
public static function meta_datas_help(): string
{
return 'Fichier de configuration à fournir à Gammu pour utiliser ce modem.';
}
/** /**
* List of entries we want in datas for the adapter. * List of entries we want in datas for the adapter.
* *

View File

@ -57,7 +57,7 @@ namespace adapters;
$this->api = new Api( $this->api = new Api(
$this->datas['app_key'], $this->datas['app_key'],
$this->datas['app_secret'], $this->datas['app_secret'],
$this->datas['endpoint'], 'ovh-eu',
$this->datas['consumer_key'] $this->datas['consumer_key']
); );
} }
@ -85,15 +85,7 @@ namespace adapters;
*/ */
public static function meta_description(): string public static function meta_description(): string
{ {
return 'Solution de SMS proposé par le groupe OVH, https://www.ovhtelecom.fr/sms/.'; return 'Solution de SMS proposé par le groupe <a target="_blank" href="https://www.ovhtelecom.fr/sms/">OVH</a>. Pour générer les clefs API OVH, <a target="_blank" href="https://api.ovh.com/createToken/index.cgi">cliquez ici.</a>';
}
/**
* Description of the datas expected by the adapter to help the user. (e.g : A list of expecteds Api credentials fields, with name and value).
*/
public static function meta_datas_help(): string
{
return 'Clefs API OVH, https://api.ovh.com/createToken/index.cgi.';
} }
/** /**
@ -122,12 +114,6 @@ namespace adapters;
'description' => 'Paramètre "Consumer Key" obtenu lors de la génération de la clef API OVH.', 'description' => 'Paramètre "Consumer Key" obtenu lors de la génération de la clef API OVH.',
'required' => true, 'required' => true,
], ],
[
'name' => 'endpoint',
'title' => 'Endpoint',
'description' => 'Endpoint de l\'API OVH, voir https://github.com/ovh/php-ovh/#supported-apis.',
'required' => true,
],
[ [
'name' => 'service_name', 'name' => 'service_name',
'title' => 'Service Name', 'title' => 'Service Name',

View File

@ -78,14 +78,6 @@ namespace adapters;
return 'A test adaptater that do not actually send or receive any message.'; return 'A test adaptater that do not actually send or receive any message.';
} }
/**
* Description of the datas expected by the adapter to help the user. (e.g : A list of expecteds Api credentials fields, with name and value).
*/
public static function meta_datas_help(): string
{
return 'No datas.';
}
/** /**
* List of entries we want in datas for the adapter. * List of entries we want in datas for the adapter.
* *

View File

@ -55,6 +55,8 @@
.popup-alert .popup-alert
{ {
margin-top: 25px;
margin-left: 25%;
width: 50%; width: 50%;
position: relative; position: relative;
} }
@ -326,3 +328,15 @@ footer
{ {
color: #c9302c; color: #c9302c;
} }
/* PHONE */
#adapter-datas-container
{
margin-top: 35px;
}
#adapter-data-fields-container
{
margin-top: 20px;
}

View File

@ -5,7 +5,7 @@
/** /**
* Cette fonction affiche un message de succès ou d'erreur dans une popup * Cette fonction affiche un message de succès ou d'erreur dans une popup
*/ */
function showMessage(message, type) function showMessage(message, type, random_id = null)
{ {
if (type == 1) //Si message de succès if (type == 1) //Si message de succès
{ {
@ -16,20 +16,29 @@ function showMessage(message, type)
var type = 'alert-danger'; var type = 'alert-danger';
} }
var alerthtml = '<div class="col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3 popup-alert alert ' + type + '"><button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>' + message + '</div>'; var alerthtml = '<div id="' + (random_id ? 'popup-' + random_id : '') + '" class="col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3 popup-alert alert ' + type + '"><button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>' + message + '</div>';
jQuery('body .popup-alerts-container').prepend(alerthtml); jQuery('body .popup-alerts-container').prepend(alerthtml);
} }
/**
* Hide a popup
*/
function fadeAlert(popup_id)
{
jQuery('#popup-' + popup_id).fadeOut('slow');
}
/** /**
* Cette fonction vérifie si un message a été reçu * Cette fonction vérifie si un message a été reçu
*/ */
function verifReceived() function verifReceived()
{ {
jQuery('.popup-alert').fadeOut('slow');
jQuery.getJSON(HTTP_PWD + "/received/popup", function( data ) { jQuery.getJSON(HTTP_PWD + "/received/popup", function( data ) {
$.each(data, function(key, val) { $.each(data, function(key, val) {
showMessage('SMS reçu du ' + val.origin + ' : ' + val.text, 1); var rand_id = Math.random().toString(36).substring(2);
showMessage('SMS reçu du ' + val.origin + ' : ' + val.text, 1, rand_id);
playReceptionSound(); playReceptionSound();
setTimeout(function() { fadeAlert(rand_id); }, 10000);
}); });
}); });
} }

View File

@ -59,16 +59,15 @@ namespace controllers\internals;
new \daemons\Phone($phone); new \daemons\Phone($phone);
} }
/** /**
* Create a user or update an existing user * Create a user or update an existing user.
*
* @param $email : User email * @param $email : User email
* @param $password : User password * @param $password : User password
* @param $admin : Is user admin * @param $admin : Is user admin
* @param $api_key : User API key, if null random api key is generated * @param $api_key : User API key, if null random api key is generated
* @return void : exit status 1 on error, else 0
*/ */
public function create_update_user (string $email, string $password, bool $admin, ?string $api_key = null) public function create_update_user(string $email, string $password, bool $admin, ?string $api_key = null)
{ {
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, 'UTF8'); $bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, 'UTF8');
$internal_user = new \controllers\internals\User($bdd); $internal_user = new \controllers\internals\User($bdd);
@ -78,11 +77,10 @@ namespace controllers\internals;
{ {
$api_key = $api_key ?? $internal_user->generate_random_api_key(); $api_key = $api_key ?? $internal_user->generate_random_api_key();
$success = $internal_user->update($user['id'], $email, $password, $admin, $api_key); $success = $internal_user->update($user['id'], $email, $password, $admin, $api_key);
exit($success ? 0 : 1); exit($success ? 0 : 1);
} }
$success = $internal_user->create($email, $password, $admin, $api_key); $success = $internal_user->create($email, $password, $admin, $api_key);
exit($success ? 0 : 1); exit($success ? 0 : 1);
} }

View File

@ -18,12 +18,11 @@ namespace controllers\internals;
class HttpError extends \descartes\InternalController class HttpError extends \descartes\InternalController
{ {
/** /**
* Return 404 error page * Return 404 error page.
*/ */
public function _404 () public function _404()
{ {
http_response_code(404); http_response_code(404);
$this->render('error/404'); $this->render('error/404');
} }
} }

View File

@ -20,30 +20,30 @@ namespace controllers\internals;
* *
* @param int $id_user : User to insert scheduled for * @param int $id_user : User to insert scheduled for
* @param $at : Scheduled date to send * @param $at : Scheduled date to send
* @param string $text : Text of the message * @param string $text : Text of the message
* @param ?string $origin : Origin number of the message, null by default * @param ?int $id_phone : Id of the phone to send message with, null by default
* @param bool $flash : Is the sms a flash sms, by default false * @param bool $flash : Is the sms a flash sms, by default false
* @param array $numbers : Numbers to send message to * @param array $numbers : Numbers to send message to
* @param array $contacts_ids : Contact ids 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 $groups_ids : Group ids to send message to
* @param array $conditional_group_ids : Conditional Groups 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 * @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 = []) public function create(int $id_user, $at, string $text, ?int $id_phone = null, bool $flash = false, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [])
{ {
$scheduled = [ $scheduled = [
'id_user' => $id_user, 'id_user' => $id_user,
'at' => $at, 'at' => $at,
'text' => $text, 'text' => $text,
'origin' => $origin, 'id_phone' => $id_phone,
'flash' => $flash, 'flash' => $flash,
]; ];
if ($origin) if ($id_phone !== null)
{ {
$internal_phone = new Phone($this->bdd); $internal_phone = new Phone($this->bdd);
$find_phone = $internal_phone->get_by_number_and_user($id_user, $origin); $find_phone = $internal_phone->get_for_user($id_user, $id_phone);
if (!$find_phone) if (!$find_phone)
{ {
@ -54,10 +54,6 @@ namespace controllers\internals;
$id_scheduled = $this->get_model()->insert($scheduled); $id_scheduled = $this->get_model()->insert($scheduled);
if (!$id_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; return false;
} }
@ -102,6 +98,10 @@ namespace controllers\internals;
$this->get_model()->insert_scheduled_conditional_group_relation($id_scheduled, $conditional_group_id); $this->get_model()->insert_scheduled_conditional_group_relation($id_scheduled, $conditional_group_id);
} }
$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 $id_scheduled; return $id_scheduled;
} }
@ -111,30 +111,30 @@ namespace controllers\internals;
* @param int $id_user : User to insert scheduled for * @param int $id_user : User to insert scheduled for
* @param int $id_scheduled : Scheduled id * @param int $id_scheduled : Scheduled id
* @param $at : Scheduled date to send * @param $at : Scheduled date to send
* @param string $text : Text of the message * @param string $text : Text of the message
* @param ?string $origin : Origin number of the message, null by default * @param ?int $id_phone : Id of the phone to send message with, null by default
* @param bool $flash : Is the sms a flash sms, by default false * @param bool $flash : Is the sms a flash sms, by default false
* @param array $numbers : Numbers to send message to * @param array $numbers : Numbers to send message to
* @param array $contacts_ids : Contact ids 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 $groups_ids : Group ids to send message to
* @param array $conditional_group_ids : Conditional Groups 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 * @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 = []) public function update_for_user(int $id_user, int $id_scheduled, $at, string $text, ?string $id_phone = null, bool $flash = false, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [])
{ {
$scheduled = [ $scheduled = [
'id_user' => $id_user, 'id_user' => $id_user,
'at' => $at, 'at' => $at,
'text' => $text, 'text' => $text,
'origin' => $origin, 'id_phone' => $id_phone,
'flash' => $flash, 'flash' => $flash,
]; ];
if ($origin) if ($id_phone !== null)
{ {
$internal_phone = new Phone($this->bdd); $internal_phone = new Phone($this->bdd);
$find_phone = $internal_phone->get_by_number_and_user($id_user, $origin); $find_phone = $internal_phone->get_for_user($id_user, $id_phone);
if (!$find_phone) if (!$find_phone)
{ {
@ -210,7 +210,7 @@ namespace controllers\internals;
/** /**
* Get all messages to send and the number to use to send theme. * Get all messages to send and the number to use to send theme.
* *
* @return array : [['id_scheduled', 'text', 'origin', 'destination', 'flash'], ...] * @return array : [['id_scheduled', 'text', 'id_phone', 'destination', 'flash'], ...]
*/ */
public function get_smss_to_send() public function get_smss_to_send()
{ {
@ -247,6 +247,23 @@ namespace controllers\internals;
$users_phones[$scheduled['id_user']] = $phones ? $phones : []; $users_phones[$scheduled['id_user']] = $phones ? $phones : [];
} }
$phone_to_use = null;
foreach ($users_phones[$scheduled['id_user']] as $phone)
{
if ($phone['id'] !== $scheduled['id_phone'])
{
continue;
}
$phone_to_use = $phone;
}
if (null === $phone_to_use)
{
$rnd_key = array_rand($users_phones[$scheduled['id_user']]);
$phone_to_use = $users_phones[$scheduled['id_user']][$rnd_key];
}
$messages = []; $messages = [];
//Add messages for numbers //Add messages for numbers
@ -256,18 +273,11 @@ namespace controllers\internals;
$message = [ $message = [
'id_user' => $scheduled['id_user'], 'id_user' => $scheduled['id_user'],
'id_scheduled' => $scheduled['id'], 'id_scheduled' => $scheduled['id'],
'origin' => $scheduled['origin'], 'id_phone' => $phone_to_use['id'],
'destination' => $number['number'], 'destination' => $number['number'],
'flash' => $scheduled['flash'], '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)) if ((int) ($users_settings[$scheduled['id_user']]['templating'] ?? false))
{ {
$render = $internal_templating->render($scheduled['text']); $render = $internal_templating->render($scheduled['text']);
@ -317,18 +327,11 @@ namespace controllers\internals;
$message = [ $message = [
'id_user' => $scheduled['id_user'], 'id_user' => $scheduled['id_user'],
'id_scheduled' => $scheduled['id'], 'id_scheduled' => $scheduled['id'],
'origin' => $scheduled['origin'], 'id_phone' => $phone_to_use['id'],
'destination' => $number['number'], 'destination' => $number['number'],
'flash' => $scheduled['flash'], '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)) if ((int) ($users_settings[$scheduled['id_user']]['templating'] ?? false))
{ {
$contact['datas'] = json_decode($contact['datas'], true); $contact['datas'] = json_decode($contact['datas'], true);

View File

@ -160,7 +160,7 @@ namespace controllers\publics;
* *
* @param string $_POST['at'] : Date to send message at format Y-m-d H:i:s * @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['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['id_phone'] : Default null. Id of phone 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['flash'] : Default false. Is the sms a flash sms.
* @param string $_POST['numbers'] : Array of numbers to send message to * @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['contacts'] : Array of ids of contacts to send message to
@ -173,7 +173,7 @@ namespace controllers\publics;
{ {
$at = $_POST['at'] ?? false; $at = $_POST['at'] ?? false;
$text = $_POST['text'] ?? false; $text = $_POST['text'] ?? false;
$origin = empty($_POST['origin']) ? null : $_POST['origin']; $id_phone = empty($_POST['id_phone']) ? null : $_POST['id_phone'];
$flash = (bool) ($_POST['flash'] ?? false); $flash = (bool) ($_POST['flash'] ?? false);
$numbers = $_POST['numbers'] ?? []; $numbers = $_POST['numbers'] ?? [];
$contacts = $_POST['contacts'] ?? []; $contacts = $_POST['contacts'] ?? [];
@ -227,18 +227,18 @@ namespace controllers\publics;
return false; return false;
} }
if ($origin && !$this->internal_phone->get_by_number_and_user($this->user['id'], $origin)) if ($id_phone && !$this->internal_phone->get_for_user($this->user['id'], $id_phone))
{ {
$return = self::DEFAULT_RETURN; $return = self::DEFAULT_RETURN;
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER']; $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.'; $return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'id_phone : You must specify an id_phone number among thoses of user phones.';
$this->auto_http_code(false); $this->auto_http_code(false);
$this->json($return); $this->json($return);
return false; return false;
} }
$scheduled_id = $this->internal_scheduled->create($this->user['id'], $at, $text, $origin, $flash, $numbers, $contacts, $groups, $conditional_groups); $scheduled_id = $this->internal_scheduled->create($this->user['id'], $at, $text, $id_phone, $flash, $numbers, $contacts, $groups, $conditional_groups);
if (!$scheduled_id) if (!$scheduled_id)
{ {
$return = self::DEFAULT_RETURN; $return = self::DEFAULT_RETURN;

View File

@ -16,6 +16,7 @@ namespace controllers\publics;
*/ */
class Callback extends \descartes\Controller class Callback extends \descartes\Controller
{ {
private $user;
private $internal_user; private $internal_user;
private $internal_sended; private $internal_sended;
private $internal_adapter; private $internal_adapter;
@ -27,21 +28,33 @@ namespace controllers\publics;
$this->internal_user = new \controllers\internals\User($bdd); $this->internal_user = new \controllers\internals\User($bdd);
$this->internal_sended = new \controllers\internals\Sended($bdd); $this->internal_sended = new \controllers\internals\Sended($bdd);
$this->internal_adapter = new \controllers\internals\Adapter(); $this->internal_adapter = new \controllers\internals\Adapter();
//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)
{
http_response_code(401);
echo json_encode(['error' => 'Invalid API key. You must provide a valid GET or POST api_key param.']);
exit(1);
}
} }
/** /**
* Function call on a sended sms status change notification reception. * Function call on a sended sms status change notification reception.
* We return nothing, and we let the adapter do his things
* *
* @param string $adapter_name : Name of the adapter to use * @param string $adapter_name : Name of the adapter to use
* * @return bool : true on success, false on error
* @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) 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 //Search for an adapter
$find_adapter = false; $find_adapter = false;
$adapters = $this->internal_adapter->list_adapters(); $adapters = $this->internal_adapter->list_adapters();
@ -60,16 +73,12 @@ namespace controllers\publics;
//Instanciate adapter, check if status change is supported and if so call status change callback //Instanciate adapter, check if status change is supported and if so call status change callback
$adapter_classname = $find_adapter['meta_classname']; $adapter_classname = $find_adapter['meta_classname'];
if (!$find_adapter['meta_support_status_change']) if (!$find_adapter['meta_support_status_change'])
{ {
return false; return false;
} }
$callback_return = $adapter_classname::status_change_callback(); $callback_return = $adapter_classname::status_change_callback();
var_dump($callback_return);
if (!$callback_return) if (!$callback_return)
{ {
return false; return false;
@ -83,6 +92,6 @@ namespace controllers\publics;
$this->internal_sended->update_status($sended['id'], $callback_return['status']); $this->internal_sended->update_status($sended['id'], $callback_return['status']);
return false; return true;
} }
} }

View File

@ -132,7 +132,7 @@ class Phone extends \descartes\Controller
\FlashMessage\FlashMessage::push('danger', 'Numéro de téléphone incorrect.'); \FlashMessage\FlashMessage::push('danger', 'Numéro de téléphone incorrect.');
return $this->redirect(\descartes\Router::url('Phone', 'add')); return $this->redirect(\descartes\Router::url('Phone', 'add'));
} }
$number_exist = $this->internal_phone->get_by_number($number); $number_exist = $this->internal_phone->get_by_number($number);
if ($number_exist) if ($number_exist)
@ -185,7 +185,7 @@ class Phone extends \descartes\Controller
$adapter_classname = $find_adapter['meta_classname']; $adapter_classname = $find_adapter['meta_classname'];
$adapter_instance = new $adapter_classname($number, $adapter_datas); $adapter_instance = new $adapter_classname($number, $adapter_datas);
$adapter_working = $adapter_instance->test(); $adapter_working = $adapter_instance->test();
if (!$adapter_working) 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.'); \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.');

View File

@ -214,15 +214,19 @@ namespace controllers\publics;
} }
/** /**
* Cette fonction insert un nouveau scheduled. * Create a new scheduled message
* (you must provide at least one entry in any of numbers, contacts, groups or conditional_groups).
* *
* @param $csrf : Le jeton CSRF * @param $csrf : Le jeton CSRF
* @param string $_POST['name'] : Le nom du scheduled * @param string $_POST['at'] : Date to send message for
* @param string $_POST['date'] : La date d'envoie du scheduled * @param string $_POST['text'] : Text of the message
* @param string $_POST['numbers'] : Les numeros de téléphone du scheduled * @param ?bool $_POST['flash'] : Is the message a flash message (by default false)
* @param string $_POST['contacts'] : Les contacts du scheduled * @param ?int $_POST['id_phone'] : Id of the phone to send message from, if null use random phone
* @param string $_POST['groups'] : Les groups du scheduled * @param ?array $_POST['numbers'] : Numbers to send the message to
* @param array $_FILES['media'] : The media to link to a scheduled * @param ?array $_POST['contacts'] : Numbers to send the message to
* @param ?array $_POST['groups'] : Numbers to send the message to
* @param ?array $_POST['conditional_groups'] : Numbers to send the message to
* @param ?array $_FILES['media'] : The media to link to a scheduled
*/ */
public function create($csrf) public function create($csrf)
{ {
@ -237,11 +241,12 @@ namespace controllers\publics;
$at = $_POST['at'] ?? false; $at = $_POST['at'] ?? false;
$text = $_POST['text'] ?? false; $text = $_POST['text'] ?? false;
$flash = (bool) ($_POST['flash'] ?? false); $flash = (bool) ($_POST['flash'] ?? false);
$origin = empty($_POST['origin']) ? null : $_POST['origin']; $id_phone = empty($_POST['id_phone']) ? null : $_POST['id_phone'];
$numbers = $_POST['numbers'] ?? []; $numbers = $_POST['numbers'] ?? [];
$contacts = $_POST['contacts'] ?? []; $contacts = $_POST['contacts'] ?? [];
$groups = $_POST['groups'] ?? []; $groups = $_POST['groups'] ?? [];
$conditional_groups = $_POST['conditional_groups'] ?? []; $conditional_groups = $_POST['conditional_groups'] ?? [];
$media = $_FILES['media'] ?? false;
if (empty($text)) if (empty($text))
{ {
@ -278,14 +283,7 @@ namespace controllers\publics;
return $this->redirect(\descartes\Router::url('Scheduled', 'add')); return $this->redirect(\descartes\Router::url('Scheduled', 'add'));
} }
if ($origin && !$this->internal_phone->get_by_number_and_user($id_user, $origin)) $scheduled_id = $this->internal_scheduled->create($id_user, $at, $text, $id_phone, $flash, $numbers, $contacts, $groups, $conditional_groups);
{
\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) if (!$scheduled_id)
{ {
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer le Sms.'); \FlashMessage\FlashMessage::push('danger', 'Impossible de créer le Sms.');
@ -294,7 +292,6 @@ namespace controllers\publics;
} }
//If mms is enabled, try to process a media to link to the scheduled //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) if (!($_SESSION['user']['settings']['mms'] ?? false) || !$media)
{ {
\FlashMessage\FlashMessage::push('success', 'Le Sms a bien été créé pour le ' . $at . '.'); \FlashMessage\FlashMessage::push('success', 'Le Sms a bien été créé pour le ' . $at . '.');
@ -340,7 +337,7 @@ namespace controllers\publics;
$id_user = $_SESSION['user']['id']; $id_user = $_SESSION['user']['id'];
$at = $scheduled['at'] ?? false; $at = $scheduled['at'] ?? false;
$text = $scheduled['text'] ?? false; $text = $scheduled['text'] ?? false;
$origin = empty($scheduled['origin']) ? null : $scheduled['origin']; $id_phone = empty($scheduled['id_phone']) ? null : $scheduled['id_phone'];
$flash = (bool) ($scheduled['flash'] ?? false); $flash = (bool) ($scheduled['flash'] ?? false);
$numbers = $scheduled['numbers'] ?? []; $numbers = $scheduled['numbers'] ?? [];
$contacts = $scheduled['contacts'] ?? []; $contacts = $scheduled['contacts'] ?? [];
@ -381,12 +378,7 @@ namespace controllers\publics;
continue; continue;
} }
if ($origin && !$this->internal_phone->get_by_number_and_user($id_user, $origin)) $success = $this->internal_scheduled->update_for_user($id_user, $id_scheduled, $at, $text, $id_phone, $flash, $numbers, $contacts, $groups, $conditional_groups);
{
continue;
}
$success = $this->internal_scheduled->update_for_user($id_user, $id_scheduled, $at, $text, $origin, $flash, $numbers, $contacts, $groups, $conditional_groups);
//Check for media //Check for media
/* /*
@ -410,7 +402,7 @@ namespace controllers\publics;
} }
*/ */
++$nb_update; $nb_update++;
} }
if ($nb_update !== \count($scheduleds)) if ($nb_update !== \count($scheduleds))

View File

@ -101,7 +101,7 @@ class Launcher extends AbstractDaemon
{ {
foreach ($phones as $phone) foreach ($phones as $phone)
{ {
$phone_name = 'RaspiSMS Daemon Phone ' . $phone['number']; $phone_name = 'RaspiSMS Daemon Phone ' . $phone['id'];
$pid_file = PWD_PID . '/' . $phone_name . '.pid'; $pid_file = PWD_PID . '/' . $phone_name . '.pid';
if (file_exists($pid_file)) if (file_exists($pid_file))

View File

@ -35,9 +35,9 @@ class Phone extends AbstractDaemon
public function __construct(array $phone) public function __construct(array $phone)
{ {
$this->phone = $phone; $this->phone = $phone;
$this->msg_queue_id = (int) mb_substr($this->phone['number'], 1); $this->msg_queue_id = (int) (QUEUE_ID_PHONE_PREFIX . $this->phone['id']);
$name = 'RaspiSMS Daemon Phone ' . $this->phone['number']; $name = 'RaspiSMS Daemon Phone ' . $this->phone['id'];
$logger = new Logger($name); $logger = new Logger($name);
$logger->pushHandler(new StreamHandler(PWD_LOGS . '/raspisms.log', Logger::DEBUG)); $logger->pushHandler(new StreamHandler(PWD_LOGS . '/raspisms.log', Logger::DEBUG));
$pid_dir = PWD_PID; $pid_dir = PWD_PID;
@ -140,6 +140,8 @@ class Phone extends AbstractDaemon
$message['at'] = $at; $message['at'] = $at;
$message['origin'] = $this->phone['number'];
$this->logger->info('Try send message : ' . json_encode($message)); $this->logger->info('Try send message : ' . json_encode($message));
$sended_sms_uid = $this->adapter->send($message['destination'], $message['text'], $message['flash']); $sended_sms_uid = $this->adapter->send($message['destination'], $message['text'], $message['flash']);
@ -163,7 +165,7 @@ class Phone extends AbstractDaemon
} }
/** /**
* Read smss for a number. * Read smss for a phone.
*/ */
private function read_smss() private function read_smss()
{ {

View File

@ -48,7 +48,7 @@ class Sender extends AbstractDaemon
//Get smss and transmit order to send to appropriate phone daemon //Get smss and transmit order to send to appropriate phone daemon
$smss = $this->internal_scheduled->get_smss_to_send(); $smss = $this->internal_scheduled->get_smss_to_send();
$this->transmit_smss($smss); //Add new queues to array of queues $this->transmit_smss($smss); //Add new queue to array of queues
usleep(0.5 * 1000000); usleep(0.5 * 1000000);
} }
@ -63,7 +63,7 @@ class Sender extends AbstractDaemon
foreach ($smss as $sms) foreach ($smss as $sms)
{ {
//If queue not already exists //If queue not already exists
$queue_id = (int) mb_substr($sms['origin'], 1); $queue_id = (int) (QUEUE_ID_PHONE_PREFIX . $sms['id_phone']);
if (!msg_queue_exists($queue_id) || !isset($queues[$queue_id])) if (!msg_queue_exists($queue_id) || !isset($queues[$queue_id]))
{ {
$this->queues[$queue_id] = msg_get_queue($queue_id); $this->queues[$queue_id] = msg_get_queue($queue_id);
@ -73,7 +73,7 @@ class Sender extends AbstractDaemon
'id_user' => $sms['id_user'], 'id_user' => $sms['id_user'],
'id_scheduled' => $sms['id_scheduled'], 'id_scheduled' => $sms['id_scheduled'],
'text' => $sms['text'], 'text' => $sms['text'],
'origin' => $sms['origin'], 'id_phone' => $sms['id_phone'],
'destination' => $sms['destination'], 'destination' => $sms['destination'],
'flash' => $sms['flash'], 'flash' => $sms['flash'],
]; ];

View File

@ -0,0 +1,18 @@
<?php
use Phinx\Migration\AbstractMigration;
class AddIdPhoneScheduled extends AbstractMigration
{
/**
* Add column id_phone in scheduled and remove origin
*/
public function change()
{
$table = $this->table('scheduled');
$table->removeColumn('origin')
->addColumn('id_phone', 'integer', ['null' => True])
->addForeignKey('id_phone', 'phone', 'id', ['delete'=> 'SET_NULL', 'update'=> 'CASCADE'])
->save();
}
}

View File

@ -38,11 +38,12 @@
], ],
//Phone messages types //Phone messages types
'QUEUE_ID_PHONE_PREFIX' => ftok(__FILE__, 'p'),
'QUEUE_TYPE_SEND_MSG' => 1, 'QUEUE_TYPE_SEND_MSG' => 1,
'QUEUE_TYPE_RECEIVE_MSG' => 2, 'QUEUE_TYPE_RECEIVE_MSG' => 2,
//Queues ids //Queues ids
'QUEUE_ID_WEBHOOK' => 8265838073837783, 'QUEUE_ID_WEBHOOK' => ftok(__FILE__, 'w'),
'QUEUE_TYPE_WEBHOOK' => 3, 'QUEUE_TYPE_WEBHOOK' => 3,
//User default settings //User default settings

6
templates/incs/alert.php Normal file
View File

@ -0,0 +1,6 @@
<div class="popup-alert alert alert-<?php $this->s($type); ?> alert-dismissible show" role="alert">
<?php $this->s($text); ?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>

View File

@ -11,17 +11,15 @@
</audio> </audio>
<?php } ?> <?php } ?>
<?php if (ENV == 'dev') { ?>
<script>
<?php while ($message = \FlashMessage\FlashMessage::next()) { ?>
alert('<?php $this->s($message['type'] . ' : ' . $message['text']); ?>');
<?php } ?>
</script>
<?php } ?>
<?php if (! ($_SESSION['user']['settings']['display_help'] ?? false)) { ?> <?php if (! ($_SESSION['user']['settings']['display_help'] ?? false)) { ?>
<style>.help {display: none;}</style> <style>.help {display: none;}</style>
<?php } ?> <?php } ?>
<div class="popup-alerts-container">
<?php while ($message = \FlashMessage\FlashMessage::next()) { ?>
<?php $this->render('incs/alert', $message); ?>
<?php } ?>
</div>
</body> </body>
</html> </html>

View File

@ -48,20 +48,5 @@
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]--> <![endif]-->
<script>
jQuery(document).ready(function ()
{
<?php if (!empty($_SESSION['errormessage'])) { ?>
showMessage('<?php $this->s($_SESSION['errormessage'], false, true); ?>', 0);
<?php unset($_SESSION['errormessage']); ?>
<?php } ?>
<?php if (!empty($_SESSION['successmessage'])) { ?>
showMessage('<?php $this->s($_SESSION['successmessage'], false, true); ?>', 1);
<?php unset($_SESSION['successmessage']); ?>
<?php } ?>
});
</script>
</head> </head>
<body> <body>
<div class="popup-alerts-container"></div>

View File

@ -44,12 +44,12 @@
Le numéro de téléphone qui enverra et recevra les messages. Le numéro de téléphone qui enverra et recevra les messages.
</p> </p>
<div class="form-group"> <div class="form-group">
<input name="" class="form-control" type="tel" id="phone-international-input" placeholder="Numéro de téléphone à utiliser."> <input required="required" name="" class="form-control" type="tel" id="phone-international-input" placeholder="Numéro de téléphone à utiliser.">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Adaptateur logiciel du téléphone : </label> <label>Adaptateur logiciel du téléphone : </label>
<p class="italic small help" id="description-adapter"> <p class="italic small help" id="description-adapter-general">
L'adaptateur logiciel utilisé par RaspiSMS pour communiquer avec le téléphone. Pour plus d'information, consultez <a href="https://raspisms.raspberry-pi.fr/documentation" target="_blank">la documentation de RaspiSMS</a> concernant les adaptateurs logiciels. L'adaptateur logiciel utilisé par RaspiSMS pour communiquer avec le téléphone. Pour plus d'information, consultez <a href="https://raspisms.raspberry-pi.fr/documentation" target="_blank">la documentation de RaspiSMS</a> concernant les adaptateurs logiciels.
</p> </p>
<select name="adapter" class="form-control" id="adapter-select"> <select name="adapter" class="form-control" id="adapter-select">
@ -58,7 +58,6 @@
value="<?= $adapter['meta_classname'] ?>" value="<?= $adapter['meta_classname'] ?>"
title="<?php $this->s($adapter['meta_description']); ?>" title="<?php $this->s($adapter['meta_description']); ?>"
data-description="<?php $this->s($adapter['meta_description']); ?>" data-description="<?php $this->s($adapter['meta_description']); ?>"
data-datas-help="<?php $this->s($adapter['meta_datas_help']); ?>"
data-datas-fields="<?php $this->s(json_encode($adapter['meta_datas_fields'])); ?>" data-datas-fields="<?php $this->s(json_encode($adapter['meta_datas_fields'])); ?>"
> >
<?php $this->s($adapter['meta_name']); ?> <?php $this->s($adapter['meta_name']); ?>
@ -66,7 +65,16 @@
<?php } ?> <?php } ?>
</select> </select>
</div> </div>
<div id="adapter-datas-fields-container"> <div id="adapter-datas-container" class="form-group">
<div id="adapter-datas-description-container">
<h4>Description de l'adaptateur</h4>
<div id="adapter-datas-description"></div>
</div>
<div id="adapter-data-fields-container">
<h4>Réglages de l'adaptateur</h4>
<div id="adapter-datas-fields"></div>
</div>
</div> </div>
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Annuler</a> <a class="btn btn-danger" href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Annuler</a>
<input type="submit" class="btn btn-success" value="Enregistrer le phone" /> <input type="submit" class="btn btn-success" value="Enregistrer le phone" />
@ -83,7 +91,7 @@
function change_adapter () function change_adapter ()
{ {
var option = jQuery('#adapter-select').find('option:selected'); var option = jQuery('#adapter-select').find('option:selected');
jQuery('#description-adapter').text(option.attr('data-description')); jQuery('#adapter-datas-description').html(option.attr('data-description'));
jQuery('#description-adapter-datas').text(option.attr('data-datas-help')); jQuery('#description-adapter-datas').text(option.attr('data-datas-help'));
var datas_fields = option.attr('data-datas-fields'); var datas_fields = option.attr('data-datas-fields');
@ -102,7 +110,12 @@
'</div>'; '</div>';
}); });
jQuery('#adapter-datas-fields-container').html(html); if (html == '')
{
html = 'Pas de réglages.';
}
jQuery('#adapter-datas-fields').html(html);
} }
jQuery('document').ready(function($) jQuery('document').ready(function($)

View File

@ -108,10 +108,10 @@
<?php } ?> <?php } ?>
<div class="form-group"> <div class="form-group">
<label>Numéro à employer : </label> <label>Numéro à employer : </label>
<select name="origin" class="form-control"> <select name="id_phone" class="form-control">
<option value="">N'importe lequel</option> <option value="">N'importe lequel</option>
<?php foreach ($phones as $phone) { ?> <?php foreach ($phones as $phone) { ?>
<option value="<?php $this->s($phone['number']); ?>"><?php $this->s($phone['number']); ?></option> <option value="<?php $this->s($phone['id']); ?>"><?php $this->s($phone['number']); ?></option>
<?php } ?> <?php } ?>
</select> </select>
</div> </div>

View File

@ -119,10 +119,10 @@
<?php } ?> <?php } ?>
<div class="form-group"> <div class="form-group">
<label>Numéro à employer : </label> <label>Numéro à employer : </label>
<select name="scheduleds[<?php $this->s($scheduled['id']); ?>][origin]" class="form-control"> <select name="scheduleds[<?php $this->s($scheduled['id']); ?>][id_phone]" class="form-control">
<option <?php echo ($scheduled['origin'] ? '' : 'selected="selected"'); ?> value="">N'importe lequel</option> <option <?php echo ($scheduled['id_phone'] ? '' : 'selected="selected"'); ?> value="">N'importe lequel</option>
<?php foreach ($phones as $phone) { ?> <?php foreach ($phones as $phone) { ?>
<option <?php echo ($scheduled['origin'] == $phone['number'] ? 'selected="selected"' : '' ); ?> value="<?php $this->s($phone['number']); ?>"><?php $this->s($phone['number']); ?></option> <option <?php echo ($scheduled['id_phone'] == $phone['id'] ? 'selected="selected"' : '' ); ?> value="<?php $this->s($phone['id']); ?>"><?php $this->s($phone['number']); ?></option>
<?php } ?> <?php } ?>
</select> </select>
</div> </div>