ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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()->root();
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 }
ILIAS Setting Class.
global $DIC
Definition: shib_login.php:26

References $DIC, ILIAS\Notifications\ilNotificationPushHandler\$provider, 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 151 of file ilNotificationPushHandler.php.

151 : string
152 {
153 return base64_decode(str_replace(['-', '_'], ['+', '/'], $data));
154 }

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 188 of file ilNotificationPushHandler.php.

188 : string
189 {
190 $actions = [];
191 foreach ($notification->links as $link) {
192 $actions[] = [
193 'title' => $link->getTitle(),
194 'action' => $link->getUrl(),
195 ];
196 }
197
198 return base64_encode(json_encode([
199 $notification->title,
200 [
201 'data' => ['action' => $notification->action ?? '/'],
202 'icon' => $notification->iconPath ?: ilUtil::getImagePath('logo/HeaderIconResponsive.svg'),
203 'body' => $notification->shortDescription,
204 'actions' => $actions
205 ]
206 ], JSON_THROW_ON_ERROR)) . \chr(2);
207 }
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 209 of file ilNotificationPushHandler.php.

210 {
211 if ($response !== '') {
212 $this->logger->info("Push notification [$auth] response: $response");
213 }
214 switch ($http_code) {
217 $this->logger->debug("Push notification [$auth] successful.");
222 $this->logger->error("Push notification [$auth] request was invalid.");
226 $this->subscription_repo->deleteSubscription($auth);
227 $this->logger->debug("Push notification [$auth] endpoint outdated. Subscription removed.");
231 $this->logger->debug("Push notification [$auth] endpoint blocked due to heavy usage or spam.");
233 default:
234 $this->logger->info("Push notification [$auth] went into unkown/browser-specific handling.");
235 return PushQueueResult::UNKNOWN;
236 }
237 }
const HTTP_REQUEST_ENTITY_TOO_LARGE
Definition: StatusCode.php:69
$response
Definition: xapitoken.php:93

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(), and ILIAS\Notifications\Model\Push\SUCCEEDED.

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 167 of file ilNotificationPushHandler.php.

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

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
139 if ($response === false) {
140 $this->logger->error('Push notification [' . $subscription->getAuth() . '] request failed.');
142 } else {
143 $this->setLastQueueResult(
144 $this->handleResponse($curl->getInfo(CURLINFO_HTTP_CODE), $response, $subscription->getAuth())
145 );
146 }
147 $curl->close();
148 }
149 }
$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)
$post
Definition: ltitoken.php:46

References $data, $id, $post, $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 179 of file ilNotificationPushHandler.php.

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

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 156 of file ilNotificationPushHandler.php.

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

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

+ Here is the caller graph for this function:

◆ resetLastQueueResult()

ILIAS\Notifications\ilNotificationPushHandler::resetLastQueueResult ( )
protected

Definition at line 239 of file ilNotificationPushHandler.php.

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

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 244 of file ilNotificationPushHandler.php.

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

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 255 of file ilNotificationPushHandler.php.

255 : bool
256 {
257 return \in_array($id, json_decode($user->getPref('push_notification_provider') ?? '[]'), true);
258 }
getPref(string $a_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: