1
1
use chrono;
2
2
use rocket:: http:: { Cookie , CookieJar } ;
3
3
use rocket:: serde:: { Deserialize , Serialize } ;
4
+ use time:: Duration ;
4
5
6
+ /// Session data.
7
+ #[ derive( Serialize , Deserialize , Debug , Clone ) ]
8
+ pub struct Notifications {
9
+ /// App-wide notifications.
10
+ notifications : Vec < NotificationCookie > ,
11
+ }
12
+
13
+ /// App-wide notifications.
5
14
#[ derive( Debug , Clone , Deserialize , Serialize , Default , PartialEq ) ]
6
15
pub struct NotificationCookie {
16
+ /// Unique ID of the notification.
7
17
pub id : String ,
18
+ /// Time the notification was viewed. Used for reshowing the notification.
8
19
pub time_viewed : Option < chrono:: DateTime < chrono:: Utc > > ,
20
+ /// Time the notification modal was viewed. Used for reshowing the notification modal.
9
21
pub time_modal_viewed : Option < chrono:: DateTime < chrono:: Utc > > ,
10
22
}
11
23
12
- pub struct Notifications { }
24
+ #[ derive( Serialize , Deserialize , Debug , Clone ) ]
25
+ pub struct NotificationsCookieOld {
26
+ pub notifications : Vec < String > ,
27
+ }
28
+
29
+ impl From < NotificationsCookieOld > for NotificationCookie {
30
+ fn from ( old : NotificationsCookieOld ) -> Self {
31
+ NotificationCookie {
32
+ id : old. notifications [ 0 ] . clone ( ) ,
33
+ time_viewed : None ,
34
+ time_modal_viewed : None ,
35
+ }
36
+ }
37
+ }
13
38
14
39
impl Notifications {
15
- pub fn update_viewed ( all_desired_notifications : & Vec < NotificationCookie > , cookies : & CookieJar < ' _ > ) {
16
- let session = Notifications :: safe_serialize_session ( all_desired_notifications) ;
40
+ /// Update the viewed notifications in the session.
41
+ pub fn update_viewed ( notifications : & [ NotificationCookie ] , cookies : & CookieJar < ' _ > ) {
42
+ let session = Notifications :: safe_serialize_session ( notifications) ;
17
43
18
44
let mut cookie = Cookie :: new ( "session" , session) ;
19
- cookie. set_max_age ( :: time :: Duration :: weeks ( 4 ) ) ;
45
+ cookie. set_max_age ( Duration :: weeks ( 52 * 100 ) ) ; // Keep the cookie "forever"
20
46
cookies. add_private ( cookie) ;
21
47
}
22
48
49
+ /// Get viewed notifications from the session.
23
50
pub fn get_viewed ( cookies : & CookieJar < ' _ > ) -> Vec < NotificationCookie > {
24
51
match cookies. get_private ( "session" ) {
25
52
Some ( session) => Notifications :: safe_deserialize_session ( session. value ( ) ) ,
@@ -28,40 +55,21 @@ impl Notifications {
28
55
}
29
56
30
57
pub fn safe_deserialize_session ( session : & str ) -> Vec < NotificationCookie > {
31
- match serde_json:: from_str :: < serde_json:: Value > ( session) . unwrap_or_else ( |_| {
32
- serde_json:: from_str :: < serde_json:: Value > ( & Notifications :: safe_serialize_session ( & vec ! [ ] ) ) . unwrap ( )
33
- } ) [ "notifications" ]
34
- . as_array ( )
35
- {
36
- Some ( items) => items
37
- . into_iter ( )
38
- . map ( |notification| {
39
- serde_json:: from_str :: < NotificationCookie > ( & notification. to_string ( ) ) . unwrap_or_else ( |_| {
40
- serde_json:: from_str :: < String > ( & notification. to_string ( ) )
41
- . and_then ( |id| {
42
- Ok ( NotificationCookie {
43
- id,
44
- time_viewed : None ,
45
- time_modal_viewed : None ,
46
- } )
47
- } )
48
- . unwrap_or_else ( |_| NotificationCookie :: default ( ) )
49
- } )
50
- } )
51
- . collect :: < Vec < NotificationCookie > > ( ) ,
52
- _ => vec ! [ ] ,
58
+ match serde_json:: from_str :: < Notifications > ( session) {
59
+ Ok ( notifications) => notifications. notifications ,
60
+ Err ( _) => match serde_json:: from_str :: < NotificationsCookieOld > ( session) {
61
+ Ok ( notifications) => vec ! [ NotificationCookie :: from( notifications) ] ,
62
+ Err ( _) => vec ! [ ] ,
63
+ } ,
53
64
}
54
65
}
55
66
56
- pub fn safe_serialize_session ( cookies : & Vec < NotificationCookie > ) -> String {
57
- let serialized = cookies
58
- . iter ( )
59
- . map ( |x| serde_json:: to_string ( x) )
60
- . filter ( |x| x. is_ok ( ) )
61
- . map ( |x| x. unwrap ( ) )
62
- . collect :: < Vec < String > > ( ) ;
67
+ pub fn safe_serialize_session ( notifications : & [ NotificationCookie ] ) -> String {
68
+ let notifications = Notifications {
69
+ notifications : notifications. to_vec ( ) ,
70
+ } ;
63
71
64
- format ! ( r#"{{" notifications": [{}]}}"# , serialized . join ( "," ) )
72
+ serde_json :: to_string ( & notifications) . unwrap ( )
65
73
}
66
74
}
67
75
@@ -118,7 +126,7 @@ mod test {
118
126
time_viewed: None ,
119
127
time_modal_viewed: None ,
120
128
} ] ;
121
- let expected = r#"{"notifications": [{"id":"1","time_viewed":null,"time_modal_viewed":null}]}"# ;
129
+ let expected = r#"{"notifications":[{"id":"1","time_viewed":null,"time_modal_viewed":null}]}"# ;
122
130
assert_eq ! ( Notifications :: safe_serialize_session( & cookies) , expected) ;
123
131
}
124
132
}
0 commit comments