mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
MDL-76722 message_airnotifier: Add encrypted notifications
This commit is contained in:
parent
9bc236d48d
commit
38160a6f94
@ -39,6 +39,8 @@ $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['encryptnotifications'] = 'Encrypt notifications';
|
||||
$string['encryptnotifications_help'] = 'Enable end-to-end encryption of app notifications where possible. Only personal data is encrypted, some data may be removed from notification payload if it can\'t be encrypted.';
|
||||
$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.';
|
||||
@ -77,3 +79,4 @@ $string['serverconnectivityerror'] = 'This site is not able to connect to the no
|
||||
$string['unknowndevice'] = 'Unknown device';
|
||||
$string['userdevices'] = 'User devices';
|
||||
$string['airnotifier:managedevice'] = 'Manage devices';
|
||||
$string['view_notification'] = 'Tap to view';
|
||||
|
@ -85,6 +85,7 @@ class message_output_airnotifier extends message_output {
|
||||
$extra->site = $siteid;
|
||||
$extra->date = (!empty($eventdata->timecreated)) ? $eventdata->timecreated : time();
|
||||
$extra->notification = (!empty($eventdata->notification)) ? 1 : 0;
|
||||
$extra->encrypted = get_config('message_airnotifier', 'encryptnotifications') == 1;
|
||||
|
||||
// Site name.
|
||||
$site = get_site();
|
||||
@ -110,7 +111,6 @@ class message_output_airnotifier extends message_output {
|
||||
$devicetokens = $airnotifiermanager->get_user_devices($CFG->airnotifiermobileappname, $eventdata->userto->id);
|
||||
|
||||
foreach ($devicetokens as $devicetoken) {
|
||||
|
||||
if (!$devicetoken->enable) {
|
||||
continue;
|
||||
}
|
||||
@ -124,11 +124,18 @@ class message_output_airnotifier extends message_output {
|
||||
$curl->setopt(array('CURLOPT_TIMEOUT' => 2, 'CURLOPT_CONNECTTIMEOUT' => 2));
|
||||
$curl->setHeader($header);
|
||||
|
||||
$extra = $this->encrypt_payload($extra, $devicetoken);
|
||||
$params = array(
|
||||
'device' => $devicetoken->platform,
|
||||
'token' => $devicetoken->pushid,
|
||||
'extra' => $extra
|
||||
);
|
||||
if ($extra->encrypted) {
|
||||
// Setting alert to null makes air notifier send the notification as a data payload,
|
||||
// this forces Android phones to call the app onMessageReceived function to decrypt the notification.
|
||||
// Otherwise notifications are created by the Android system and will not be decrypted.
|
||||
$params['alert'] = null;
|
||||
}
|
||||
|
||||
// JSON POST raw body request.
|
||||
$resp = $curl->post($serverurl, json_encode($params));
|
||||
@ -137,6 +144,74 @@ class message_output_airnotifier extends message_output {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt the notification payload.
|
||||
*
|
||||
* @param stdClass $payload The notification payload.
|
||||
* @param stdClass $devicetoken The device token record
|
||||
* @return stdClass
|
||||
*/
|
||||
protected function encrypt_payload(stdClass $payload, stdClass $devicetoken): stdClass {
|
||||
if (empty($payload->encrypted)) {
|
||||
return $payload;
|
||||
}
|
||||
|
||||
if (empty($devicetoken->publickey)) {
|
||||
$payload->encrypted = false;
|
||||
return $payload;
|
||||
}
|
||||
|
||||
// Clone the data to avoid modifying the original.
|
||||
$payload = clone $payload;
|
||||
$publickey = sodium_base642bin($devicetoken->publickey, SODIUM_BASE64_VARIANT_ORIGINAL);
|
||||
$fields = [
|
||||
'userfromfullname',
|
||||
'userfromid',
|
||||
'sitefullname',
|
||||
'smallmessage',
|
||||
'fullmessage',
|
||||
'fullmessagehtml',
|
||||
'subject',
|
||||
'contexturl',
|
||||
];
|
||||
foreach ($fields as $field) {
|
||||
if (!isset($payload->$field)) {
|
||||
continue;
|
||||
}
|
||||
$payload->$field = sodium_bin2base64(sodium_crypto_box_seal(
|
||||
$payload->$field,
|
||||
$publickey
|
||||
), SODIUM_BASE64_VARIANT_ORIGINAL);
|
||||
}
|
||||
|
||||
// Remove extra fields which may contain personal data.
|
||||
// They cannot be encrypted otherwise we would go over the 4KB payload size limit.
|
||||
unset($payload->usertoid);
|
||||
unset($payload->replyto);
|
||||
unset($payload->replytoname);
|
||||
unset($payload->name);
|
||||
unset($payload->siteshortname);
|
||||
unset($payload->customdata);
|
||||
unset($payload->contexturlname);
|
||||
unset($payload->replytoname);
|
||||
unset($payload->attachment);
|
||||
unset($payload->attachname);
|
||||
unset($payload->fullmessageformat);
|
||||
unset($payload->fullmessagetrust);
|
||||
|
||||
// We use Firebase to deliver all Push Notifications, and for all device types.
|
||||
// Firebase has a 4KB payload limit.
|
||||
// https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages
|
||||
// If the message is over that limit we remove unneeded fields and replace the title with a simple message.
|
||||
if (\core_text::strlen(json_encode($payload), '8bit') > 4000) {
|
||||
unset($payload->fullmessage);
|
||||
unset($payload->fullmessagehtml);
|
||||
$payload->smallmessage = get_string('view_notification', 'message_airnotifier');
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates necessary fields in the messaging config form.
|
||||
*
|
||||
@ -221,4 +296,3 @@ class message_output_airnotifier extends message_output {
|
||||
return $airnotifiermanager->is_system_configured();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,12 @@ if ($ADMIN->fulltree) {
|
||||
get_string('airnotifieraccesskey', 'message_airnotifier'),
|
||||
get_string('configairnotifieraccesskey', 'message_airnotifier'), '', PARAM_ALPHANUMEXT));
|
||||
|
||||
$settings->add(new admin_setting_configcheckbox('message_airnotifier/encryptnotifications',
|
||||
new lang_string('encryptnotifications', 'message_airnotifier'),
|
||||
new lang_string('encryptnotifications_help', 'message_airnotifier'),
|
||||
false
|
||||
));
|
||||
|
||||
$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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user