1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
use sqlx::{Sqlite, SqliteConnection, Transaction};
use web_push::SubscriptionInfo;
use crate::{login::Login, token::Token};
pub trait Provider {
fn push(&mut self) -> Push<'_>;
}
impl Provider for Transaction<'_, Sqlite> {
fn push(&mut self) -> Push<'_> {
Push(self)
}
}
pub struct Push<'t>(&'t mut SqliteConnection);
impl Push<'_> {
pub async fn create(
&mut self,
token: &Token,
subscription: &SubscriptionInfo,
) -> Result<(), sqlx::Error> {
sqlx::query!(
r#"
insert into push_subscription (token, endpoint, p256dh, auth)
values ($1, $2, $3, $4)
"#,
token.id,
subscription.endpoint,
subscription.keys.p256dh,
subscription.keys.auth,
)
.execute(&mut *self.0)
.await?;
Ok(())
}
pub async fn by_endpoint(
&mut self,
subscriber: &Login,
endpoint: &str,
) -> Result<SubscriptionInfo, sqlx::Error> {
let row = sqlx::query!(
r#"
select
subscription.endpoint,
subscription.p256dh,
subscription.auth
from push_subscription as subscription
join token on subscription.token = token.id
join login as subscriber on token.login = subscriber.id
where subscriber.id = $1
and subscription.endpoint = $2
"#,
subscriber.id,
endpoint,
)
.fetch_one(&mut *self.0)
.await?;
let info = SubscriptionInfo::new(row.endpoint, row.p256dh, row.auth);
Ok(info)
}
pub async fn unsubscribe_token(&mut self, token: &Token) -> Result<(), sqlx::Error> {
sqlx::query!(
r#"
delete from push_subscription
where token = $1
"#,
token.id,
)
.execute(&mut *self.0)
.await?;
Ok(())
}
pub async fn unsubscribe_login(&mut self, login: &Login) -> Result<(), sqlx::Error> {
sqlx::query!(
r#"
with tokens as (
select id from token
where login = $1
)
delete from push_subscription
where token in tokens
"#,
login.id,
)
.execute(&mut *self.0)
.await?;
Ok(())
}
// Unsubscribe logic for token expiry lives in the `tokens` repository, for maintenance reasons.
pub async fn clear(&mut self) -> Result<(), sqlx::Error> {
// We assume that _all_ stored subscriptions are for a VAPID key we're about to delete.
sqlx::query!(
r#"
delete from push_subscription
"#,
)
.execute(&mut *self.0)
.await?;
Ok(())
}
}
|