use session crate from crates io
This commit is contained in:
Generated
+24
-7
@@ -142,6 +142,8 @@ name = "cookie"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -796,6 +798,17 @@ name = "regex-syntax"
|
||||
version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket"
|
||||
version = "0.4.2"
|
||||
@@ -829,7 +842,7 @@ dependencies = [
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket_contrib 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket_session 0.1.0 (git+https://git.ondrovo.com/packages/rocket_session.git)",
|
||||
"rocket_session 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -881,15 +894,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rocket_session"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.ondrovo.com/packages/rocket_session.git#2aaa877cb5121fcd19ac5e6f4817af9c8878d64b"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"json_dotpath 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1180,6 +1190,11 @@ name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.7.2"
|
||||
@@ -1382,11 +1397,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
|
||||
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
|
||||
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
|
||||
"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
|
||||
"checksum rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "42c1e9deb3ef4fa430d307bfccd4231434b707ca1328fae339c43ad1201cc6f7"
|
||||
"checksum rocket_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "79aa1366f9b2eccddc05971e17c5de7bb75a5431eb12c2b5c66545fd348647f4"
|
||||
"checksum rocket_contrib 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e0fa5c1392135adc0f96a02ba150ac4c765e27c58dbfd32aa40678e948f6e56f"
|
||||
"checksum rocket_http 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1391457ee4e80b40d4b57fa5765c0f2836b20d73bcbee4e3f35d93cf3b80817"
|
||||
"checksum rocket_session 0.1.0 (git+https://git.ondrovo.com/packages/rocket_session.git)" = "<none>"
|
||||
"checksum rocket_session 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d2f62206b13d4d0b2e52bd176e727519ba2326c9eea77978c54c25d48296bf"
|
||||
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||
"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
||||
@@ -1425,6 +1441,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
|
||||
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
|
||||
"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
|
||||
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ json_dotpath = "0.1.2"
|
||||
titlecase = "0.10.0"
|
||||
rand = "0.7.2"
|
||||
|
||||
rocket_session = { git = "https://git.ondrovo.com/packages/rocket_session.git" }
|
||||
rocket_session = "0.1.1"
|
||||
|
||||
# special data structure that preserves order
|
||||
indexmap = { version="1.3.0", features=["serde-1"] }
|
||||
|
||||
+6
-3
@@ -15,7 +15,8 @@ use rocket_contrib::templates::Template;
|
||||
//mod session;
|
||||
mod store;
|
||||
|
||||
use rocket_session::Session;
|
||||
mod session;
|
||||
use session::Session;
|
||||
|
||||
use crate::store::form::{
|
||||
collect_card_form, render_card_fields, render_empty_fields, MapFromForm, RenderedCard,
|
||||
@@ -30,6 +31,8 @@ use rocket::response::Redirect;
|
||||
use rocket::State;
|
||||
use std::env;
|
||||
use std::time::Duration;
|
||||
use crate::session::SessionAccess;
|
||||
//use crate::session::SessionAccess;
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct ListContext<'a> {
|
||||
@@ -64,7 +67,7 @@ fn route_index(store: State<RwLock<Store>>, session: Session, page: Option<usize
|
||||
count += 1;
|
||||
session.set("foo.bar.count", count);
|
||||
|
||||
println!("{:?}", session);
|
||||
//println!("{:?}", session);
|
||||
|
||||
let mut page = page.unwrap_or_default();
|
||||
let n_pages = (rg.data.cards.len() as f64 / PER_PAGE as f64).ceil() as usize;
|
||||
@@ -77,7 +80,7 @@ fn route_index(store: State<RwLock<Store>>, session: Session, page: Option<usize
|
||||
fields: render_empty_fields(&rg),
|
||||
pages: n_pages,
|
||||
page,
|
||||
count,
|
||||
count: count as usize,
|
||||
cards: rg
|
||||
.data
|
||||
.cards
|
||||
|
||||
+26
-139
@@ -1,172 +1,59 @@
|
||||
use json_dotpath::DotPaths;
|
||||
use parking_lot::RwLock;
|
||||
use rand::Rng;
|
||||
use rocket::fairing::{self, Fairing, Info};
|
||||
use rocket::request::FromRequest;
|
||||
|
||||
use rocket::{
|
||||
http::{Cookie, Status},
|
||||
Outcome, Request, Response, Rocket, State,
|
||||
};
|
||||
use serde_json::Value;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use serde_json::{Map, Value};
|
||||
use json_dotpath::DotPaths;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::time::{Instant, Duration};
|
||||
use std::ops::Add;
|
||||
pub type Session<'a> = rocket_session::Session<'a, serde_json::Map<String, Value>>;
|
||||
|
||||
const SESSION_ID: &'static str = "SESSID";
|
||||
pub trait SessionAccess {
|
||||
fn get<T: DeserializeOwned>(&self, path: &str) -> Option<T>;
|
||||
|
||||
type SessionsMap = HashMap<String, SessionInstance>;
|
||||
fn get_or<T: DeserializeOwned>(&self, path: &str, def: T) -> T;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SessionInstance {
|
||||
data: serde_json::Map<String, Value>,
|
||||
expires: Instant,
|
||||
fn get_or_else<T: DeserializeOwned, F: FnOnce() -> T>(&self, path: &str, def: F) -> T;
|
||||
|
||||
fn get_or_default<T: DeserializeOwned + Default>(&self, path: &str) -> T;
|
||||
|
||||
fn take<T: DeserializeOwned>(&self, path: &str) -> Option<T>;
|
||||
|
||||
fn replace<O: DeserializeOwned, N: Serialize>(&self, path: &str, new: N) -> Option<O>;
|
||||
|
||||
fn set<T: Serialize>(&self, path: &str, value: T);
|
||||
|
||||
fn remove(&self, path: &str) -> bool;
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct SessionStore {
|
||||
inner: RwLock<SessionsMap>,
|
||||
lifespan: Duration,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Hash, Clone, Debug)]
|
||||
pub struct SessionID(String);
|
||||
|
||||
impl<'a, 'r> FromRequest<'a, 'r> for &'a SessionID {
|
||||
type Error = ();
|
||||
|
||||
fn from_request(request: &'a Request<'r>) -> Outcome<Self, (Status, Self::Error), ()> {
|
||||
Outcome::Success(request.local_cache(|| {
|
||||
println!("get id");
|
||||
if let Some(cookie) = request.cookies().get(SESSION_ID) {
|
||||
println!("from cookie");
|
||||
SessionID(cookie.value().to_string()) // FIXME avoid cloning
|
||||
} else {
|
||||
println!("new id");
|
||||
SessionID(
|
||||
rand::thread_rng()
|
||||
.sample_iter(&rand::distributions::Alphanumeric)
|
||||
.take(16)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Session<'a> {
|
||||
store: State<'a, SessionStore>,
|
||||
id: &'a SessionID,
|
||||
}
|
||||
|
||||
impl<'a, 'r> FromRequest<'a, 'r> for Session<'a> {
|
||||
type Error = ();
|
||||
|
||||
fn from_request(request: &'a Request<'r>) -> Outcome<Self, (Status, Self::Error), ()> {
|
||||
Outcome::Success(Session {
|
||||
id: request.local_cache(|| {
|
||||
if let Some(cookie) = request.cookies().get(SESSION_ID) {
|
||||
SessionID(cookie.value().to_string())
|
||||
} else {
|
||||
SessionID(
|
||||
rand::thread_rng()
|
||||
.sample_iter(&rand::distributions::Alphanumeric)
|
||||
.take(16)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}),
|
||||
store: request.guard().unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Session<'a> {
|
||||
pub fn fairing() -> impl Fairing {
|
||||
SessionFairing
|
||||
}
|
||||
|
||||
fn tap<T>(&self, func : impl FnOnce(&mut serde_json::Map<String, Value>) -> T) -> T {
|
||||
let mut wg = self.store.inner.write();
|
||||
if let Some(instance) = wg.get_mut(&self.id.0) {
|
||||
instance.expires = Instant::now().add(self.store.lifespan);
|
||||
func(&mut instance.data)
|
||||
} else {
|
||||
let mut data = Map::new();
|
||||
let rv = func(&mut data);
|
||||
wg.insert(self.id.0.clone(), SessionInstance {
|
||||
data: data,
|
||||
expires: Instant::now().add(self.store.lifespan),
|
||||
});
|
||||
rv
|
||||
}
|
||||
}
|
||||
|
||||
pub fn renew(&self) {
|
||||
self.tap(|_| ())
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
self.tap(|data| data.clear())
|
||||
}
|
||||
|
||||
pub fn get<T: DeserializeOwned>(&self, path: &str) -> Option<T> {
|
||||
impl<'a> SessionAccess for Session<'a> {
|
||||
fn get<T: DeserializeOwned>(&self, path: &str) -> Option<T> {
|
||||
self.tap(|data| data.dot_get(path))
|
||||
}
|
||||
|
||||
pub fn get_or<T: DeserializeOwned>(&self, path: &str, def: T) -> T {
|
||||
fn get_or<T: DeserializeOwned>(&self, path: &str, def: T) -> T {
|
||||
self.get(path).unwrap_or(def)
|
||||
}
|
||||
|
||||
pub fn get_or_else<T: DeserializeOwned, F: FnOnce() -> T>(&self, path: &str, def: F) -> T {
|
||||
fn get_or_else<T: DeserializeOwned, F: FnOnce() -> T>(&self, path: &str, def: F) -> T {
|
||||
self.get(path).unwrap_or_else(def)
|
||||
}
|
||||
|
||||
pub fn get_or_default<T: DeserializeOwned + Default>(&self, path: &str) -> T {
|
||||
fn get_or_default<T: DeserializeOwned + Default>(&self, path: &str) -> T {
|
||||
self.get(path).unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn take<T: DeserializeOwned>(&self, path: &str) -> Option<T> {
|
||||
fn take<T: DeserializeOwned>(&self, path: &str) -> Option<T> {
|
||||
self.tap(|data| data.dot_take(path))
|
||||
}
|
||||
|
||||
pub fn replace<O: DeserializeOwned, N: Serialize>(&self, path: &str, new: N) -> Option<O> {
|
||||
fn replace<O: DeserializeOwned, N: Serialize>(&self, path: &str, new: N) -> Option<O> {
|
||||
self.tap(|data| data.dot_replace(path, new))
|
||||
}
|
||||
|
||||
pub fn set<T: Serialize>(&self, path: &str, value: T) {
|
||||
fn set<T: Serialize>(&self, path: &str, value: T) {
|
||||
self.tap(|data| data.dot_set(path, value));
|
||||
}
|
||||
|
||||
pub fn remove(&self, path: &str) -> bool {
|
||||
fn remove(&self, path: &str) -> bool {
|
||||
self.tap(|data| data.dot_remove(path))
|
||||
}
|
||||
}
|
||||
|
||||
/// Fairing struct
|
||||
struct SessionFairing;
|
||||
|
||||
impl Fairing for SessionFairing {
|
||||
fn info(&self) -> Info {
|
||||
Info {
|
||||
name: "Session Fairing",
|
||||
kind: fairing::Kind::Attach | fairing::Kind::Response,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_attach(&self, rocket: Rocket) -> Result<Rocket, Rocket> {
|
||||
Ok(rocket.manage(SessionStore::default()))
|
||||
}
|
||||
|
||||
fn on_response<'r>(&self, request: &'r Request, response: &mut Response) {
|
||||
let session = request.local_cache(|| SessionID("".to_string()));
|
||||
|
||||
if !session.0.is_empty() {
|
||||
response.adjoin_header(Cookie::build(SESSION_ID, session.0.clone()).finish());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user