Skip to content

Conversation

@p1gp1g
Copy link

@p1gp1g p1gp1g commented Nov 28, 2025

This PR adds web push support to send push notifications. Web Push is defined by 3 RFCs: RFC8030 (the requests), RFC8291 (encryption) and RFC8292 (server authorization).

It can then be used by the web application to receive real time notifications, even when nextcloud isn't opened in a tab, and without the notify_push app (which adds a websocket support to nextcloud). This is particularly useful for collaborative work, as nexcloud isn't always opened but we can expect to be notified anyway. This support is in the second PR

This support also allow to get push notifications on Android without the proxy:

  • FCM servers can be notified with webpush
  • UnifiedPush can be used, for user who prefer or can't use the Play Services

Fix #1225

Required for:
nextcloud/android#8684
nextcloud/talk-android#257

Which will also fix:
nextcloud/android#12151 (won't be necessary)
nextcloud/android#11898 (duplicate)
nextcloud/android#5510 (supersede, openpush was a research project, and their website now link to unifiedpush)
nextcloud/android#8800 (another duplicated ?)
nextcloud/android#3333 (UP supports allow using FCM without the proprietary lib)
(There might be other issues)

This was referenced Nov 28, 2025
@wrenix
Copy link

wrenix commented Nov 28, 2025

You do not signoff your commits, could you please check the DCO CI job?

@p1gp1g
Copy link
Author

p1gp1g commented Nov 28, 2025

@provokateurin it may interest you for Neon

@nickvergessen
Copy link
Member

We'll check the rough idea later this week, but CI seems pretty red at the moment 🙈

@p1gp1g
Copy link
Author

p1gp1g commented Dec 2, 2025

We'll check the rough idea later this week, but CI seems pretty red at the moment 🙈

Indeed, I'm fixing it. I was waiting for the CI to run

PS: I forgot to mention, this feature is part of a grant with NLnet

@p1gp1g p1gp1g force-pushed the back/webpush branch 2 times, most recently from 9afa07d to 4da7b5f Compare December 2, 2025 09:03
@nickvergessen
Copy link
Member

It's conflicting in composer.lock so CI is not starting 🙈

@p1gp1g
Copy link
Author

p1gp1g commented Dec 2, 2025

Should be ok now

@p1gp1g
Copy link
Author

p1gp1g commented Dec 3, 2025

@nickvergessen Can you run the CI again ?

@p1gp1g
Copy link
Author

p1gp1g commented Dec 3, 2025

I will need some help to fix the CI.

  • The static-psalm-analysis raises many UndefinedClass: I don't know how you manage to fix this on other existent classes?
  • The integration tests fail, I think it is because test:integration runs tests/Integration/run.sh and it misses mozart compose, used to get minishlink/web-push. I can't run the CI on my own repo, I think that because the workflows use your own runners. Do you mind if I push a commit that I think should work ? We probably can expect one or 2 tries before
    it works

@p1gp1g
Copy link
Author

p1gp1g commented Dec 4, 2025

The changes for the android-lib are ready, once this PR is done: nextcloud/android-library@master...p1gp1g:nextcloud-library:feat/webpush

@p1gp1g
Copy link
Author

p1gp1g commented Dec 5, 2025

@nickvergessen : Are you OK to run the CI if I push a potential fix for it? (cf. #2662 (comment))

@nickvergessen
Copy link
Member

You were missing some files to set up Mozart correctly, I added them. Let's see what that does to CI.

"time": "2025-12-02T00:53:42+00:00"
},
{
"name": "psr/clock",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is wrong here.
It might be that your dependency brings in psr/clock or in a different version or something

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it has moved to the packages list, same version: it may be possible another lib use it. Is it a problem since the lib is still listed ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that it should be here, but aparently is not anymore as per Psalm:

Error: lib/BackgroundJob/GenerateUserSettings.php:21:3: MissingDependency: OCP\AppFramework\Utility\ITimeFactory depends on class or interface psr\clock\clockinterface that does not exist (see https://psalm.dev/157)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ok if I do composer require psr/clock --dev and update the lock, so it will be explicitly included in dev requirement ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how that fully works, but psr/clock is part of server's 3rdparty directory already and we should not duplicate it or create a conflict or something.
Maybe you can try if provide solves that?
https://github.com/ChristophWurst/nextcloud_sentry/blob/9e8385fb2c0c170edbedc3d81f3d304f50197cd6/composer.json#L27-L29

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, we have to add the "provide" to nextcloud/ocp, I can push a test using a temporary repo to override nextcloud/ocp

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested different combinations, with/without provide, in notification app, in ocp, with require/require-dev and nothing works: p1gp1g#1 any idea ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found the issue: mozart removes the vendor directory after namespacing, and psc/clock is a transitive dependence of the webpush lib

@p1gp1g
Copy link
Author

p1gp1g commented Dec 5, 2025

Thank you. I think we need to ignore the new vendor directories too?

@nickvergessen
Copy link
Member

I think we need to ignore the new vendor directories too?

The vendor-bin/ part is correctly ignored already:

/vendor-bin/*/vendor

But since this app is shipped with the server it has to be buildable repeatingly, so we need to commit lib/Vendor/ at the end of the pull request work or in a follow up. (Please don't commit it yet, as it makes the PR even more unreadable and not loadable in the GitHub UI)

@p1gp1g
Copy link
Author

p1gp1g commented Dec 5, 2025

OK, I see, maybe excluding them from the lint checks then ?

nickvergessen and others added 8 commits December 9, 2025 08:14
Signed-off-by: Joas Schilling <coding@schilljs.com>
Fix index too long for the DB

Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
@p1gp1g
Copy link
Author

p1gp1g commented Dec 9, 2025

The psalm CI was fixed, but there was still some errors. The lint error is fixed now, and I moved the VAPID initialization to fix other CI. There shouldn't be much to do now. The openapi CI is expected to fail because lib/Vendor isn't included in the git repo at this moment

@p1gp1g
Copy link
Author

p1gp1g commented Dec 9, 2025

OK, the CI is finally good 👍

@blizzz
Copy link
Member

blizzz commented Dec 9, 2025

The openapi CI is expected to fail because lib/Vendor isn't included in the git repo at this moment

Are you sure? I think the lib/Vendor is just misleading, the actual mismatch that leads to the error state happens before. Did you try regenerating the openapi specs?

@p1gp1g
Copy link
Author

p1gp1g commented Dec 9, 2025

The openapi CI is expected to fail because lib/Vendor isn't included in the git repo at this moment

Are you sure? I think the lib/Vendor is just misleading, the actual mismatch that leads to the error state happens before. Did you try regenerating the openapi specs?

Yes, the openapi jsons are updated in the PR, and if I run composer run openapi nothing changes

@nickvergessen
Copy link
Member

grafik

Yeah that's okay for now.


Unfortunately I'm sick atm, but I hope to be able to review it in more detail later this or next week.

@p1gp1g
Copy link
Author

p1gp1g commented Dec 9, 2025

I wish you good recovery. I'll finish UnifiedPush support for Talk android until then :)

@github-actions
Copy link
Contributor

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

@wrenix
Copy link

wrenix commented Dec 13, 2025

Why not put lib/Vendor into the .gitignore ?

@nickvergessen
Copy link
Member

Why not put lib/Vendor into the .gitignore ?

Because we need repeatable builds and packages, so any shipped code needs to be checked in at the end.

@p1gp1g
Copy link
Author

p1gp1g commented Jan 5, 2026

Hey, I wish you recovered well, and a happy new year. This is a gentle bump to find out when you think you'll be able to continue the review ?

@nickvergessen
Copy link
Member

Hey, I wish you recovered well, and a happy new year.

Not fully there yet, but getting there. Thanks a lot.

This is a gentle bump to find out when you think you'll be able to continue the review ?

Yes.

Copy link
Member

@nickvergessen nickvergessen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After writing the summary I pressed outside of the box and it wiped the text. Sorry if this is shorter now, just can't write it twice.

I reviewed most of the code, but can't follow all the changes in Push.php. Some look like they try to do things that are unrelated to introducing webpush support?

Also we are now checking 2 database tables all the time. Comparing the table structures it should almost be possible to map them to a single one?

  • id
  • uid
  • token
  • endpoint = proxyserver
  • p256dh = devicepublickey
  • auth = pushtokenhash
  • apptypes = apptype
  • activated = ??
  • activation_token = deviceidentifier

Not sure that makes sense, just an idea. Otherwise we should start caching if a user has at least one device in webpush and/or pushhash to save queries where possible.


I'm also missing some general information. Which server is being used by default if a user/device/app would use this? Is it sending data to any 3rd party servers, e.g. unifiedpush.org?

case NO_SUB = 3;
}

#[OpenAPI(scope: 'push')]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: I think we should use a different scope, as a client either needs to implement and handle the APIs of push or the ones from webpush, but basically not both?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you prefer. On the other side, this controller only adds 3 endpoints, and they are about push notifications too, and webpush is added to the push capabilities too.

Let me know if you still prefer a new scope (webpush)

* @param string $endpoint Push Server URL, max 765 chars (RFC8030)
* @param string $uaPublicKey Public key of the device, uncompress base64url encoded (RFC8291)
* @param string $auth Authentication tag, base64url encoded (RFC8291)
* @param string $apptypes comma seperated list of types used to filter incoming notifications - apptypes are alphanum - use "all" to get all notifications, prefix with `-` to exclude (eg. 'all,-talk')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Looks like it's "our choice", then let's stick with current naming patterns:

Suggested change
* @param string $apptypes comma seperated list of types used to filter incoming notifications - apptypes are alphanum - use "all" to get all notifications, prefix with `-` to exclude (eg. 'all,-talk')
* @param string $appTypes comma seperated list of types used to filter incoming notifications - apptypes are alphanum - use "all" to get all notifications, prefix with `-` to exclude (eg. 'all,-talk')

* Register a subscription for push notifications
*
* @param string $endpoint Push Server URL, max 765 chars (RFC8030)
* @param string $uaPublicKey Public key of the device, uncompress base64url encoded (RFC8291)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UA is user agent? I'd prefer to stick with the naming you use to explain it in the description :P

Suggested change
* @param string $uaPublicKey Public key of the device, uncompress base64url encoded (RFC8291)
* @param string $devicePublicKey Public key of the device, uncompress base64url encoded (RFC8291)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RFC8291 always refer to user agents, and it may be more realistic given a single device can have multiple user agents (multiple browsers, multiple sessions, etc). Device in the comment is a shortcut

Again, let me know, I can rename if you still prefer changing

$device['token'] = (int)$device['token'];
if (!$this->validateToken($device['token'], $maxAge)) {
// Token does not exist anymore
$this->deleteProxyPushToken($device['token']);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the device was inactive for 60 days we shouldn't delete it directly.
It's possible that the device/user is coming back online.
The problem is the comment is misleading by now.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf. https://github.com/nextcloud/notifications/pull/2662/files#r2673154228 comment

validateToken used to call this function in this case, delete*PushToken have just been moved out of validateToken

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not fully, last branch of validateToken is also returning false and not deleting it:

notifications/lib/Push.php

Lines 568 to 574 in 1237d5f

if ($age > $maxAge) {
$this->printInfo('Device token is valid');
return true;
}
$this->printInfo('<comment>Device token "last checked" is older than 60 days: ' . $age . '</comment>');
return false;

Comment on lines +602 to +604
// The nextcloud application, requested with the proxy push,
// use to not support `delete-multiple`
if (!\in_array($app, ['spreed', 'talk', 'admin_notification_talk'], true)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand where this is coming from?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It comes with this commit, which will be easier to understand alone: 424adbc

424adbc#diff-5f4fa2d752904832306c56f7832e2126a1e12db8dd1679abd71e526b77989821L173

If the application wasn't 'talk' (so assumed nextcloud), we used to split notificationIds into arrays of 1 element and call pushDeleteToDevice for each elements. That's because nextcloud application doesn't support (yet) delete-multiple (which I have implemented for Nextcloud, but that's another question)

As:

  • We don't have any legacy to maintain with the new webpush feature, so that's the best moment to avoid introducing a debt here => we expect all web push client to support delete-multiple
  • It is more efficient to send delete-multiple
  • We don't have a single "application type" per UA/client with web push, but the clients subscribe to different types. It allows:
    • to handle every subscriptions independently and more efficiently
    • 3rd party clients don't have to "fake" being nextcloud or talk
    • it allows another application to subscribe only for its own notifications (for example, a task application could subscribe for tasks notifications only)

And because we don't want the behavior to change for proxy push, and notifiationIds isn't a single element array anymore, we do the notificationIds split in proxyPushDeleteToDevice if the application doesn't target talk


But looking closer at the implementation, we should do a condition to control that the device's apptype is talk, not if the app emitting the notification is talk. Which is different from the current behavior, but will probably break the CI tests (cf. 424adbc#diff-5f4fa2d752904832306c56f7832e2126a1e12db8dd1679abd71e526b77989821L173 memo: $this->deletesToPush is $userId => $appId => $notificationIds)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When/If the future PR for Nextcloud application is merged, I can open a PR here, to assume delete-multiple is supported by all proxy-push clients too, which would avoid any issue. I think it will be OK to merge it ~a year after the Nextcloud app support it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for the explanation, my biggest point of trouble was the negation on !in_array which I had missed and I was wondering why you would stop doing the better version for talk :D

if ($type === IToken::WIPE_TOKEN) {
// Token does not exist any more, should drop the push device entry
$this->printInfo('Device token is marked for remote wipe');
$this->deletePushToken($tokenId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be kept with deleteProxyPushToken

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf. This commit 094eccb =>

Before that commit, validateToken used to:

  • be used for proxyPush only
  • call deletePushToken before returning false, in 2 different cases

After that commit, validateToken:

  • can be used to validate tokens for proxyPush and webpush
  • therefore, doesn't call deletePushToken directly

As it used to call deletePushToken everytime it returned false, deleteProxyPushToken and deleteWebPushToken are now called in place everytime the validation failed; cf

I think it is more readable if the deletion doesn't happen in the validation function. If it helps to review the PR, I can do something else: keep the deletion in validateToken and add a parameter to inform if it is called for web push or proxy push. Then I can potentially open another PR to move the deletion out of the function

} catch (InvalidTokenException) {
// Token does not exist any more, should drop the push device entry
$this->printInfo('<error>InvalidTokenException is thrown</error>');
$this->deletePushToken($tokenId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be kept with deleteProxyPushToken

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf. https://github.com/nextcloud/notifications/pull/2662/files#r2673154228 comment

delete*PushToken have just been moved out of validateToken

*/
protected function webPushCallback(MessageSentReport $report): void {
if ($report->isSubscriptionExpired()) {
$this->deleteWebPushTokenByEndpoint($report->getEndpoint());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This permanently removes all the device entries, even if the subscription is continued in the future?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It removes a single push subscription, endpoints are unique

p1gp1g added 4 commits January 9, 2026 16:09
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Signed-off-by: sim <git@sgougeon.fr>
Copy link
Author

@p1gp1g p1gp1g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After writing the summary I pressed outside of the box and it wiped the text. Sorry if this is shorter now, just can't write it twice.

Thanks a lot for the review! No problem for the missing summary :)

I tried to answer all your points. I've to push a few commits after submitting that review. You made some comments to potentially change a few things, such as variable names, I made a comment to explain why I did that way, just confirm for each comments if you still want to make the modification and I'll commit it

I reviewed most of the code, but can't follow all the changes in Push.php. Some look like they try to do things that are unrelated to introducing webpush support?

Changes in Push.php should not change how it works for proxy push. But I had to move a few things when it wasn't applicable to web push. There are mainly 2 things:

  • the delete*Token has been moved out the verification function, but is called for the same events
  • the split of notificationIds for non-talk app is done later but applies to the same events

I have commented these different changes

Also we are now checking 2 database tables all the time. Comparing the table structures it should almost be possible to map them to a single one?

* id

* uid

* token

* endpoint = proxyserver

* p256dh = devicepublickey

* auth = pushtokenhash

* apptypes = apptype

* activated = ??

* activation_token = deviceidentifier

Not sure that makes sense, just an idea. Otherwise we should start caching if a user has at least one device in webpush and/or pushhash to save queries where possible.

We used to do this kind of casting for other app, and this isn't great. The columns will contain different types of data. It leads to confusion, may have side effect and make it harder to modify in the future. So I prefer 2 tables :)

I'm also missing some general information. Which server is being used by default if a user/device/app would use this? Is it sending data to any 3rd party servers, e.g. unifiedpush.org?

This first PR is about web push, so most of the time you will have one of the big players push servers (fcm.googleapis.com for Chromium based browsers, push.services.mozilla.com for Firefox based browsers, and push.apple.com for Apple products). Once this PR and the frontend PR are merged, we'll be able to get notifications on browser even when Nextcloud isn't opened in a tab (which will help me to not miss Talk messages :))

And of course, the idea is to reuse this feature for UnifiedPush too, which I have already implemented on Nextcloud app. Web push can also be used to push to FCM (Google play notifications) without nextcloud proxy, using VAPID authentication instead of the secret hosted on nextcloud proxy, which may be used to reduce load on your nextcloud proxy. The feature will probably be used by Neon too

And finally, other push servers may be used. Gnome browser doesn't have one yet, but it may be added later, and there are some new browsers being implemented

case NO_SUB = 3;
}

#[OpenAPI(scope: 'push')]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you prefer. On the other side, this controller only adds 3 endpoints, and they are about push notifications too, and webpush is added to the push capabilities too.

Let me know if you still prefer a new scope (webpush)

* Register a subscription for push notifications
*
* @param string $endpoint Push Server URL, max 765 chars (RFC8030)
* @param string $uaPublicKey Public key of the device, uncompress base64url encoded (RFC8291)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RFC8291 always refer to user agents, and it may be more realistic given a single device can have multiple user agents (multiple browsers, multiple sessions, etc). Device in the comment is a shortcut

Again, let me know, I can rename if you still prefer changing

'notnull' => true,
'length' => 767,
]);
$table->addColumn('p256dh', Types::STRING, [
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you ok with ua_public, like RFC8291 does, if we continue with uaPublicKey wit the previous comment ?

'notnull' => true,
'length' => 32,
]);
$table->addColumn('apptypes', Types::STRING, [
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was for consistency with notifications_pushhash table

Confirm and I change 👍

$publicKey = $this->appConfig->getValueString(
Application::APP_ID,
'webpush_vapid_pubkey',
lazy: true
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know the details, and you probably know better than me.

The only thing I have is the doc saying "do not flag as lazy part of code that might be called during the global loading of the instance and its apps", and getVapid isn't done called during that phase. Should I remove ?

PS: There is a typo in the doc where lazy is written in leet with a 1, 1azy


if (!$this->validateToken($device['token'], $maxAge)) {
// Token does not exist anymore
$this->deleteProxyPushToken($device['token']);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf. https://github.com/nextcloud/notifications/pull/2662/files#r2673154228 comment

validateToken used to call this function in this case, delete*PushToken have just been moved out of validateToken

Comment on lines +602 to +604
// The nextcloud application, requested with the proxy push,
// use to not support `delete-multiple`
if (!\in_array($app, ['spreed', 'talk', 'admin_notification_talk'], true)) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It comes with this commit, which will be easier to understand alone: 424adbc

424adbc#diff-5f4fa2d752904832306c56f7832e2126a1e12db8dd1679abd71e526b77989821L173

If the application wasn't 'talk' (so assumed nextcloud), we used to split notificationIds into arrays of 1 element and call pushDeleteToDevice for each elements. That's because nextcloud application doesn't support (yet) delete-multiple (which I have implemented for Nextcloud, but that's another question)

As:

  • We don't have any legacy to maintain with the new webpush feature, so that's the best moment to avoid introducing a debt here => we expect all web push client to support delete-multiple
  • It is more efficient to send delete-multiple
  • We don't have a single "application type" per UA/client with web push, but the clients subscribe to different types. It allows:
    • to handle every subscriptions independently and more efficiently
    • 3rd party clients don't have to "fake" being nextcloud or talk
    • it allows another application to subscribe only for its own notifications (for example, a task application could subscribe for tasks notifications only)

And because we don't want the behavior to change for proxy push, and notifiationIds isn't a single element array anymore, we do the notificationIds split in proxyPushDeleteToDevice if the application doesn't target talk


But looking closer at the implementation, we should do a condition to control that the device's apptype is talk, not if the app emitting the notification is talk. Which is different from the current behavior, but will probably break the CI tests (cf. 424adbc#diff-5f4fa2d752904832306c56f7832e2126a1e12db8dd1679abd71e526b77989821L173 memo: $this->deletesToPush is $userId => $appId => $notificationIds)

*/
protected function webPushCallback(MessageSentReport $report): void {
if ($report->isSubscriptionExpired()) {
$this->deleteWebPushTokenByEndpoint($report->getEndpoint());
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It removes a single push subscription, endpoints are unique

Comment on lines +602 to +604
// The nextcloud application, requested with the proxy push,
// use to not support `delete-multiple`
if (!\in_array($app, ['spreed', 'talk', 'admin_notification_talk'], true)) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When/If the future PR for Nextcloud application is merged, I can open a PR here, to assume delete-multiple is supported by all proxy-push clients too, which would avoid any issue. I think it will be OK to merge it ~a year after the Nextcloud app support it

}

protected function getWPClient(): WebPushClient {
return new WebPushClient($this->appConfig);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, no idea. For the moment this is another function so WebPushClient is initialized only if we need the VAPID public key or send a push notification, with the validation token

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: S1m <31284753+p1gp1g@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WebPush support

5 participants