Skip to content

Commit

Permalink
MDL-65983 airnotifier: Configuration check report
Browse files Browse the repository at this point in the history
  • Loading branch information
jleyva committed Apr 12, 2021
1 parent 3c5a338 commit fdb4792
Show file tree
Hide file tree
Showing 5 changed files with 424 additions and 0 deletions.
111 changes: 111 additions & 0 deletions message/output/airnotifier/checkconfiguration.php
@@ -0,0 +1,111 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Check and test Push notifications configuration.
*
* @package message_airnotifier
* @copyright 2020 Juan Leyva
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

require('../../../config.php');
require_once($CFG->libdir . '/filelib.php');

$pageurl = new moodle_url('/message/output/airnotifier/checkconfiguration.php');
$PAGE->set_url($pageurl);
$PAGE->set_context(context_system::instance());

require_login();
require_capability('moodle/site:config', context_system::instance());

// Build a path.
$strheading = get_string('checkconfiguration', 'message_airnotifier');
$PAGE->navbar->add(get_string('administrationsite'));
$returl = new moodle_url('/admin/category.php', ['category' => 'messaging']);
$PAGE->navbar->add(get_string('messagingcategory', 'admin'), $returl);
$returl = new moodle_url('/admin/settings.php', ['section' => 'messagesettingairnotifier']);
$PAGE->navbar->add(get_string('pluginname', 'message_airnotifier'), $returl);
$PAGE->navbar->add($strheading);

$PAGE->set_heading($SITE->fullname);
$PAGE->set_title($strheading);

$manager = new message_airnotifier_manager();

// Sending a test Push notification.
if (data_submitted()) {
require_sesskey();

if (optional_param('confirm', 0, PARAM_INT)) {
$manager->send_test_notification($USER);

redirect($pageurl, get_string('eventnotificationsent', 'message'), 5);
} else {

if (!$manager->has_enabled_devices($CFG->airnotifiermobileappname)) {
// The user has not connected to the site with the app yet.
redirect($pageurl, get_string('nodevices', 'message_airnotifier'), 5, \core\output\notification::NOTIFY_ERROR);
}

echo $OUTPUT->header();
$message = get_string('sendtestconfirmation', 'message_airnotifier');
$confirmurl = new moodle_url($pageurl->out(false), ['confirm' => 1]);
$continueb = new single_button($confirmurl, get_string('continue'), 'post');
$cancelb = new single_button($pageurl, get_string('cancel'), 'get');
echo $OUTPUT->confirm($message, $continueb, $cancelb);
echo $OUTPUT->footer();
}
die;
}

$checkresults = $manager->check_configuration();

$table = new \html_table();
$table->data = [];
$table->head = [
get_string('status'),
get_string('check'),
get_string('summary'),
];
$table->colclasses = [
'rightalign status',
'leftalign check',
'leftalign summary',
];
$table->id = 'message_airnotifier_checkconfiguration';
$table->attributes = ['class' => 'admintable generaltable'];
$table->data = [];

$senddisabled = false;
foreach ($checkresults as $result) {
if ($result->get_status() == core\check\result::CRITICAL || $result->get_status() == core\check\result::ERROR) {
$senddisabled = true;
}
$table->data[] = [$OUTPUT->check_result($result), $result->get_summary(), $result->get_details()];
}

echo $OUTPUT->header();
echo $OUTPUT->heading($strheading);

// Check table.
echo \html_writer::table($table);

// Test notification button.
$button = $OUTPUT->single_button($PAGE->url, get_string('sendtest', 'message_airnotifier'), 'post', ['disabled' => $senddisabled]);
echo $OUTPUT->box($button, 'clearfix mdl-align');

echo $OUTPUT->footer();
183 changes: 183 additions & 0 deletions message/output/airnotifier/classes/manager.php
Expand Up @@ -217,4 +217,187 @@ public static function enable_device($deviceid, $enable) {
return $DB->update_record('message_airnotifier_devices', $device);
}

/**
* Check the system configuration to detect possible issues.
*
* @return array result checks
*/
public function check_configuration(): array {
global $CFG, $DB;

$results = [];
// Check Mobile services enabled.
$summary = html_writer::link((new moodle_url('/admin/settings.php', ['section' => 'mobilesettings'])),
get_string('enablemobilewebservice', 'admin'));
if (empty($CFG->enablewebservices) || empty($CFG->enablemobilewebservice)) {
$results[] = new core\check\result(core\check\result::CRITICAL, $summary, get_string('enablewsdescription', 'webservice'));
} else {
$results[] = new core\check\result(core\check\result::OK, $summary, get_string('enabled', 'admin'));
}

// Check Mobile notifications enabled.
require_once($CFG->dirroot . '/message/lib.php');
$processors = get_message_processors();
$enabled = false;
foreach ($processors as $processor => $status) {
if ($processor == 'airnotifier' && $status->enabled) {
$enabled = true;
}
}

$summary = html_writer::link((new moodle_url('/admin/message.php')), get_string('enableprocessor', 'message_airnotifier'));
if ($enabled) {
$results[] = new core\check\result(core\check\result::OK, $summary, get_string('enabled', 'admin'));
} else {
$results[] = new core\check\result(core\check\result::CRITICAL, $summary,
get_string('mobilenotificationsdisabledwarning', 'tool_mobile'));
}

// Check Mobile notifications configuration is ok.
$summary = html_writer::link((new moodle_url('/admin/settings.php', ['section' => 'messagesettingairnotifier'])),
get_string('notificationsserverconfiguration', 'message_airnotifier'));
if ($this->is_system_configured()) {
$results[] = new core\check\result(core\check\result::OK, $summary, get_string('configured', 'message_airnotifier'));
} else {
$results[] = new core\check\result(core\check\result::ERROR, $summary, get_string('notconfigured', 'message_airnotifier'));
}

// Check settings properly formatted. Only display in case of errors.
$settingstocheck = ['airnotifierappname', 'airnotifiermobileappname'];
if ($this->is_system_configured()) {
foreach ($settingstocheck as $setting) {
if ($CFG->$setting != trim($CFG->$setting)) {
$summary = html_writer::link((new moodle_url('/admin/settings.php', ['section' => 'messagesettingairnotifier'])),
get_string('notificationsserverconfiguration', 'message_airnotifier'));

$results[] = new core\check\result(core\check\result::ERROR, $summary,
get_string('airnotifierfielderror', 'message_airnotifier', get_string($setting, 'message_airnotifier')));
}
}
}

// Check connectivity with Airnotifier.
$url = $CFG->airnotifierurl . ':' . $CFG->airnotifierport;
$curl = new \curl();
$curl->setopt(['CURLOPT_TIMEOUT' => 5, 'CURLOPT_CONNECTTIMEOUT' => 5]);
$curl->get($url);
$info = $curl->get_info();

$summary = html_writer::link($url, get_string('airnotifierurl', 'message_airnotifier'));
if (!empty($info['http_code']) && ($info['http_code'] == 200 || $info['http_code'] == 302)) {
$results[] = new core\check\result(core\check\result::OK, $summary, get_string('online', 'message'));
} else {
$details = get_string('serverconnectivityerror', 'message_airnotifier', $url);
$curlerrno = $curl->get_errno();
if (!empty($curlerrno)) {
$details .= ' CURL ERROR: ' . $curlerrno . ' - ' . $curl->error;
}
$results[] = new core\check\result(core\check\result::ERROR, $summary, $details);
}

// Check access key by trying to create an invalid token.
$settingsurl = new moodle_url('/admin/settings.php', ['section' => 'messagesettingairnotifier']);
$summary = html_writer::link($settingsurl, get_string('airnotifieraccesskey', 'message_airnotifier'));
if (!empty($CFG->airnotifieraccesskey)) {
$url = $CFG->airnotifierurl . ':' . $CFG->airnotifierport . '/tokens/testtoken';
$header = ['Accept: application/json', 'X-AN-APP-NAME: ' . $CFG->airnotifierappname,
'X-AN-APP-KEY: ' . $CFG->airnotifieraccesskey];
$curl->setHeader($header);
$response = $curl->post($url);
$info = $curl->get_info();

if ($curlerrno = $curl->get_errno()) {
$details = get_string('serverconnectivityerror', 'message_airnotifier', $url);
$details .= ' CURL ERROR: ' . $curlerrno . ' - ' . $curl->error;
$results[] = new core\check\result(core\check\result::ERROR, $summary, $details);
} else if (!empty($info['http_code']) && $info['http_code'] == 400 && $key = json_decode($response, true)) {
if ($key['error'] == 'Invalid access key') {
$results[] = new core\check\result(core\check\result::ERROR, $summary, $key['error']);
} else {
$results[] = new core\check\result(core\check\result::OK, $summary, get_string('enabled', 'admin'));
}
}
} else {
$results[] = new core\check\result(core\check\result::ERROR, $summary,
get_string('requestaccesskey', 'message_airnotifier'));
}

// Check default preferences.
$preferences = (array) get_message_output_default_preferences();
$providerscount = 0;
$providersconfigured = 0;
foreach ($preferences as $prefname => $prefval) {
if (strpos($prefname, 'message_provider') === 0) {
$providerscount++;
if (strpos($prefval, 'airnotifier') !== false) {
$providersconfigured++;
}
}
}

$summary = html_writer::link((new moodle_url('/admin/message.php')), get_string('managemessageoutputs', 'message'));
if ($providersconfigured == 0) {
$results[] = new core\check\result(core\check\result::ERROR, $summary,
get_string('messageprovidersempty', 'message_airnotifier'));
} else if ($providersconfigured / $providerscount < 0.25) {
// Less than a 25% of the providers are enabled by default for users.
$results[] = new core\check\result(core\check\result::WARNING, $summary,
get_string('messageproviderslow', 'message_airnotifier'));
} else {
$results[] = new core\check\result(core\check\result::OK, $summary, get_string('configured', 'message_airnotifier'));
}

// Check user devices from last month.
$recentdevicescount = $DB->count_records_select('user_devices', 'appid = ? AND timemodified > ?',
[$CFG->airnotifiermobileappname, time() - (WEEKSECS * 4)]);

$summary = get_string('userdevices', 'message_airnotifier');
if (!empty($recentdevicescount)) {
$results[] = new core\check\result(core\check\result::OK, $summary, get_string('configured', 'message_airnotifier'));
} else {
$results[] = new core\check\result(core\check\result::ERROR, $summary, get_string('nodevices', 'message_airnotifier'));
}
return $results;
}

/**
* Send a test notification to the given user.
*
* @param stdClass $user user object
*/
public function send_test_notification(stdClass $user): void {
global $CFG;
require_once($CFG->dirroot . '/message/output/airnotifier/message_output_airnotifier.php');

$data = new stdClass;
$data->userto = clone $user;
$data->subject = 'Push Notification Test';
$data->fullmessage = 'This is a test message send at: ' . userdate(time());
$data->notification = 1;

// The send_message method always return true, so it does not make sense to return anything.
$airnotifier = new message_output_airnotifier();
$airnotifier->send_message($data);
}

/**
* Check whether the given user has enabled devices or not for the given app.
*
* @param string $appname the app to check
* @param int $userid the user to check the devices for (empty for current user)
* @return bool true when the user has enabled devices, false otherwise
*/
public function has_enabled_devices(string $appname, int $userid = null): bool {
$enableddevices = false;
$devices = $this->get_user_devices($appname, $userid);

foreach ($devices as $device) {
if (!$device->enable) {
continue;
}
$enableddevices = true;
break;
}
return $enableddevices;
}
}
10 changes: 10 additions & 0 deletions message/output/airnotifier/lang/en/message_airnotifier.php
Expand Up @@ -24,24 +24,30 @@

$string['airnotifieraccesskey'] = 'Airnotifier access key';
$string['airnotifierappname'] = 'Airnotifier app name';
$string['airnotifierfielderror'] = 'Please remove any empty spaces or unnecessary characters from the following field: {$a}';
$string['airnotifiermobileappname'] = 'Mobile app name';
$string['airnotifierport'] = 'Airnotifier port';
$string['airnotifierurl'] = 'Airnotifier URL';
$string['checkconfiguration'] = 'Check and test push notification configuration';
$string['configairnotifierurl'] = 'The server URL to connect to for sending push notifications.';
$string['configairnotifierport'] = 'The port to use when connecting to the airnotifier server.';
$string['configairnotifieraccesskey'] = 'The access key for connecting to the Airnotifier server. You can obtain an access key by clicking the "Request access key" link below (registered sites only) or by creating an account on the <a href="https://apps.moodle.com">Moodle Apps Portal</a>.';
$string['configairnotifierappname'] = 'The app name identifier in Airnotifier.';
$string['configairnotifiermobileappname'] = 'The Mobile app unique identifier (usually something like com.moodle.moodlemobile).';
$string['configured'] = 'Configured';
$string['deletecheckdevicename'] = 'Delete your device: {$a->name}';
$string['deletedevice'] = 'Delete the device. Note that an app can register the device again. If the device keeps reappearing, disable it.';
$string['devicetoken'] = 'Device token';
$string['enableprocessor'] = 'Enable mobile notifications';
$string['errorretrievingkey'] = 'An error occurred while retrieving the access key. Your site must be registered to use this service. If your site is already registered, please try updating your registration. Alternatively, you can obtain an access key by creating an account on the <a href="https://apps.moodle.com">Moodle Apps Portal</a>.';
$string['keyretrievedsuccessfully'] = 'The access key was retrieved successfully. To access Moodle app usage statistics, please create an account on the <a href="https://apps.moodle.com">Moodle Apps Portal</a>.';
$string['messageprovidersempty'] = 'There are no mobile notifications enabled in default notification preferences.';
$string['messageproviderslow'] = 'Only a few mobile notifications are enabled in default notification preferences.';
$string['moodleappsportallimitswarning'] = 'Please note that the number of user devices allowed to receive notifications depends on your Moodle app subscription. For details, visit the <a href="{$a}" target="_blank">Moodle Apps Portal</a>.';
$string['nodevices'] = 'No registered devices. Devices will automatically appear after you install the Moodle app and add this site.';
$string['nopermissiontomanagedevices'] = 'You don\'t have permission to manage devices.';
$string['notconfigured'] = 'The Airnotifier server has not been configured so push notifications cannot be sent.';
$string['notificationsserverconfiguration'] = 'Notifications server (Airnotifier) configuration';
$string['pluginname'] = 'Mobile';
$string['privacy:appiddescription'] = 'This is an identifier to the application being used.';
$string['privacy:enableddescription'] = 'If this device is enabled for airnotifier.';
Expand All @@ -63,5 +69,9 @@
$string['sitemustberegistered'] = 'In order to use the public Airnotifier instance, your site must be registered. Alternatively, you can obtain an access key by creating an account on the <a href="https://apps.moodle.com">Moodle Apps Portal</a>.';
$string['showhide'] = 'Enable/disable the device.';
$string['requestaccesskey'] = 'Request access key';
$string['sendtest'] = 'Send test push notification to my devices';
$string['sendtestconfirmation'] = 'A test push notification will be sent to the devices you use to connect to this site. Please ensure that your devices are connected to the Internet and that the mobile app is not open (since push notifications are only displayed when received in the background).';
$string['serverconnectivityerror'] = 'This site is not able to connect to the notifications server {$a}';
$string['unknowndevice'] = 'Unknown device';
$string['userdevices'] = 'User devices';
$string['airnotifier:managedevice'] = 'Manage devices';
4 changes: 4 additions & 0 deletions message/output/airnotifier/settings.php
Expand Up @@ -52,4 +52,8 @@
$url = new moodle_url('/message/output/airnotifier/requestaccesskey.php', array('sesskey' => sesskey()));
$link = html_writer::link($url, get_string('requestaccesskey', 'message_airnotifier'));
$settings->add(new admin_setting_heading('requestaccesskey', '', $link));
// Check configuration.
$url = new moodle_url('/message/output/airnotifier/checkconfiguration.php');
$link = html_writer::link($url, get_string('checkconfiguration', 'message_airnotifier'));
$settings->add(new admin_setting_heading('checkconfiguration', '', $link));
}

0 comments on commit fdb4792

Please sign in to comment.