@@ -5,6 +5,9 @@ use std::time::Duration;
55
66use a2:: { Client , Endpoint } ;
77use anyhow:: { Context as _, Result } ;
8+ use base64:: Engine as _;
9+ use web_push_native:: jwt_simple:: prelude:: ECDSAP256PublicKeyLike as _;
10+ use web_push_native:: p256:: pkcs8:: DecodePrivateKey as _;
811
912use crate :: debouncer:: Debouncer ;
1013use crate :: metrics:: Metrics ;
@@ -19,11 +22,11 @@ pub struct State {
1922pub struct InnerState {
2023 schedule : Schedule ,
2124
22- fcm_client : reqwest:: Client ,
25+ http_client : reqwest:: Client ,
2326
24- production_client : Client ,
27+ apns_production_client : Client ,
2528
26- sandbox_client : Client ,
29+ apns_sandbox_client : Client ,
2730
2831 topic : Option < String > ,
2932
@@ -34,6 +37,8 @@ pub struct InnerState {
3437
3538 fcm_authenticator : yup_oauth2:: authenticator:: DefaultAuthenticator ,
3639
40+ vapid_key : web_push_native:: jwt_simple:: prelude:: ES256KeyPair ,
41+
3742 /// Decryptor for incoming tokens
3843 /// storing the secret keyring inside.
3944 openpgp_decryptor : PgpDecryptor ,
@@ -51,13 +56,14 @@ impl State {
5156 metrics : Metrics ,
5257 interval : Duration ,
5358 fcm_key_path : String ,
59+ vapid_key_path : String ,
5460 openpgp_keyring_path : String ,
5561 ) -> Result < Self > {
5662 let schedule = Schedule :: new ( db) ?;
57- let fcm_client = reqwest:: ClientBuilder :: new ( )
63+ let http_client = reqwest:: ClientBuilder :: new ( )
5864 . timeout ( Duration :: from_secs ( 60 ) )
5965 . build ( )
60- . context ( "Failed to build FCM client" ) ?;
66+ . context ( "Failed to build HTTP client (FCM/UBPorts/WebPush) " ) ?;
6167
6268 let fcm_key: yup_oauth2:: ServiceAccountKey =
6369 yup_oauth2:: read_service_account_key ( fcm_key_path)
@@ -68,12 +74,21 @@ impl State {
6874 . await
6975 . context ( "Failed to create authenticator" ) ?;
7076
71- let production_client =
77+ let apns_production_client =
7278 Client :: certificate ( & mut certificate, password, Endpoint :: Production )
7379 . context ( "Failed to create production client" ) ?;
7480 certificate. rewind ( ) ?;
75- let sandbox_client = Client :: certificate ( & mut certificate, password, Endpoint :: Sandbox )
76- . context ( "Failed to create sandbox client" ) ?;
81+ let apns_sandbox_client =
82+ Client :: certificate ( & mut certificate, password, Endpoint :: Sandbox )
83+ . context ( "Failed to create sandbox client" ) ?;
84+
85+ let p256_sk =
86+ web_push_native:: p256:: ecdsa:: SigningKey :: read_pkcs8_pem_file ( & vapid_key_path) ?;
87+ let vapid_key =
88+ web_push_native:: jwt_simple:: prelude:: ES256KeyPair :: from_bytes ( & p256_sk. to_bytes ( ) ) ?;
89+ let vapid_pubkey = & base64:: engine:: general_purpose:: URL_SAFE_NO_PAD
90+ . encode ( vapid_key. public_key ( ) . public_key ( ) . to_bytes_uncompressed ( ) ) ;
91+ log:: warn!( "VAPID pubkey={vapid_pubkey}" ) ;
7792
7893 let mut keyring_file = std:: fs:: File :: open ( openpgp_keyring_path) ?;
7994 let mut keyring = String :: new ( ) ;
@@ -83,13 +98,14 @@ impl State {
8398 Ok ( State {
8499 inner : Arc :: new ( InnerState {
85100 schedule,
86- fcm_client ,
87- production_client ,
88- sandbox_client ,
101+ http_client ,
102+ apns_production_client ,
103+ apns_sandbox_client ,
89104 topic,
90105 metrics,
91106 interval,
92107 fcm_authenticator,
108+ vapid_key,
93109 openpgp_decryptor,
94110 debouncer : Default :: default ( ) ,
95111 } ) ,
@@ -100,8 +116,8 @@ impl State {
100116 & self . inner . schedule
101117 }
102118
103- pub fn fcm_client ( & self ) -> & reqwest:: Client {
104- & self . inner . fcm_client
119+ pub fn http_client ( & self ) -> & reqwest:: Client {
120+ & self . inner . http_client
105121 }
106122
107123 pub async fn fcm_token ( & self ) -> Result < Option < String > > {
@@ -115,12 +131,16 @@ impl State {
115131 Ok ( token)
116132 }
117133
134+ pub fn vapid_key ( & self ) -> & web_push_native:: jwt_simple:: prelude:: ES256KeyPair {
135+ & self . inner . vapid_key
136+ }
137+
118138 pub fn production_client ( & self ) -> & Client {
119- & self . inner . production_client
139+ & self . inner . apns_production_client
120140 }
121141
122142 pub fn sandbox_client ( & self ) -> & Client {
123- & self . inner . sandbox_client
143+ & self . inner . apns_sandbox_client
124144 }
125145
126146 pub fn topic ( & self ) -> Option < & str > {
0 commit comments