Got session expiration working.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
This commit is contained in:
@@ -11,6 +11,7 @@ use std::{
|
|||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
sync::mpsc::Receiver,
|
sync::mpsc::Receiver,
|
||||||
thread::spawn,
|
thread::spawn,
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -492,18 +493,25 @@ struct SessionEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SessionEntry {
|
impl SessionEntry {
|
||||||
|
const EXPIRE_IN: Duration = Duration::from_hours(1);
|
||||||
|
|
||||||
|
fn new(id: Field) -> Self {
|
||||||
|
Self {
|
||||||
|
id: id,
|
||||||
|
expire_time: Utc::now() + SessionEntry::EXPIRE_IN,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn id(&self) -> &Field {
|
fn id(&self) -> &Field {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_expired(&self) -> bool {
|
fn extend(&mut self) {
|
||||||
Utc::now() > self.expire_time
|
self.expire_time = Utc::now() + SessionEntry::EXPIRE_IN;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionEntry {
|
fn is_expired(&self) -> bool {
|
||||||
fn new(id: Field) -> Self {
|
Utc::now() > self.expire_time
|
||||||
Self { id: id, expire_time: Utc::now(), }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,8 +524,12 @@ mod session_entries {
|
|||||||
#[test]
|
#[test]
|
||||||
fn does_entry_return_id() {
|
fn does_entry_return_id() {
|
||||||
let id: Field = Uuid::new_v4().into();
|
let id: Field = Uuid::new_v4().into();
|
||||||
|
let start = Utc::now() + SessionEntry::EXPIRE_IN;
|
||||||
let entry = SessionEntry::new(id.clone());
|
let entry = SessionEntry::new(id.clone());
|
||||||
|
let end = Utc::now() + SessionEntry::EXPIRE_IN;
|
||||||
assert_eq!(entry.id(), &id);
|
assert_eq!(entry.id(), &id);
|
||||||
|
assert!(start < entry.expire_time, "{:?} should have been after {:?}", entry.expire_time, start);
|
||||||
|
assert!(end > entry.expire_time, "{:?} should have been after {:?}", entry.expire_time, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -529,6 +541,17 @@ mod session_entries {
|
|||||||
entry.expire_time = data - Duration::from_secs(1);
|
entry.expire_time = data - Duration::from_secs(1);
|
||||||
assert!(entry.is_expired(), "entry should be expired");
|
assert!(entry.is_expired(), "entry should be expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_expiration_be_reset() {
|
||||||
|
let mut entry = SessionEntry::new(Uuid::nil().into());
|
||||||
|
entry.expire_time = Utc::now();
|
||||||
|
let start = Utc::now() + SessionEntry::EXPIRE_IN;
|
||||||
|
entry.extend();
|
||||||
|
let end = Utc::now() + SessionEntry::EXPIRE_IN;
|
||||||
|
assert!(start < entry.expire_time, "{:?} should have been after {:?}", entry.expire_time, start);
|
||||||
|
assert!(end > entry.expire_time, "{:?} should have been after {:?}", entry.expire_time, end);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Session {
|
struct Session {
|
||||||
@@ -551,8 +574,11 @@ impl Session {
|
|||||||
},
|
},
|
||||||
_ => Field::None,
|
_ => Field::None,
|
||||||
};
|
};
|
||||||
match self.entries.get(&converted) {
|
match self.entries.get_mut(&converted) {
|
||||||
Some(data) => data.clone(),
|
Some(data) => {
|
||||||
|
data.extend();
|
||||||
|
data.clone()
|
||||||
|
}
|
||||||
None => {
|
None => {
|
||||||
let mut new_id: Field = Uuid::new_v4().into();
|
let mut new_id: Field = Uuid::new_v4().into();
|
||||||
while self.entries.contains_key(&new_id) {
|
while self.entries.contains_key(&new_id) {
|
||||||
@@ -564,6 +590,18 @@ impl Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expire(&mut self) {
|
||||||
|
let mut remove: Vec<Field> = Vec::new();
|
||||||
|
for (id, session) in self.entries.iter() {
|
||||||
|
if session.is_expired() {
|
||||||
|
remove.push(id.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for id in remove.iter() {
|
||||||
|
self.entries.remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -590,8 +628,13 @@ mod sessions {
|
|||||||
fn are_valid_uuids_returned() {
|
fn are_valid_uuids_returned() {
|
||||||
let mut sess = Session::new();
|
let mut sess = Session::new();
|
||||||
let data = sess.get(&Field::None);
|
let data = sess.get(&Field::None);
|
||||||
|
let start = Utc::now() + SessionEntry::EXPIRE_IN;
|
||||||
let result = sess.get(data.id());
|
let result = sess.get(data.id());
|
||||||
|
let end = Utc::now() + SessionEntry::EXPIRE_IN;
|
||||||
assert_eq!(result.id(), data.id());
|
assert_eq!(result.id(), data.id());
|
||||||
|
let entry = sess.entries.get(data.id()).unwrap();
|
||||||
|
assert!(start < entry.expire_time, "{:?} should have been after {:?}", entry.expire_time, start);
|
||||||
|
assert!(end > entry.expire_time, "{:?} should have been after {:?}", entry.expire_time, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -646,6 +689,17 @@ mod sessions {
|
|||||||
_ => panic!("session id should always return a uuid field"),
|
_ => panic!("session id should always return a uuid field"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn are_expired_sessions_removed() {
|
||||||
|
let mut sess = Session::new();
|
||||||
|
let lose = sess.get(&Field::None);
|
||||||
|
sess.entries.get_mut(&lose.id).unwrap().expire_time = Utc::now() - SessionEntry::EXPIRE_IN;
|
||||||
|
let keep = sess.get(&Field::None);
|
||||||
|
sess.expire();
|
||||||
|
assert_eq!(sess.entries.len(), 1, "should only contain one entry, had {:?}", sess.entries);
|
||||||
|
assert!(sess.entries.contains_key(&keep.id), "had {:?}, expected {:?}", sess.entries.keys(), &keep.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DocRegistry {
|
pub struct DocRegistry {
|
||||||
|
|||||||
Reference in New Issue
Block a user