Commit 0a10d56e authored by Robert Czechowski's avatar Robert Czechowski
Browse files

Add iron-sessionstorage with hotfix to no longer depend on openssl-0.9

parent 41b3c53c
Pipeline #215 failed with stage
in 10 minutes and 13 seconds
......@@ -124,11 +124,6 @@ name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.1.0"
......@@ -273,22 +268,13 @@ name = "constant_time_eq"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cookie"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (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)",
]
[[package]]
name = "cookie"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.14.6 (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)",
]
......@@ -422,7 +408,7 @@ dependencies = [
[[package]]
name = "error-chain"
version = "0.7.2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -785,13 +771,12 @@ dependencies = [
[[package]]
name = "iron-sessionstorage"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.7.0"
dependencies = [
"cookie 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -902,7 +887,7 @@ dependencies = [
"bcrypt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"handlebars-iron 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)",
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"iron-sessionstorage 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"iron-sessionstorage 0.7.0",
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mount 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"params 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -1235,18 +1220,6 @@ name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "openssl"
version = "0.9.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl"
version = "0.10.24"
......@@ -1725,6 +1698,19 @@ dependencies = [
"winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ring"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "route-recognizer"
version = "0.1.12"
......@@ -1974,6 +1960,11 @@ dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "stable_deref_trait"
version = "1.1.1"
......@@ -2328,6 +2319,11 @@ dependencies = [
"traitobject 0.1.0 (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"
......@@ -2491,7 +2487,6 @@ dependencies = [
"checksum bcrypt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a426ab63025c1d21e4e12a218c915fa22097b89ab7ed5765fa803101e004b27"
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774"
......@@ -2511,7 +2506,6 @@ dependencies = [
"checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5"
"checksum cookie 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d12191219481eb202e05529f646f9af8d1ecfcd53bbf3997d4a4b15ca095cf8"
"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c"
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
......@@ -2527,8 +2521,8 @@ dependencies = [
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
"checksum error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e606f14042bb87cc02ef6a14db6c90ab92ed6f62d87e69377bc759fd7987cc"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9"
"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
......@@ -2565,7 +2559,6 @@ dependencies = [
"checksum inotify 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8458c07bdbdaf309c80e2c3304d14c3db64e7465d4f07cf589ccb83fd0ff31a"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2440ae846e7a8c7f9b401db8f6e31b4ea5e7d3688b91761337da7e054520c75b"
"checksum iron-sessionstorage 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e609d6824dbc56e514638d22fa23bf3745d9257d066f664a3f930623bfa49d57"
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
......@@ -2614,7 +2607,6 @@ dependencies = [
"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15"
"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)" = "b5ba300217253bcc5dc68bed23d782affa45000193866e025329aa8a7a9f05b8"
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
......@@ -2663,6 +2655,7 @@ dependencies = [
"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f"
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0777154c2c3eb54f5c480db01de845652d941e47191277cc673634c3853939"
"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c"
"checksum route-recognizer 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3255338088df8146ba63d60a9b8e3556f1146ce2973bc05a75181a42ce2256"
"checksum router 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b1797ff166029cb632237bb5542696e54961b4cf75a324c6f05c9cf0584e4e"
"checksum rusqlite 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9d9118f1ce84d8d0b67f9779936432fb42bb620cef2122409d786892cce9a3c"
......@@ -2696,6 +2689,7 @@ dependencies = [
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
"checksum socket2 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df028e0e632c2a1823d920ad74895e7f9128e6438cbc4bc6fd1f180e644767b9"
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31493480e073d52522a94cdf56269dd8eb05f99549effd1826b0271690608878"
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
......@@ -2736,6 +2730,7 @@ dependencies = [
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
"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 urlencoded 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c28708636d6f7298a53b1cdb6af40f1ab523209a7cb83cf4d41b3ebc671d319"
"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde"
......
......@@ -32,7 +32,7 @@ persistent = "0.3"
staticfile = "0.4"
serde_derive = "1.0"
handlebars-iron = "0.25.1"
iron-sessionstorage = "*"
iron-sessionstorage = { path = "iron-sessionstorage" }
serde_yaml = "0.8.9"
structopt = "0.2.18"
reqwest = "0.9.19"
......
[package]
name = "iron-sessionstorage"
version = "0.7.0"
authors = ["Markus Unterwaditzer <markus@unterwaditzer.net>"]
license = "MIT"
keywords = ["iron", "sessions", "cookie", "user", "login"]
readme = "README.md"
description = "Session middleware for Iron."
repository = "https://github.com/iron/iron-sessionstorage"
homepage = "https://github.com/iron/iron-sessionstorage"
[dependencies]
iron = "0.5.1"
cookie = { version = "0.12.0", features = ["secure"] }
error-chain = "0.11"
rand = "0.4"
redis = { version = "0.8.0", optional = true }
r2d2_redis = { version = "0.7.0", optional = true }
r2d2 = { version = "0.8", optional = true }
[features]
redis-backend = ["redis", "r2d2_redis", "r2d2"]
[dev-dependencies]
router = "0.6.0"
urlencoded = "0.6.0"
Copyright (c) 2016 Markus Unterwaditzer & contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
//! You can choose between multiple backends to store your session data. The easiest to manage is
//! `SignedCookieBackend`. You need to compile with the `redis-backend` feature to use the Redis
//! backend.
mod signedcookie;
pub use self::signedcookie::SignedCookieBackend;
#[cfg(feature = "redis-backend")]
mod redis;
#[cfg(feature = "redis-backend")]
pub use self::redis::RedisBackend;
use std::iter::FromIterator;
use redis;
use redis::Commands;
use r2d2;
use r2d2_redis::RedisConnectionManager;
use iron;
use rand;
use rand::Rng;
use RawSession;
use SessionBackend;
use get_default_cookie;
use errors::*;
use iron::prelude::*;
use cookie;
const COOKIE_NAME: &'static str = "iron_session_id";
type RedisPool = r2d2::Pool<RedisConnectionManager>;
pub struct RedisSession {
session_id: String,
pool: RedisPool,
}
impl RawSession for RedisSession {
fn get_raw(&self, key: &str) -> IronResult<Option<String>> {
let conn = itry!(self.pool.get());
Ok(itry!(conn.hget(&self.session_id, key)))
}
fn set_raw(&mut self, key: &str, value: String) -> IronResult<()> {
let conn = itry!(self.pool.get());
itry!(conn.hset::<&str, &str, String, ()>(&self.session_id, key, value));
Ok(())
}
fn clear(&mut self) -> IronResult<()> {
let conn = itry!(self.pool.get());
itry!(conn.del::<&str, ()>(&self.session_id));
self.session_id = "".to_owned();
Ok(())
}
fn write(&self, res: &mut Response) -> IronResult<()> {
let cookie = get_default_cookie(COOKIE_NAME.to_owned(), self.session_id.clone());
if let Some(cookies) = res.headers.get_mut::<iron::headers::SetCookie>() {
debug_assert!(cookies.iter().all(|cookie| cookie != COOKIE_NAME));
cookies.push(format!("{}", cookie.pair()));
return Ok(());
}
res.headers
.set(iron::headers::SetCookie(vec![format!("{}", cookie.pair())]));
Ok(())
}
}
pub struct RedisBackend {
pool: RedisPool,
}
impl RedisBackend {
pub fn new<T: redis::IntoConnectionInfo>(params: T) -> Result<Self> {
let manager = try!(
RedisConnectionManager::new(params)
.chain_err(|| "Couldn't create redis connection manager")
);
let pool = try!(
r2d2::Pool::builder()
.build(manager)
.chain_err(|| "Couldn't create redis connection pool")
);
Ok(RedisBackend { pool: pool })
}
}
impl SessionBackend for RedisBackend {
type S = RedisSession;
fn from_request(&self, req: &mut Request) -> Self::S {
let session_id = req.headers
.get::<iron::headers::Cookie>()
.map(|cookies| {
// FIXME: Our cookies are unsigned. Why do I need to specify a key?
let mut jar = cookie::CookieJar::new(b"");
for cookie in cookies.iter() {
if let Ok(cookie) = cookie::Cookie::parse(&cookie) {
jar.add_original(cookie);
}
}
jar
})
.and_then(|jar| jar.find(COOKIE_NAME))
.map(|cookie| cookie.value)
.unwrap_or_else(|| {
let mut rng = rand::OsRng::new().unwrap();
String::from_iter(rng.gen_ascii_chars().take(40))
});
RedisSession {
session_id: session_id,
pool: self.pool.clone(),
}
}
}
use std::sync::Arc;
use cookie;
use iron;
use iron::prelude::*;
use RawSession;
use SessionBackend;
use get_default_cookie;
pub struct SignedCookieSession {
unsigned_jar: std::cell::RefCell<cookie::CookieJar>,
signing_key: cookie::Key,
cookie_modifier: Option<Arc<Box<dyn Fn(cookie::Cookie) -> cookie::Cookie + Send + Sync>>>
}
impl RawSession for SignedCookieSession {
fn get_raw(&self, key: &str) -> IronResult<Option<String>> {
Ok(self.unsigned_jar.borrow_mut().signed(&self.signing_key).get(key).map(|c| c.value().to_owned()))
}
fn set_raw(&mut self, key: &str, value: String) -> IronResult<()> {
let mut c = get_default_cookie(key.to_owned(), value);
if let Some(ref modifier) = self.cookie_modifier {
c = modifier(c);
}
self.unsigned_jar.borrow_mut().signed(&self.signing_key).add(c);
Ok(())
}
fn clear(&mut self) -> IronResult<()> {
#[allow(deprecated)]
self.unsigned_jar.borrow_mut().clear();
Ok(())
}
fn write(&self, res: &mut Response) -> IronResult<()> {
debug_assert!(!res.headers.has::<iron::headers::SetCookie>());
res.headers.set(iron::headers::SetCookie(
self.unsigned_jar
.borrow()
.delta()
.into_iter()
.map(|c| format!("{}", c))
.collect()
));
Ok(())
}
}
/// Use signed cookies as session storage. See
/// http://lucumr.pocoo.org/2013/11/17/my-favorite-database/ for an introduction to this concept.
///
/// You need to pass a random value to the constructor of `SignedCookieBackend`. When this value is
/// changed, all session data is lost. Never publish this value, everybody who has it can forge
/// sessions.
///
/// Note that whatever you write into your session is visible by the user (but not modifiable).
pub struct SignedCookieBackend {
signing_key: Arc<Vec<u8>>,
cookie_modifier: Option<Arc<Box<dyn Fn(cookie::Cookie) -> cookie::Cookie + Send + Sync + 'static>>>
}
impl SignedCookieBackend {
pub fn new(signing_key: Vec<u8>) -> Self {
SignedCookieBackend {
signing_key: Arc::new(signing_key),
cookie_modifier: None,
}
}
pub fn set_cookie_modifier<F: Fn(cookie::Cookie) -> cookie::Cookie + Send + Sync + 'static>(&mut self, f: F) {
self.cookie_modifier = Some(Arc::new(Box::new(f)));
}
}
impl SessionBackend for SignedCookieBackend {
type S = SignedCookieSession;
fn from_request(&self, req: &mut Request) -> Self::S {
let mut jar = cookie::CookieJar::new();
if let Some(cookies) = req.headers.get::<iron::headers::Cookie>() {
for cookie in cookies.iter() {
if let Ok(cookie) = cookie::Cookie::parse(cookie.clone()) {
jar.add_original(cookie);
}
}
};
SignedCookieSession {
unsigned_jar: std::cell::RefCell::new(jar),
signing_key: cookie::Key::from_master(&self.signing_key),
cookie_modifier: self.cookie_modifier.clone(),
}
}
}
extern crate cookie as _cookie;
#[macro_use] extern crate error_chain;
#[cfg(feature = "redis-backend")] #[macro_use] extern crate iron;
#[cfg(not(feature = "redis-backend"))] extern crate iron;
extern crate rand;
#[cfg(feature = "redis-backend")] extern crate redis;
#[cfg(feature = "redis-backend")] extern crate r2d2;
#[cfg(feature = "redis-backend")] extern crate r2d2_redis;
use iron::prelude::*;
use iron::middleware::{AroundMiddleware,Handler};
use iron::typemap;
pub mod backends;
pub mod errors;
/// Re-export of the cookie crate
pub mod cookie {
pub use _cookie::*;
}
/// A simple key-value storage interface that is internally used by `Session`. After request
/// handling the `write` method is called where the session backend has the chance to e.g. set
/// cookies or otherwise modify the response.
pub trait RawSession {
fn get_raw(&self, key: &str) -> IronResult<Option<String>>;
fn set_raw(&mut self, key: &str, value: String) -> IronResult<()>;
fn clear(&mut self) -> IronResult<()>;
fn write(&self, response: &mut Response) -> IronResult<()>;
}
pub trait SessionBackend: Send + Sync + 'static {
type S: RawSession;
/// Parse the session before request handling and return the data in parsed form.
fn from_request(&self, request: &mut Request) -> Self::S;
}
/// The most important type, the middleware you need to register.
///
/// First parameter is a session backend, which determines how your session data is actually
/// stored. Depending on whether you store your data clientside (signed cookies) or serverside
/// (e.g. Redis and a session key) you're going to have different security properties.
pub struct SessionStorage<B: SessionBackend> {
backend: B
}
impl<B: SessionBackend> SessionStorage<B> {
pub fn new(backend: B) -> Self {
SessionStorage {
backend: backend
}
}
}
/// The high-level interface you use to modify session data. You obtain this object with
/// `request.session()`.
pub struct Session {
inner: Box<dyn RawSession>,
has_changed: bool,
}
impl Session {
fn new(s: Box<dyn RawSession>) -> Self {
Session {
inner: s,
has_changed: false
}
}
}
/// A typed interface to the string-to-string mapping. Each type represents a key, each instance of
/// a type can be serialized into a value.
pub trait Value: Sized + 'static {
fn get_key() -> &'static str;
fn into_raw(self) -> String;
fn from_raw(value: String) -> Option<Self>;
}
impl Session {
/// Get a `Value` from the session.
pub fn get<T: Value + Sized + 'static>(&self) -> IronResult<Option<T>> {
Ok(try!(self.inner.get_raw(T::get_key())).and_then(T::from_raw))
}
/// Set a `Value` in the session.
pub fn set<T: Value>(&mut self, t: T) -> IronResult<()> {
// FIXME: Equality check for less unnecessary writes
self.has_changed = true;
self.inner.set_raw(T::get_key(), t.into_raw())
}
/// Clear/delete the session
pub fn clear(&mut self) -> IronResult<()> {
// FIXME: Equality check for less unnecessary writes
self.has_changed = true;
self.inner.clear()
}
}
struct SessionKey;
impl typemap::Key for SessionKey { type Value = Session; }
impl<B: SessionBackend> AroundMiddleware for SessionStorage<B> {
fn around(self, handler: Box<dyn Handler>) -> Box<dyn Handler> {
Box::new(move |req: &mut Request| -> IronResult<Response> {
let s = self.backend.from_request(req);
req.extensions.insert::<SessionKey>(Session::new(Box::new(s)));
let mut res = handler.handle(req);
let s = req.extensions.remove::<SessionKey>().unwrap();
if s.has_changed {
match res {
Ok(ref mut r) => try!(s.inner.write(r)),
Err(ref mut e) => try!(s.inner.write(&mut e.response))
}
};
res
})
}
}
/// The helper trait to obtain your session data from a request.
pub trait SessionRequestExt {
fn session(&mut self) -> &mut Session;
}
impl<'a, 'b> SessionRequestExt for Request<'a, 'b> {
fn session(&mut self) -> &mut Session {
self.extensions.get_mut::<SessionKey>().unwrap()
}
}
fn get_default_cookie(key: String, value: String) -> cookie::Cookie<'static> {
cookie::Cookie::build(key, value)