summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kjetil.orbekk@gmail.com>2020-01-31 20:30:03 -0500
committerKjetil Orbekk <kjetil.orbekk@gmail.com>2020-01-31 20:30:03 -0500
commit2c86325e3c23fdddfb0a84e479437c8bc057a7eb (patch)
tree79c3f366aa062915b021da782506584262273a8b
parentcbf64a8a5c7d748722369a2ec47c1230650d7b88 (diff)
Add user request guard
-rw-r--r--src/db.rs24
-rw-r--r--src/error.rs2
-rw-r--r--src/main.rs9
-rw-r--r--src/models.rs9
-rw-r--r--src/schema.rs5
-rw-r--r--src/server.rs57
-rw-r--r--templates/index.hbs3
7 files changed, 87 insertions, 22 deletions
diff --git a/src/db.rs b/src/db.rs
index 6014db9..3f94ff2 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -1,15 +1,14 @@
use crate::error::Error;
use crate::models;
-use base64;
+use diesel::dsl::select;
+use diesel::dsl::exists;
use diesel::connection::Connection;
use diesel::pg::PgConnection;
use diesel::ExpressionMethods;
use diesel::QueryDsl;
use diesel::RunQueryDsl;
-use rand;
-use rand::Rng;
-pub const COST: u32 = 12;
+pub const COST: u32 = 10;
pub fn create_config(conn: &PgConnection, config: &models::Config) -> Result<(), Error> {
use crate::schema::config;
@@ -24,6 +23,12 @@ pub fn create_config(conn: &PgConnection, config: &models::Config) -> Result<(),
})
}
+pub fn get_config(conn: &PgConnection) -> Result<models::Config, Error> {
+ use crate::schema::config;
+ config::table.get_result::<models::Config>(conn)
+ .map_err(From::from)
+}
+
pub fn adduser(conn: &PgConnection, username: &str, password: &str) -> Result<(), Error> {
use crate::schema::users;
@@ -54,3 +59,14 @@ pub fn authenticate(
Err(Error::NotFound)
}
}
+
+pub fn user_exists(
+ conn: &PgConnection,
+ username: &str) -> Result<bool, Error> {
+ use crate::schema::users;
+
+ let result = select(exists(users::table.filter(users::username.eq(username))))
+ .get_result(conn)
+ .map_err(|err| err)?;
+ Ok(result)
+}
diff --git a/src/error.rs b/src/error.rs
index 81647d5..523922a 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -10,6 +10,7 @@ pub enum Error {
PasswordError(BcryptError),
AlreadyExists,
NotFound,
+ InternalError,
}
impl fmt::Display for Error {
@@ -19,6 +20,7 @@ impl fmt::Display for Error {
Error::PasswordError(ref e) => e.fmt(f),
Error::AlreadyExists => f.write_str("AlreadyExists"),
Error::NotFound => f.write_str("NotFound"),
+ Error::InternalError => f.write_str("InternalError"),
}
}
}
diff --git a/src/main.rs b/src/main.rs
index 6d8693f..70cd9d6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -66,9 +66,10 @@ fn main() {
if let Some(matches) = matches.subcommand_matches("init") {
let config = pjournal::models::Config {
- strava_client_id: matches.value_of("strava_client_id").unwrap(),
- strava_client_secret: matches.value_of("strava_client_secret").unwrap(),
- rocket_secret_key: matches.value_of("rocket_secret_key").unwrap(),
+ strava_client_id: matches.value_of("strava_client_id").unwrap().to_string(),
+ strava_client_secret: matches.value_of("strava_client_secret").unwrap().to_string(),
+ rocket_secret_key: matches.value_of("rocket_secret_key").unwrap().to_string(),
+ singleton: true,
};
pjournal::db::create_config(&conn, &config).unwrap();
@@ -80,6 +81,6 @@ fn main() {
let config = pjournal::server::Params {
base_url: base_url.to_string(),
};
- pjournal::server::start(db_url, config);
+ pjournal::server::start(conn, db_url, config);
}
}
diff --git a/src/models.rs b/src/models.rs
index 28a8b65..10f7d68 100644
--- a/src/models.rs
+++ b/src/models.rs
@@ -5,10 +5,11 @@ use bcrypt;
#[derive(Insertable, Queryable)]
#[table_name = "config"]
-pub struct Config<'a> {
- pub strava_client_secret: &'a str,
- pub strava_client_id: &'a str,
- pub rocket_secret_key: &'a str,
+pub struct Config {
+ pub strava_client_secret: String,
+ pub strava_client_id: String,
+ pub rocket_secret_key: String,
+ pub singleton: bool,
}
#[derive(Insertable, Queryable)]
diff --git a/src/schema.rs b/src/schema.rs
index 055d6d0..809706c 100644
--- a/src/schema.rs
+++ b/src/schema.rs
@@ -14,4 +14,7 @@ table! {
}
}
-allow_tables_to_appear_in_same_query!(config, users,);
+allow_tables_to_appear_in_same_query!(
+ config,
+ users,
+);
diff --git a/src/server.rs b/src/server.rs
index 4f98337..40e6b87 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -1,13 +1,14 @@
-use diesel::pg::PgConnection;
use rocket::http::Cookies;
use rocket::http::Cookie;
use rocket::config::Config;
use rocket::config::Environment;
use rocket::config::Value;
use rocket::http::Status;
+use rocket::request;
use rocket::request::Form;
use rocket::request::FromForm;
-use rocket::response;
+use rocket::request::FromRequest;
+use rocket::request::Request;
use rocket::response::Redirect;
use rocket::State;
use rocket_contrib::templates::Template;
@@ -24,11 +25,48 @@ pub struct Params {
#[database("db")]
pub struct Db(diesel::PgConnection);
+#[derive(Debug)]
+pub struct LoggedInUser {
+ pub username: String,
+}
+
+impl<'a, 'r> FromRequest<'a, 'r> for LoggedInUser {
+ type Error = Error;
+
+ fn from_request(request: &'a Request<'r>)
+ -> request::Outcome<Self, Self::Error> {
+ let conn = request.guard::<Db>()
+ .map_failure(|(s, ())| (s, Error::InternalError))?;
+
+ let user = (|| {
+ let username = request.cookies()
+ .get_private("user")
+ .map(|cookie| cookie.value().to_string())
+ .ok_or(Error::NotFound)?;
+ if db::user_exists(&conn, &username)? {
+ Ok(LoggedInUser{username: username})
+ } else {
+ Err(Error::NotFound)
+ }
+ })();
+
+ use request::Outcome;
+ match user {
+ Ok(user) => Outcome::Success(user),
+ Err(Error::NotFound) => Outcome::Forward(()),
+ Err(e) => Outcome::Failure((Status::InternalServerError, e)),
+ }
+ }
+}
+
#[get("/")]
-fn index() -> Template {
+fn index(user: Option<LoggedInUser>) -> Template {
let mut context = HashMap::new();
- context.insert("parent", "layout");
- context.insert("message", "Hello, World");
+ context.insert("parent", "layout".to_string());
+ context.insert("message", "Hello, World".to_string());
+ for user in user {
+ context.insert("user", user.username);
+ }
Template::render("index", context)
}
@@ -48,12 +86,10 @@ struct LoginData {
password: String,
}
-// Request guard for logged in user: https://api.rocket.rs/v0.4/rocket/request/trait.FromRequest.html
-
#[post("/login", data = "<data>")]
fn login_submit(conn: Db, data: Form<LoginData>, mut cookies: Cookies) -> Result<Redirect, Error> {
match db::authenticate(&*conn, &data.username, &data.password) {
- Ok(user) => {
+ Ok(_user) => {
cookies.add_private(Cookie::new("user", data.username.clone()));
Ok(Redirect::to(uri!(index).to_string()))
},
@@ -87,14 +123,17 @@ fn link_strava(config: State<Params>) -> Redirect {
))
}
-pub fn start(db_url: &str, params: Params) {
+pub fn start(conn: diesel::PgConnection, db_url: &str, params: Params) {
let mut database_config = HashMap::new();
let mut databases = HashMap::new();
database_config.insert("url", Value::from(db_url));
databases.insert("db", Value::from(database_config));
+ let persistent_config = db::get_config(&conn).expect("loading config");
+
let config = Config::build(Environment::Development)
.extra("databases", databases)
+ .secret_key(persistent_config.rocket_secret_key)
.finalize()
.unwrap();
diff --git a/templates/index.hbs b/templates/index.hbs
index f61c517..238e5e2 100644
--- a/templates/index.hbs
+++ b/templates/index.hbs
@@ -1,4 +1,7 @@
{{#*inline "page"}}
+{{#if user}}
+ <p>Logged in as {{ user }}</p>
+{{/if}}
<p>Message: {{ message }}</p>
<p><a href="/link_strava">Link strava account</a></p>
{{/inline}}