From 3af0c639002dbf6afd80adcbde011b8896b727ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Fri, 26 Feb 2016 18:27:01 +0100 Subject: [PATCH] Authenticate /services. r=fabrice --- Cargo.lock | 74 +++++++++++++++++------------------ Cargo.toml | 8 +++- README.md | 9 +++++ src/service_router.rs | 89 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 126 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e32eb39..d11bec42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,7 @@ dependencies = [ "docopt 0.6.78 (registry+https://github.com/rust-lang/crates.io-index)", "docopt_macros 0.6.81 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "foxbox_users 0.1.0 (git+https://github.com/fxbox/users.git?rev=d00552c)", + "foxbox_users 0.1.0 (git+https://github.com/fxbox/users.git?rev=80bf99f)", "get_if_addrs 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "iron 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -18,12 +18,12 @@ dependencies = [ "multicast_dns 0.1.0 (git+https://github.com/fxbox/multicast-dns.git?rev=0f211f0)", "router 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", "stainless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "staticfile 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.4.5 (git+https://github.com/housleyjk/ws-rs.git?rev=d154fc5)", ] @@ -76,8 +76,8 @@ name = "clippy" version = "0.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex-syntax 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -105,7 +105,7 @@ name = "docopt" version = "0.6.78" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -124,7 +124,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -139,22 +139,22 @@ dependencies = [ [[package]] name = "foxbox_users" version = "0.1.0" -source = "git+https://github.com/fxbox/users.git?rev=d00552c#d00552c48e0d7406cd70666097ec87aa26a87ec6" +source = "git+https://github.com/fxbox/users.git?rev=80bf99f#80bf99fbf9e7a4b0647608a8164ec6a73b9a6bc0" dependencies = [ "iron 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "jwt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "router 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rusqlite 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gcc" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -198,14 +198,14 @@ dependencies = [ "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -225,7 +225,7 @@ dependencies = [ "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -295,7 +295,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -325,7 +325,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -337,7 +337,7 @@ dependencies = [ "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.5.0-pre (git+https://github.com/carllerche/nix-rust?rev=c4257f8a76)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", @@ -350,7 +350,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -379,7 +379,7 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -400,7 +400,7 @@ dependencies = [ [[package]] name = "nom" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -414,12 +414,10 @@ dependencies = [ [[package]] name = "num_cpus" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -428,7 +426,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -443,7 +441,7 @@ dependencies = [ "gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -452,14 +450,14 @@ name = "openssl-sys-extras" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pkg-config" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -509,18 +507,18 @@ dependencies = [ [[package]] name = "regex" -version = "0.1.51" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -553,7 +551,7 @@ name = "rust-crypto" version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -567,7 +565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc_version" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", @@ -580,10 +578,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "semver" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nom 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -593,7 +591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "0.6.13" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -615,7 +613,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -713,10 +711,10 @@ dependencies = [ [[package]] name = "unicase" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc_version 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5b973111..d3c5d444 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,12 +4,16 @@ version = "0.1.0" authors = ["fabrice "] build = "build.rs" +[features] +default = ["authentication"] +authentication = [] + [dependencies] clippy = "0.0.44" docopt = "0.6.78" docopt_macros = "0.6.80" env_logger = "0.3.2" -foxbox_users = { git = "https://github.com/fxbox/users.git", rev = "d00552c" } +foxbox_users = { git = "https://github.com/fxbox/users.git", rev = "80bf99f" } get_if_addrs = "0.3.1" hyper = "0.7.2" multicast_dns = { git = "https://github.com/fxbox/multicast-dns.git", rev = "0f211f0" } @@ -24,7 +28,7 @@ serde = "0.6.13" serde_json = "0.6.0" serde_macros = "0.6.14" staticfile = "0.1.0" -unicase = "1.2.1" +unicase = "1.3.0" uuid = "0.1.18" ws = { git = "https://github.com/housleyjk/ws-rs.git", rev = "d154fc5" } diff --git a/README.md b/README.md index c13f0ede..3ac0e3ea 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,15 @@ Alternatively you can build the app without running it via: $ cargo build ``` +## Build time options +### Disable authentication +You may want to disable endpoints authentication to ease your development process. You can do that by removing `authentication` from the `default` feature in the `Cargo.toml` file. + +```conf +[features] +default = [] +authentication = [] +``` ## Rust tests diff --git a/src/service_router.rs b/src/service_router.rs index 20abcd72..f951df98 100644 --- a/src/service_router.rs +++ b/src/service_router.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use controller::Controller; +use foxbox_users::auth_middleware::{ AuthEndpoint, AuthMiddleware }; use iron::{ AfterMiddleware, headers, IronResult, Request, Response }; use iron::headers::ContentType; use iron::method::Method; @@ -70,6 +71,7 @@ impl AfterMiddleware for CORS { res.headers.set(headers::AccessControlAllowHeaders( vec![ UniCase(String::from("accept")), + UniCase(String::from("authorization")), UniCase(String::from("content-type")) ] )); @@ -98,13 +100,34 @@ pub fn create(controller: T) -> Chain { let c2 = controller.clone(); router.any(":service/:command", move |req: &mut Request| -> IronResult { - // Call a function on a service. - let id = req.extensions.get::().unwrap() - .find("service").unwrap_or("").to_owned(); - c2.dispatch_service_request(id, req) + match req.method { + Method::Get | + Method::Post | + Method::Put => { + // Call a function on a service. + let id = req.extensions.get::().unwrap() + .find("service").unwrap_or("").to_owned(); + c2.dispatch_service_request(id, req) + }, + _ => Ok(Response::with(Status::NotImplemented)) + } }); + let auth_endpoints = if cfg!(feature = "authentication") { + vec![ + AuthEndpoint(vec![Method::Get], "list.json".to_owned()), + AuthEndpoint(vec![Method::Get, Method::Post, Method::Put], + ":service/:command".to_owned()) + ] + } else { + vec![] + }; + let mut chain = Chain::new(router); + chain.around(AuthMiddleware { + auth_endpoints: auth_endpoints + }); + chain.link_after(CORS); chain @@ -113,23 +136,63 @@ pub fn create(controller: T) -> Chain { #[cfg(test)] describe! service_router { before_each { - use iron::Headers; use controller::FoxBox; + use foxbox_users::users_router::UsersRouter; + use iron::Headers; use iron_test::request; + use mount::Mount; let controller = FoxBox::new(false, Some("localhost".to_owned()), None, None); let service_router = create(controller.clone()); + + let mut mount = Mount::new(); + mount.mount("", service_router) + .mount("/users", UsersRouter::init()); } describe! services { before_each { + extern crate serde_json; + + use foxbox_users::users_db::{ UserBuilder, UsersDb }; + use iron::headers::{ Authorization, Basic, Bearer }; use iron_test::response; + + let db = UsersDb::new(); + db.clear().ok(); + let user = UserBuilder::new() + .id(1).name(String::from("username")) + .password(String::from("password")) + .email(String::from("username@example.com")) + .finalize().unwrap(); + db.create(&user).ok(); + let mut headers = Headers::new(); + headers.set(Authorization(Basic { + username: "username".to_owned(), + password: Some("password".to_owned()) + })); + let response = request::post("http://localhost:3000/users/login", + headers, + "{}", + &mount).unwrap(); + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Token { + session_token: String + }; + + let result: Token = serde_json::from_str( + &response::extract_body_to_string(response) + ).unwrap(); + let mut auth_header = Headers::new(); + auth_header.set(Authorization(Bearer { + token: result.session_token + })); } it "should create list.json" { let response = request::get("http://localhost:3000/list.json", - Headers::new(), - &service_router).unwrap(); + auth_header, + &mount).unwrap(); let result = response::extract_body_to_string(response); assert_eq!(result, "[]"); @@ -140,8 +203,8 @@ describe! service_router { use stubs::service::ServiceStub; controller.add_service(Box::new(ServiceStub)); let response = request::get("http://localhost:3000/1/a-command", - Headers::new(), - &service_router).unwrap(); + auth_header, + &mount).unwrap(); let result = response::extract_body_to_string(response); assert_eq!(result, "request processed"); @@ -149,8 +212,8 @@ describe! service_router { it "should return an error if no service was found" { let response = request::get("http://localhost:3000/unknown-id/a-command", - Headers::new(), - &service_router).unwrap(); + auth_header, + &mount).unwrap(); let result = response::extract_body_to_string(response); assert_eq!(result, "No Such Service: unknown-id"); @@ -168,9 +231,7 @@ describe! service_router { let (_, path) = *endpoint; let path = "http://localhost:3000/".to_owned() + &(path.replace(":", "foo")); - let response = request::options(&path, - Headers::new(), - &service_router).unwrap(); + let response = request::options(&path, Headers::new(), &mount).unwrap(); let headers = &response.headers; assert!(headers.has::()); assert!(headers.has::());