summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kjetil.orbekk@gmail.com>2017-07-13 07:28:42 -0400
committerKjetil Orbekk <kjetil.orbekk@gmail.com>2017-07-13 07:28:42 -0400
commitfe6d45474a2024fb362ee59f7a38f827283ac0c4 (patch)
treecc09092fac8bca86372939cabc61220b1e0e303c
parentba1ab61901e657903a34b0b0acecb81c12b5e0d0 (diff)
add: Persistent user id.
This will be used to limit users to one vote per quote.
-rw-r--r--Cargo.lock118
-rw-r--r--Cargo.toml2
-rw-r--r--src/data.rs31
-rw-r--r--src/data/templates/base.hbs1
-rw-r--r--src/error.rs10
-rw-r--r--src/lib.rs2
-rw-r--r--src/main.rs23
-rw-r--r--src/server.rs58
8 files changed, 226 insertions, 19 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 616dc9f..ab51d14 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8,10 +8,12 @@ dependencies = [
"handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
"handlebars-iron 0.24.1 (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)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"params 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"router 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rusqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -51,6 +53,29 @@ dependencies = [
]
[[package]]
+name = "backtrace"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "base64"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -86,6 +111,11 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "cfg-if"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "chrono"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -119,6 +149,26 @@ dependencies = [
]
[[package]]
+name = "cookie"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "openssl 0.9.14 (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.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "dbghelp-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "dtoa"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -147,6 +197,24 @@ dependencies = [
]
[[package]]
+name = "error-chain"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foreign-types"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "gcc"
+version = "0.3.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "handlebars"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -225,6 +293,17 @@ dependencies = [
]
[[package]]
+name = "iron-sessionstorage"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+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)",
+ "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "itoa"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -429,6 +508,28 @@ dependencies = [
]
[[package]]
+name = "openssl"
+version = "0.9.14"
+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.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "params"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -594,6 +695,11 @@ dependencies = [
]
[[package]]
+name = "rustc-demangle"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -896,24 +1002,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
+"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
+"checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff"
"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bodyparser 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6928e817538b74a73d1dd6e9a942a2a35c632a597b6bb14fd009480f859a6bf5"
"checksum buf_redux 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "861b9d19b9f5cb40647242d10d0cb0a13de0a96d5ff8c8a01ea324fa3956eb7d"
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
+"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9"
"checksum clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867a885995b4184be051b70a592d4d70e32d7a188db6e8dff626af286a962771"
"checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8"
+"checksum cookie 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d12191219481eb202e05529f646f9af8d1ecfcd53bbf3997d4a4b15ca095cf8"
+"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
"checksum error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e606f14042bb87cc02ef6a14db6c90ab92ed6f62d87e69377bc759fd7987cc"
+"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
+"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
+"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a"
"checksum handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fbba80e74e9591a5f6a4ffff6b7f9d645759a896e431cfbdc853e9184370294a"
"checksum handlebars-iron 0.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b2625ebcf649448bce7d8f895c8355a696ae62a3fb351fbc817312f48d9a6fa8"
"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
"checksum hyper 0.10.12 (registry+https://github.com/rust-lang/crates.io-index)" = "0f01e4a20f5dfa5278d7762b7bdb7cab96e24378b9eca3889fbd4b5e94dc7063"
"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37"
"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.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
@@ -940,6 +1055,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d"
"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"
"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
+"checksum openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41"
+"checksum openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "236c718c2e2c2b58a546d86ffea5194400bb15dbe01ca85325ffd357b03cf66c"
"checksum params 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "421e9f2c30e80365c9672709be664bfc84f73b088720d1cc1f4e99675814bb37"
"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
"checksum persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c9c94f2ef72dc272c6bcc8157ccf2bc7da14f4c58c69059ac2fc48492d6916"
@@ -961,6 +1078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"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.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffaf393ccdac5580092a4d8eb2edffbffe9a8c4484c62d8a0fcac99bc3718566"
+"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
diff --git a/Cargo.toml b/Cargo.toml
index 9f288a0..ca9de78 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ logger = "~0.3.0"
router = "~0.5.0"
handlebars = "~0.26.0"
handlebars-iron = "~0.24.0"
+iron-sessionstorage = "~0.6.0"
log = "^0.3"
env_logger = "^0.3"
rusqlite = "^0.12.0"
@@ -19,3 +20,4 @@ serde_derive = "^1.0.0"
persistent = "^0.3.0"
params = "^0.6.0"
chrono = "^0.4.0"
+rand = "^0.3"
diff --git a/src/data.rs b/src/data.rs
index 5674f92..a5d7afb 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -1,5 +1,6 @@
use rusqlite::Connection;
use error::{Result, LinoError};
+use rand::{OsRng, Rng};
#[derive(Serialize, Debug, Clone)]
pub struct Quote {
@@ -31,8 +32,27 @@ pub fn init(c: &Connection) -> Result<()> {
score INTEGER NOT NULL,
FOREIGN KEY(quote_id) REFERENCES quotes(id)
);
+
+ CREATE TABLE IF NOT EXISTS keys (
+ id TEXT PRIMARY KEY,
+ value BLOB NOT NULL
+ );
"#,
)?;
+
+ let key = {
+ let mut v = vec![0u8; 32];
+ (OsRng::new()?).fill_bytes(v.as_mut());
+ v
+ };
+ c.execute(
+ r#"
+ INSERT OR IGNORE INTO keys (id, value) VALUES
+ ('session', ?1);
+ "#,
+ &[&key],
+ )?;
+
Ok(())
}
@@ -56,6 +76,17 @@ pub fn populate_test_db(c: &Connection) -> Result<()> {
Ok(())
}
+pub fn get_key(c: &Connection, id: &str) -> Result<Vec<u8>> {
+ let key = c.query_row(
+ r#"
+ SELECT value FROM keys WHERE id = ?1
+ "#,
+ &[&id],
+ |row| row.get(0),
+ )?;
+ Ok(key)
+}
+
pub fn new_quote(c: &Connection, date: &str, author: &str, content: &str) -> Result<()> {
c.execute(
r#"
diff --git a/src/data/templates/base.hbs b/src/data/templates/base.hbs
index d548965..db7bb9e 100644
--- a/src/data/templates/base.hbs
+++ b/src/data/templates/base.hbs
@@ -67,6 +67,7 @@
<p>linoquotes v.3 © 2004-2017 Kjetil Ørbekk, Erlend Hamberg, Vidar Holen, John H. Anthony.
<p>Source code at <a href="https://git.orbekk.com/linoquotes-gamma.git">https://git.orbekk.com/linoquotes-gamma.git</a>.
<p>The quotes on this page are copyright their respective owners and submitters.</p>
+<p>Your user id: {{user_id}}.
</center>
</body>
diff --git a/src/error.rs b/src/error.rs
index 41b4e64..1005564 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -9,6 +9,7 @@ use iron::modifiers::Header;
#[derive(Debug)]
pub enum LinoError {
DbError(rusqlite::Error),
+ IoError(std::io::Error),
NotFound(String),
BadRequest(String),
}
@@ -19,6 +20,7 @@ impl fmt::Display for LinoError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
LinoError::DbError(ref err) => err.fmt(f),
+ LinoError::IoError(ref err) => err.fmt(f),
LinoError::NotFound(ref x) => write!(f, "Could not find {}", x),
LinoError::BadRequest(ref x) => write!(f, "Bad request: {}", x),
}
@@ -29,6 +31,7 @@ impl std::error::Error for LinoError {
fn description(&self) -> &str {
match *self {
LinoError::DbError(ref err) => err.description(),
+ LinoError::IoError(ref err) => err.description(),
LinoError::NotFound(_) => "not found",
LinoError::BadRequest(_) => "bad request",
}
@@ -37,6 +40,7 @@ impl std::error::Error for LinoError {
fn cause(&self) -> Option<&std::error::Error> {
match *self {
LinoError::DbError(ref err) => Some(err),
+ LinoError::IoError(ref err) => Some(err),
LinoError::NotFound(_) => None,
LinoError::BadRequest(_) => None,
}
@@ -49,6 +53,12 @@ impl From<rusqlite::Error> for LinoError {
}
}
+impl From<std::io::Error> for LinoError {
+ fn from(err: std::io::Error) -> LinoError {
+ LinoError::IoError(err)
+ }
+}
+
impl From<LinoError> for IronError {
fn from(err: LinoError) -> IronError {
let code = match err {
diff --git a/src/lib.rs b/src/lib.rs
index 6b448d9..fcceb48 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,6 +13,8 @@ extern crate persistent;
extern crate params;
extern crate chrono;
extern crate logger;
+extern crate rand;
+extern crate iron_sessionstorage;
pub mod server;
pub mod data;
diff --git a/src/main.rs b/src/main.rs
index 026f610..e687255 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -62,17 +62,18 @@ fn main() {
linoquotes_gamma::data::populate_test_db(&state.connection).unwrap();
}
- for i in 1..1000 {
- linoquotes_gamma::data::new_quote(
- &state.connection,
- "2017-07-10",
- "orbekk",
- &format!("another test {}", i),
- ).unwrap();
- let qid = state.connection.last_insert_rowid();
- info!("Last inserted quote: {}", qid);
- linoquotes_gamma::data::approve_quote(&state.connection, qid).unwrap();
- }
+ // for i in 1..1000 {
+ // linoquotes_gamma::data::new_quote(
+ // &state.connection,
+ // "2017-07-10",
+ // "orbekk",
+ // &format!("another test {}", i),
+ // ).unwrap();
+ // let qid = state.connection.last_insert_rowid();
+ // info!("Last inserted quote: {}", qid);
+ // linoquotes_gamma::data::approve_quote(&state.connection, qid).unwrap();
+ // }
+ info!("Starting...");
linoquotes_gamma::server::serve(state, port);
}
diff --git a/src/server.rs b/src/server.rs
index 4816c33..54beb34 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -8,11 +8,14 @@ use rusqlite::Connection;
use std::collections::BTreeMap;
use persistent::Write;
use handlebars_iron::handlebars::to_json;
-use serde_json::Map;
+use serde_json;
use params;
use error::LinoError;
use chrono;
use logger::Logger;
+use iron_sessionstorage::{self, SessionStorage, SessionRequestExt};
+use iron_sessionstorage::backends::SignedCookieBackend;
+use rand::{OsRng, Rng};
#[derive(Debug)]
pub struct State {
@@ -22,6 +25,41 @@ impl iron::typemap::Key for State {
type Value = State;
}
+#[derive(Debug, Clone, Serialize)]
+struct UserId(u64);
+impl iron_sessionstorage::Value for UserId {
+ fn get_key() -> &'static str {
+ "user_id"
+ }
+ fn into_raw(self) -> String {
+ format!("{}", self.0)
+ }
+ fn from_raw(value: String) -> Option<Self> {
+ value.parse().ok().map(|i| UserId(i))
+ }
+}
+
+fn user_id(r: &mut Request) -> IronResult<UserId> {
+ if let Some(user_id) = r.session().get::<UserId>()? {
+ return Ok(user_id);
+ }
+
+ let mut rng = OsRng::new().map_err(|e| {
+ // This is ugly, but I don't know how to annotate the expression.
+ let e: LinoError = From::from(e);
+ e
+ })?;
+ let user_id = UserId(rng.next_u64());
+ r.session().set(user_id.clone())?;
+ Ok(user_id)
+}
+
+fn make_result(r: &mut Request) -> IronResult<serde_json::Map<String, serde_json::value::Value>> {
+ let mut result = serde_json::Map::new();
+ result.insert("user_id".to_string(), to_json(&user_id(r)?));
+ Ok(result)
+}
+
fn get_param(r: &mut Request, param: &str) -> IronResult<String> {
let map = itry!(r.get_ref::<params::Params>());
match map.get(param) {
@@ -67,7 +105,7 @@ fn make_renderer() -> HandlebarsEngine {
}
fn quotes(r: &mut Request) -> IronResult<Response> {
- let mut result = Map::new();
+ let mut result = make_result(r)?;
let quote_id = get_param(r, "id").ok().and_then(
|id| id.parse::<i64>().ok(),
);
@@ -90,9 +128,9 @@ fn quotes(r: &mut Request) -> IronResult<Response> {
)))
}
-fn add_get(_r: &mut Request) -> IronResult<Response> {
+fn add_get(r: &mut Request) -> IronResult<Response> {
let date = chrono::offset::Local::now().format("%Y-%m-%d").to_string();
- let mut result = Map::new();
+ let mut result = make_result(r)?;
result.insert("date".to_string(), to_json(&date));
Ok(Response::with((
status::Ok,
@@ -102,6 +140,7 @@ fn add_get(_r: &mut Request) -> IronResult<Response> {
}
fn add_post(r: &mut Request) -> IronResult<Response> {
+ let result = make_result(r)?;
let nick = get_param(r, "nick")?;
let date = get_param(r, "date")?;
let quote = get_param(r, "quote")?;
@@ -127,12 +166,12 @@ fn add_post(r: &mut Request) -> IronResult<Response> {
Ok(Response::with((
status::Ok,
Header(ContentType::html()),
- Template::new("add_post", Map::new()),
+ Template::new("add_post", result)
)))
}
fn approve(r: &mut Request) -> IronResult<Response> {
- let mut result = Map::new();
+ let mut result = make_result(r)?;
let quote_id = get_param(r, "id").ok().and_then(
|id| id.parse::<i64>().ok(),
);
@@ -185,7 +224,7 @@ pub fn vote(r: &mut Request) -> IronResult<Response> {
data::get_quote(&state.connection, quote_id)?
};
- let mut result = Map::new();
+ let mut result = make_result(r)?;
result.insert("quote".to_string(), to_json(&quote));
Ok(Response::with((
@@ -206,13 +245,16 @@ pub fn serve(state: State, port: u16) {
approve: get "/approve.jsp" => approve,
vote: get "/vote" => vote,
);
- let (logger_before, logger_after) = Logger::new(None);
let mut chain = Chain::new(router);
+ let (logger_before, logger_after) = Logger::new(None);
chain.link_before(logger_before);
+ let key = data::get_key(&state.connection, "session").expect("session key");
+ chain.link_around(SessionStorage::new(SignedCookieBackend::new(key)));
chain.link_after(make_renderer());
chain.link(Write::<State>::both(state));
chain.link_after(logger_after);
+
let bind_address = format!("{}:{}", "::", port);
let _server = Iron::new(chain).http(bind_address.as_str());
info!("Serving on {}", bind_address);