Page tree
Skip to end of metadata
Go to start of metadata

Push profil používateľa

Údaj v db profile používateľa v JSON forme.

Mal by to byť array hashov - jeden používateľ môže mať viac prihlášok na viacerých zariadeniach - mobilný Chrome, desktop Chrome, Safari, atď.

Aktuálne sú 2 možné zápisy - s údajmi endpoint, auth a p256dh (Chrome, resp. Firefox) alebo device (Safari).

Oba formáty majú zhodné doplňujúce údaje subscription_active (boolean aktívnosť) a topic (oblasť s notifikáciami).

Topic má prednastavenú hodnotu all (hocijaké notifikácie), backend je do budúcnosti predpripravený na čiarkou oddelený zoznam topicov.

Registracia usera

Pri registrovani pouzivatela na odber notifikacii sa musi na webe v javascripte dodrzat nasledovny postup:
  1. Registrovat service worker, co je vlastne JS subor ktory sa stiahne do browsera a zije tam aj po zavreti nasho webu. Service worker sa stara o samotne pocuvanie na event push notifikacie a ich nasledne spracovanie a zobrazenie.
  2. Vyziadat subscription, ktory nam vrati tri udaje:
    1. endpoint - URL, na ktoru sa posielaju requesty (momentalne bud len push.mozilla.com alebo fcm.google.com) - jedinecna pre kazdy subscription
    2. auth - cosi ako heslo daneho usera
    3. p256dh - public kluc usera
  3. Tieto udaje treba ulozit do nasej db a v podstate pri kazdej navsteve stranky, kde sa vykonava script pre subscribnutie, overovat ci tieto udaje sedia, resp. ich asi rovno zakazdym znova ukladat lebo sa mozu zmenit. Najma ak clovek vypne a znova zapne notifikacie. V aktualnom ukazkovom scripte je to cast v subscribeUserToPush() za poznamkou "ked prebehol subscription" kde sa ziskavaju endpoint a kluce. Tam treba zavolat AJAXom spominany service pre ulozenie udajov o userovom subscriptione.
  4. Nezabudnut, ze v javascripte sa pri subscribovani pouziva public kluc servera, ktory sedi s privatnym klucom, ktory sa pouziva pri odosielani notifikacie. Preto pri generovani noveho kluca ho treba nastavit priamo do JS suboru, resp. k nemu musi mat dany obsluzny JS pristup.
  5. Nejake nasledne "zakazanie notifikacii" by sme skor mali riesit na nasej strane, t.j. si ukladat nejake nastavenia per user (kedze by sme asi chceli aj delit napr. ake typy notifikacii chce / nechce) a tym padom v podstate neriesime ziadne zakazovanie z hladiska Web Push API. Cela rozhodovacie logika by mala byt na serveri pre lepsiu kontrolu.

Pushnutie notifikacie z backendu

Pouzivame hotovu libku v Cyclone: Ext::WebPush. Postup:
  1. Nastavenie zakladnej autentifikacie - ak posielame viacero notifikacii, staci nastavit raz:
my $webpush_auth = Ext::WebPush->new({
	server_public_key => '~87 character base64 encoded string',
	server_private_key => 'file handle to private key',
});
Privatny kluc by mal byt file handle, da sa to ale "ohackovat" nasledovnym sposobom ak sa chceme vyhnut vytvaraniu externeho suboru a z toho plynucim komplikaciam:
my $server_private_key_fh = <<'EOF';
-----BEGIN EC PARAMETERS-----
...
-----END EC PRIVATE KEY-----
EOF
Bacha na whitespace - obsah "suboru" nesmie byt odsadeny, inak moze byt nevalidny. Takisto pozor na zvlastnost, ze za EOF na konci nejde bodkociarka.
  1. Samotne odoslanie notifikacie:
my $notif = $webpush_auth->send_notification({
	vapid_subject => "mailto:admin@domain.tld",
	endpoint => uri_unescape($user{'endpoint'}),
	client_auth => $user{'auth'},
	client_public_key => $user{'p256dh'},
	payload => "test message"
});
Posielame teda spominane 3 parametre z userovho subscription; vapid_subject je povinny udaj ktory sa ale nikde viditelne nepouziva, podla specifikacie JWT sa moze pouzit napr. v pripade problemov s dorucovanim spravy (napr. spravca push servicu na dany kontakt moze poslat upozornenie, je teda odporucane nech to je kontakt na administratora resp. zodpovednej osoby webu). 
Payload je samotny obsah notifikacie, vid v odseku Payload.
Teoreticky jedine povinne parametre su endpoint a vapid_subject, avsak tym padom by prisla userovi iba genericka notifikacia podla toho, ako je nastavena v service workeri, co v 99% pripadoch nechceme. Na testovanie zakladnej funkcnosti ale moze byt vynechanie ostatnych parametrov uzitocne aby sme sme izolovali problem, kedze pri nespravnom sifrovani server niekedy vrati response akoby v poriadku spravu zaevidoval (201 Created), ale realne sa k service workeru nedostane. Pri sprave bez payloadu je teda jednoduchsi debugging, kedze vieme vylucit chyby v sifrovani sposobene napr. nesediacimi klucami.

Payload

Payload moze byt aj obycajny string / text, ale obvykle posielame JSON pre nastavenie celej notifikacie. V pripade ze sa nepodari service workeru sparsovat JSON, pouzije sa cely payload ako "text" parameter.
Ukazka:
{
     "title": "Oznámenie o zníženej cene", 
     "text": "Produktu XYZ, ktorý máte v nákupnom košíku, sme znížili cenu. Neváhajte a kúpte ho už teraz!",
     "url": "https://www.mydomain.tld",
     "icon": "https://www.mydomain.tld/media/grf/fb_thumb_photo1.png"
}
title: nadpis notifikacie (odporucany)
text: hlavny text notifikacie (jediny povinny, pokial posielame JSON v payloade)
url: URL ktora sa otvori po kliknuti na notifikaciu (odporucany)
icon: nastavitelna vlastna ikonka - url (moze byt aj relativna voci service-worker.js suboru, standardne by tam mala byt nastavena ikonka napr. s logom webu).

Troubleshooting:

Do tela spravy mi dava cely JSON z payloadu.

Pravdepodobne je nevalidny JSON - musia byt kluce aj hodnoty v dvojitych uvodzovkach a nesmie byt za poslednym parom ciarka. 
Eventualne moze byt problem v nenastavenej povinnej hodnote kluca "text" - bez neho nevie, aky text pouzit.

Ako vygenerovat server kluce?

openssl ecparam -genkey -name prime256v1 -out private_key.pem
openssl ec -in private_key.pem -pubout -outform DER|tail -c 65|base64|tr -d '=' |tr '/+' '_-' >> public_key.txt
openssl ec -in private_key.pem -outform DER|tail -c +8|head -c 32|base64|tr -d '=' |tr '/+' '_-' >> private_key.txt


Dalsie citanie:

https://web-push-book.gauntface.com/ - prijemne a kvalitne spracovany ebook o web push API.
https://developers.google.com/web/updates/2016/03/web-push-encryption - momentalne jediny kompletny navod ako presne sifrovat payload na backende

Uzitocne nastroje:

https://tests.peter.sh/notification-generator - generator vsetkych moznosti notifikacii, moze byt uzitocne pre inspiraciu dalsich moznosti a pripadne rozsirovania 
https://tests.peter.sh/push-encryption-verifier/ - uzitocny verifier pre spravne sifrovanie payloadu ktory obsahuje vacsinu krokov.

Zdrojaky na inspiraciu:

https://gauntface.github.io/simple-push-demo/ - pouzite pri nasom vyvoji pre frontend
https://github.com/web-push-libs/web-push-php/ - pouzite pri nasom vyvoji ako inspiracia pre backend (Ext::WebPush)