ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
ILIAS\Notifications\ilNotificationPushHandler Class Reference

This is the lowest common denominator of all popular browsers. More...

+ Inheritance diagram for ILIAS\Notifications\ilNotificationPushHandler:
+ Collaboration diagram for ILIAS\Notifications\ilNotificationPushHandler:

Public Member Functions

 __construct (PushProviderInterface $provider)
 
 notify (ilNotificationObject $notification)
 
 getLastQueueResult ()
 
- Public Member Functions inherited from ILIAS\Notifications\ilNotificationHandler
 notify (ilNotificationObject $notification)
 
 showSettings (ilPropertyFormGUI $form)
 
 clear ()
 

Protected Member Functions

 buildContent (ilNotificationObject $notification)
 
 handleResponse (int $http_code, string $response, string $auth)
 
 resetLastQueueResult ()
 
 setLastQueueResult (PushQueueResult $result)
 
 validateForUser (ilObjUser $user, string $id)
 

Protected Attributes

PushRepository $subscription_repo
 
ilLogger $logger
 
string $public_key
 
string $private_key
 
string $sub
 
bool $is_enabled
 
PushQueueResult $last_queue_result
 

Private Member Functions

 base64UrlDecode (string $data)
 
 publicVapidToPEM (string $key)
 
 hash (string $data, string $key, int $length=PHP_INT_MAX, ?string $preffix=null)
 
 padKey (string $key)
 The key needs to be preffixed for the request to fit the endpoints requirement. More...
 

Private Attributes

PushProviderInterface $provider
 

Detailed Description

Constructor & Destructor Documentation

◆ __construct()

ILIAS\Notifications\ilNotificationPushHandler::__construct ( PushProviderInterface  $provider)

Definition at line 56 of file ilNotificationPushHandler.php.

57 {
58 global $DIC;
59 $this->provider = $provider;
60 $this->logger = $DIC->logger()->forComponent('noti');
61 $this->sub = $DIC->settings()->get('admin_email');
62 $this->subscription_repo = new PushRepository($DIC->database(), $DIC->user());
63 $settings = new ilSetting('notifications');
64 $this->public_key = $settings->get('application_server_key');
65 $this->private_key = file_get_contents($settings->get('private_key_path'));
66 $this->is_enabled = $settings->get('enable_push') === '1';
67 }
$settings
Definition: index.php:44
ILIAS Setting Class.
global $DIC
Definition: shib_login.php:26

References $DIC, ILIAS\Notifications\ilNotificationPushHandler\$provider, $settings, ILIAS\Repository\logger(), and ILIAS\UI\examples\Menu\Sub\sub().

+ Here is the call graph for this function:

Member Function Documentation

◆ base64UrlDecode()

ILIAS\Notifications\ilNotificationPushHandler::base64UrlDecode ( string  $data)
private

Definition at line 150 of file ilNotificationPushHandler.php.

150 : string
151 {
152 return base64_decode(str_replace(['-', '_'], ['+', '/'], $data));
153 }
$data
Definition: storeScorm.php:45

References $data.

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the caller graph for this function:

◆ buildContent()

ILIAS\Notifications\ilNotificationPushHandler::buildContent ( ilNotificationObject  $notification)
protected
Returns
string The endpoints expect an encrypted payload that end on an start of text (STX) character. This might be because of an obligation of the special encoding requirement including ECDH.

Definition at line 187 of file ilNotificationPushHandler.php.

187 : string
188 {
189 $actions = [];
190 foreach ($notification->links as $link) {
191 $actions[] = [
192 'title' => $link->getTitle(),
193 'action' => $link->getUrl(),
194 ];
195 }
196
197 return base64_encode(json_encode([
198 $notification->title,
199 [
200 'data' => ['action' => $notification->action ?? '/'],
201 'icon' => $notification->iconPath ?: ilUtil::getImagePath('logo/HeaderIconResponsive.svg'),
202 'body' => $notification->shortDescription,
203 'actions' => $actions
204 ]
205 ], JSON_THROW_ON_ERROR)) . \chr(2);
206 }
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)

References ilUtil\getImagePath().

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getLastQueueResult()

ILIAS\Notifications\ilNotificationPushHandler::getLastQueueResult ( )

◆ handleResponse()

ILIAS\Notifications\ilNotificationPushHandler::handleResponse ( int  $http_code,
string  $response,
string  $auth 
)
protected

Definition at line 208 of file ilNotificationPushHandler.php.

209 {
210 if ($response !== '') {
211 $this->logger->info("Push notification [$auth] response: $response");
212 }
213 switch ($http_code) {
216 $this->logger->debug("Push notification [$auth] successful.");
221 $this->logger->error("Push notification [$auth] request was invalid.");
225 $this->subscription_repo->deleteSubscription($auth);
226 $this->logger->debug("Push notification [$auth] endpoint outdated. Subscription removed.");
230 $this->logger->debug("Push notification [$auth] endpoint blocked due to heavy usage or spam.");
232 default:
233 $this->logger->info("Push notification [$auth] went into unkown/browser-specific handling.");
235 }
236 }
const HTTP_REQUEST_ENTITY_TOO_LARGE
Definition: StatusCode.php:69
$response
Definition: xapitoken.php:92

References $response, ILIAS\Export\ImportStatus\FAILED, ILIAS\HTTP\StatusCode\HTTP_BAD_REQUEST, ILIAS\HTTP\StatusCode\HTTP_CREATED, ILIAS\HTTP\StatusCode\HTTP_FORBIDDEN, ILIAS\HTTP\StatusCode\HTTP_GONE, ILIAS\HTTP\StatusCode\HTTP_NOT_FOUND, ILIAS\HTTP\StatusCode\HTTP_OK, ILIAS\HTTP\StatusCode\HTTP_REQUEST_ENTITY_TOO_LARGE, ILIAS\HTTP\StatusCode\HTTP_TOO_MANY_REQUESTS, ILIAS\HTTP\StatusCode\HTTP_UNAUTHORIZED, ILIAS\Repository\logger(), ILIAS\Notifications\Model\Push\SUCCEEDED, and ILIAS\WebDAV\Objects\UNKNOWN.

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hash()

ILIAS\Notifications\ilNotificationPushHandler::hash ( string  $data,
string  $key,
int  $length = PHP_INT_MAX,
?string  $preffix = null 
)
private
Parameters
string$preffixIf a info preffix is set it is required by the endpoint to be padded

Definition at line 166 of file ilNotificationPushHandler.php.

166 : string
167 {
168 if ($preffix !== null) {
169 $data = $preffix . \chr(0) . $data . \chr(1);
170 }
171 return mb_substr(hash_hmac('sha256', $data, $key, true), 0, $length, '8bit');
172 }

References $data.

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the caller graph for this function:

◆ notify()

ILIAS\Notifications\ilNotificationPushHandler::notify ( ilNotificationObject  $notification)
Parameters
bool$forceThe use of this parameter is explicitly not recommended! Forced notifications are distributed to a user without agknowledgement of their preferences and should therefore be used with care!

Reimplemented from ILIAS\Notifications\ilNotificationHandler.

Definition at line 73 of file ilNotificationPushHandler.php.

73 : void
74 {
75 $this->resetLastQueueResult();
76
77 if (!$this->is_enabled) {
78 $this->logger->debug('Notifications are globaly disabled.');
80 return;
81 }
82
83 if (!$this->provider instanceof InternalPushProvider) {
84 $id = $notification->handlerParams['setting']['user_pref'];
85 if (!$this->validateForUser($notification->user, $id)) {
86 $this->logger->debug('Notification for ' . $id . ' not send due to user preferences.');
88 return;
89 }
90 }
91
92 $subscriptions = $this->subscription_repo->getUserSubscriptions($notification->user->getId());
93 if ($subscriptions === []) {
94 $this->logger->debug('User ' . $notification->user->getId() . ' has no active Subscriptions');
96 return;
97 }
98
99 $salt = (new Randomizer())->getBytes(16);
100 $local_key = $this->base64UrlDecode($this->public_key);
101 $content = $this->buildContent($notification);
102 $ttl = $notification->handlerParams['setting']['ttl'] ?? 60;
103 foreach ($subscriptions as $subscription) {
104 $url_parts = parse_url($subscription->getEndpoint());
105 $data = [
106 'sub' => 'mailto:' . $this->sub,
107 'aud' => $url_parts['scheme'] . '://' . $url_parts['host'],
108 'exp' => time() + (int) $ttl
109 ];
110
111 $user_key = $this->base64UrlDecode($subscription->getP256dh());
112 $pre_key = $this->hash(
113 openssl_pkey_derive($this->publicVapidToPEM($user_key), $this->private_key, 256),
114 $this->base64UrlDecode($subscription->getAuth())
115 );
116 $key = $this->hash($this->hash($user_key . $local_key, $pre_key, 32, 'WebPush: info'), $salt);
117 $encryptedText = openssl_encrypt(
118 $content,
119 'aes-128-gcm',
120 $this->hash('', $key, 16, 'Content-Encoding: aes128gcm'),
121 OPENSSL_RAW_DATA,
122 $this->hash('', $key, 12, 'Content-Encoding: nonce'),
123 $tag
124 );
125 $post = $salt . $this->padKey($local_key) . $encryptedText . $tag;
126
127 $curl = new ilCurlConnection($subscription->getEndpoint());
128 $curl->init();
129 $curl->setOpt(CURLOPT_HTTPHEADER, [
130 'Content-Encoding: aes128gcm',
131 'Authorization: vapid t=' . JWT::encode($data, $this->private_key, 'ES256') . ', k=' . $this->public_key,
132 'Ttl: ' . $ttl
133 ]);
134 $curl->setOpt(CURLOPT_POST, 1);
135 $curl->setOpt(CURLOPT_RETURNTRANSFER, 1);
136 $curl->setOpt(CURLOPT_POSTFIELDS, $post);
137 $response = $curl->exec();
138 if ($response === false) {
139 $this->logger->error('Push notification [' . $subscription->getAuth() . '] request failed.');
141 } else {
142 $this->setLastQueueResult(
143 $this->handleResponse($curl->getInfo(CURLINFO_HTTP_CODE), $response, $subscription->getAuth())
144 );
145 }
146 $curl->close();
147 }
148 }
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
hash(string $data, string $key, int $length=PHP_INT_MAX, ?string $preffix=null)
padKey(string $key)
The key needs to be preffixed for the request to fit the endpoints requirement.
handleResponse(int $http_code, string $response, string $auth)

References $data, $id, $response, ILIAS\Notifications\ilNotificationPushHandler\$sub, ILIAS\Notifications\ilNotificationPushHandler\base64UrlDecode(), ILIAS\Notifications\ilNotificationPushHandler\buildContent(), ILIAS\Export\ImportStatus\FAILED, ILIAS\Notifications\ilNotificationPushHandler\handleResponse(), ILIAS\Notifications\ilNotificationPushHandler\hash(), ILIAS\Repository\int(), ILIAS\Repository\logger(), ILIAS\Notifications\ilNotificationPushHandler\padKey(), ILIAS\Notifications\ilNotificationPushHandler\publicVapidToPEM(), ILIAS\Notifications\ilNotificationPushHandler\resetLastQueueResult(), ILIAS\Notifications\ilNotificationPushHandler\setLastQueueResult(), and ILIAS\Notifications\ilNotificationPushHandler\validateForUser().

+ Here is the call graph for this function:

◆ padKey()

ILIAS\Notifications\ilNotificationPushHandler::padKey ( string  $key)
private

The key needs to be preffixed for the request to fit the endpoints requirement.

This might be due to the key conversion and url encoding.

Definition at line 178 of file ilNotificationPushHandler.php.

178 : string
179 {
180 return pack('N*', 4096) . pack('C*', mb_strlen($key, '8bit')) . $key;
181 }

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the caller graph for this function:

◆ publicVapidToPEM()

ILIAS\Notifications\ilNotificationPushHandler::publicVapidToPEM ( string  $key)
private

Definition at line 155 of file ilNotificationPushHandler.php.

155 : string
156 {
157 $der_key = pack('H*', '3059301306072a8648ce3d020106082a8648ce3d030107034200') . $key;
158 return "-----BEGIN PUBLIC KEY-----\n" .
159 chunk_split(base64_encode($der_key), 64, "\n") .
160 "-----END PUBLIC KEY-----\n";
161 }

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the caller graph for this function:

◆ resetLastQueueResult()

ILIAS\Notifications\ilNotificationPushHandler::resetLastQueueResult ( )
protected

Definition at line 238 of file ilNotificationPushHandler.php.

238 : void
239 {
240 $this->last_queue_result = null;
241 }

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the caller graph for this function:

◆ setLastQueueResult()

ILIAS\Notifications\ilNotificationPushHandler::setLastQueueResult ( PushQueueResult  $result)
protected

Definition at line 243 of file ilNotificationPushHandler.php.

243 : void
244 {
245 if (
246 $this->last_queue_result === null ||
247 $this->last_queue_result === PushQueueResult::FAILED ||
249 ) {
250 $this->last_queue_result = $result;
251 }
252 }

References ILIAS\Export\ImportStatus\FAILED, and ILIAS\Notifications\Model\Push\SUCCEEDED.

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the caller graph for this function:

◆ validateForUser()

ILIAS\Notifications\ilNotificationPushHandler::validateForUser ( ilObjUser  $user,
string  $id 
)
protected

Definition at line 254 of file ilNotificationPushHandler.php.

254 : bool
255 {
256 return \in_array($id, json_decode($user->getPref('push_notification_provider') ?? '[]'), true);
257 }
getPref(string $keyword)

References $id, and ilObjUser\getPref().

Referenced by ILIAS\Notifications\ilNotificationPushHandler\notify().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $is_enabled

bool ILIAS\Notifications\ilNotificationPushHandler::$is_enabled
protected

Definition at line 52 of file ilNotificationPushHandler.php.

◆ $last_queue_result

PushQueueResult ILIAS\Notifications\ilNotificationPushHandler::$last_queue_result
protected

◆ $logger

ilLogger ILIAS\Notifications\ilNotificationPushHandler::$logger
protected

Definition at line 48 of file ilNotificationPushHandler.php.

◆ $private_key

string ILIAS\Notifications\ilNotificationPushHandler::$private_key
protected

Definition at line 50 of file ilNotificationPushHandler.php.

◆ $provider

PushProviderInterface ILIAS\Notifications\ilNotificationPushHandler::$provider
private

◆ $public_key

string ILIAS\Notifications\ilNotificationPushHandler::$public_key
protected

Definition at line 49 of file ilNotificationPushHandler.php.

◆ $sub

string ILIAS\Notifications\ilNotificationPushHandler::$sub
protected

◆ $subscription_repo

PushRepository ILIAS\Notifications\ilNotificationPushHandler::$subscription_repo
protected

Definition at line 47 of file ilNotificationPushHandler.php.


The documentation for this class was generated from the following file: