From d6a1a9b27471d4d861f6c8756860db8d08faa246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sat, 17 Feb 2018 20:47:13 +0100 Subject: [PATCH] Detect device type correctly and shorten return types of functions --- src/api/core/accounts.rs | 21 ++++++++++----------- src/api/core/ciphers.rs | 30 +++++++++++++++--------------- src/api/core/folders.rs | 17 ++++++++--------- src/api/core/mod.rs | 18 +++++++++++------- src/api/core/two_factor.rs | 15 +++++++-------- src/api/identity.rs | 31 ++++++++++++++++++++++++------- src/api/mod.rs | 6 ++++++ 7 files changed, 81 insertions(+), 57 deletions(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index 42c0635..04a590b 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -1,10 +1,9 @@ -use rocket::response::status::BadRequest; - use rocket_contrib::{Json, Value}; use db::DbConn; use db::models::*; +use api::{JsonResult, EmptyResult}; use auth::Headers; use CONFIG; @@ -28,7 +27,7 @@ struct KeysData { } #[post("/accounts/register", data = "")] -fn register(data: Json, conn: DbConn) -> Result<(), BadRequest> { +fn register(data: Json, conn: DbConn) -> EmptyResult { if !CONFIG.signups_allowed { err!(format!("Signups not allowed")) } @@ -62,12 +61,12 @@ fn register(data: Json, conn: DbConn) -> Result<(), BadRequest Result> { +fn profile(headers: Headers) -> JsonResult { Ok(Json(headers.user.to_json())) } #[post("/accounts/keys", data = "")] -fn post_keys(data: Json, headers: Headers, conn: DbConn) -> Result> { +fn post_keys(data: Json, headers: Headers, conn: DbConn) -> JsonResult { let mut user = headers.user; user.private_key = Some(data.encryptedPrivateKey.clone()); @@ -79,7 +78,7 @@ fn post_keys(data: Json, headers: Headers, conn: DbConn) -> Result, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn post_password(data: Json, headers: Headers, conn: DbConn) -> EmptyResult { let key = data["key"].as_str().unwrap(); let password_hash = data["masterPasswordHash"].as_str().unwrap(); let new_password_hash = data["newMasterPasswordHash"].as_str().unwrap(); @@ -98,7 +97,7 @@ fn post_password(data: Json, headers: Headers, conn: DbConn) -> Result<() } #[post("/accounts/security-stamp", data = "")] -fn post_sstamp(data: Json, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn post_sstamp(data: Json, headers: Headers, conn: DbConn) -> EmptyResult { let password_hash = data["masterPasswordHash"].as_str().unwrap(); let mut user = headers.user; @@ -114,7 +113,7 @@ fn post_sstamp(data: Json, headers: Headers, conn: DbConn) -> Result<(), } #[post("/accounts/email-token", data = "")] -fn post_email(data: Json, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn post_email(data: Json, headers: Headers, conn: DbConn) -> EmptyResult { let password_hash = data["masterPasswordHash"].as_str().unwrap(); let new_email = data["newEmail"].as_str().unwrap(); @@ -135,7 +134,7 @@ fn post_email(data: Json, headers: Headers, conn: DbConn) -> Result<(), B } #[post("/accounts/delete", data = "")] -fn delete_account(data: Json, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_account(data: Json, headers: Headers, conn: DbConn) -> EmptyResult { let password_hash = data["masterPasswordHash"].as_str().unwrap(); let user = headers.user; @@ -164,7 +163,7 @@ fn delete_account(data: Json, headers: Headers, conn: DbConn) -> Result<( } #[get("/accounts/revision-date")] -fn revision_date(headers: Headers) -> Result> { +fn revision_date(headers: Headers) -> String { let revision_date = headers.user.updated_at.timestamp(); - Ok(revision_date.to_string()) + revision_date.to_string() } diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index c613937..f00abf8 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -2,7 +2,6 @@ use std::path::Path; use rocket::Data; use rocket::http::ContentType; -use rocket::response::status::BadRequest; use rocket_contrib::{Json, Value}; @@ -17,12 +16,13 @@ use db::models::*; use util; use crypto; +use api::{JsonResult, EmptyResult}; use auth::Headers; use CONFIG; #[get("/sync")] -fn sync(headers: Headers, conn: DbConn) -> Result> { +fn sync(headers: Headers, conn: DbConn) -> JsonResult { let user = &headers.user; let folders = Folder::find_by_user(&user.uuid, &conn); @@ -46,7 +46,7 @@ fn sync(headers: Headers, conn: DbConn) -> Result> { #[get("/ciphers")] -fn get_ciphers(headers: Headers, conn: DbConn) -> Result> { +fn get_ciphers(headers: Headers, conn: DbConn) -> JsonResult { let ciphers = Cipher::find_by_user(&headers.user.uuid, &conn); let ciphers_json: Vec = ciphers.iter().map(|c| c.to_json(&headers.host, &conn)).collect(); @@ -58,7 +58,7 @@ fn get_ciphers(headers: Headers, conn: DbConn) -> Result> } #[get("/ciphers/")] -fn get_cipher(uuid: String, headers: Headers, conn: DbConn) -> Result> { +fn get_cipher(uuid: String, headers: Headers, conn: DbConn) -> JsonResult { let cipher = match Cipher::find_by_uuid(&uuid, &conn) { Some(cipher) => cipher, None => err!("Cipher doesn't exist") @@ -91,7 +91,7 @@ struct CipherData { } #[post("/ciphers", data = "")] -fn post_ciphers(data: Json, headers: Headers, conn: DbConn) -> Result> { +fn post_ciphers(data: Json, headers: Headers, conn: DbConn) -> JsonResult { let user_uuid = headers.user.uuid.clone(); let favorite = data.favorite.unwrap_or(false); let mut cipher = Cipher::new(user_uuid, data.type_, favorite); @@ -102,7 +102,7 @@ fn post_ciphers(data: Json, headers: Headers, conn: DbConn) -> Resul Ok(Json(cipher.to_json(&headers.host, &conn))) } -fn update_cipher_from_data(cipher: &mut Cipher, data: &CipherData, headers: &Headers, conn: &DbConn) -> Result<(), BadRequest> { +fn update_cipher_from_data(cipher: &mut Cipher, data: &CipherData, headers: &Headers, conn: &DbConn) -> EmptyResult { if let Some(ref folder_id) = data.folderId { match Folder::find_by_uuid(folder_id, conn) { Some(folder) => { @@ -183,7 +183,7 @@ fn copy_values(from: &Value, to: &mut Value) -> bool { } #[post("/ciphers/import", data = "")] -fn post_ciphers_import(data: Json, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn post_ciphers_import(data: Json, headers: Headers, conn: DbConn) -> EmptyResult { let folders_value = data["folders"].as_array().unwrap(); let ciphers_value = data["ciphers"].as_array().unwrap(); let relations_value = data["folderRelationships"].as_array().unwrap(); @@ -218,12 +218,12 @@ fn post_ciphers_import(data: Json, headers: Headers, conn: DbConn) -> Res } #[post("/ciphers/", data = "")] -fn post_cipher(uuid: String, data: Json, headers: Headers, conn: DbConn) -> Result> { +fn post_cipher(uuid: String, data: Json, headers: Headers, conn: DbConn) -> JsonResult { put_cipher(uuid, data, headers, conn) } #[put("/ciphers/", data = "")] -fn put_cipher(uuid: String, data: Json, headers: Headers, conn: DbConn) -> Result> { +fn put_cipher(uuid: String, data: Json, headers: Headers, conn: DbConn) -> JsonResult { let mut cipher = match Cipher::find_by_uuid(&uuid, &conn) { Some(cipher) => cipher, None => err!("Cipher doesn't exist") @@ -243,7 +243,7 @@ fn put_cipher(uuid: String, data: Json, headers: Headers, conn: DbCo #[post("/ciphers//attachment", format = "multipart/form-data", data = "")] -fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn) -> Result> { +fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn) -> JsonResult { let cipher = match Cipher::find_by_uuid(&uuid, &conn) { Some(cipher) => cipher, None => err!("Cipher doesn't exist") @@ -282,13 +282,13 @@ fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers } #[post("/ciphers//attachment//delete", data = "<_data>")] -fn delete_attachment_post(uuid: String, attachment_id: String, _data: Json, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_attachment_post(uuid: String, attachment_id: String, _data: Json, headers: Headers, conn: DbConn) -> EmptyResult { // Data contains a json object with the id, but we don't need it delete_attachment(uuid, attachment_id, headers, conn) } #[delete("/ciphers//attachment/")] -fn delete_attachment(uuid: String, attachment_id: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_attachment(uuid: String, attachment_id: String, headers: Headers, conn: DbConn) -> EmptyResult { let attachment = match Attachment::find_by_id(&attachment_id, &conn) { Some(attachment) => attachment, None => err!("Attachment doesn't exist") @@ -314,12 +314,12 @@ fn delete_attachment(uuid: String, attachment_id: String, headers: Headers, conn } #[post("/ciphers//delete")] -fn delete_cipher_post(uuid: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_cipher_post(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { delete_cipher(uuid, headers, conn) } #[delete("/ciphers/")] -fn delete_cipher(uuid: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_cipher(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { let cipher = match Cipher::find_by_uuid(&uuid, &conn) { Some(cipher) => cipher, None => err!("Cipher doesn't exist") @@ -339,7 +339,7 @@ fn delete_cipher(uuid: String, headers: Headers, conn: DbConn) -> Result<(), Bad } #[post("/ciphers/delete", data = "")] -fn delete_all(data: Json, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_all(data: Json, headers: Headers, conn: DbConn) -> EmptyResult { let password_hash = data["masterPasswordHash"].as_str().unwrap(); let user = headers.user; diff --git a/src/api/core/folders.rs b/src/api/core/folders.rs index 73ce71a..d079143 100644 --- a/src/api/core/folders.rs +++ b/src/api/core/folders.rs @@ -1,14 +1,13 @@ -use rocket::response::status::BadRequest; - use rocket_contrib::{Json, Value}; use db::DbConn; use db::models::*; +use api::{JsonResult, EmptyResult}; use auth::Headers; #[get("/folders")] -fn get_folders(headers: Headers, conn: DbConn) -> Result> { +fn get_folders(headers: Headers, conn: DbConn) -> JsonResult { let folders = Folder::find_by_user(&headers.user.uuid, &conn); let folders_json: Vec = folders.iter().map(|c| c.to_json()).collect(); @@ -20,7 +19,7 @@ fn get_folders(headers: Headers, conn: DbConn) -> Result> } #[get("/folders/")] -fn get_folder(uuid: String, headers: Headers, conn: DbConn) -> Result> { +fn get_folder(uuid: String, headers: Headers, conn: DbConn) -> JsonResult { let folder = match Folder::find_by_uuid(&uuid, &conn) { Some(folder) => folder, _ => err!("Invalid folder") @@ -34,7 +33,7 @@ fn get_folder(uuid: String, headers: Headers, conn: DbConn) -> Result, headers: Headers, conn: DbConn) -> Result> { +fn post_folders(data: Json, headers: Headers, conn: DbConn) -> JsonResult { let name = &data["name"].as_str(); if name.is_none() { @@ -49,12 +48,12 @@ fn post_folders(data: Json, headers: Headers, conn: DbConn) -> Result", data = "")] -fn post_folder(uuid: String, data: Json, headers: Headers, conn: DbConn) -> Result> { +fn post_folder(uuid: String, data: Json, headers: Headers, conn: DbConn) -> JsonResult { put_folder(uuid, data, headers, conn) } #[put("/folders/", data = "")] -fn put_folder(uuid: String, data: Json, headers: Headers, conn: DbConn) -> Result> { +fn put_folder(uuid: String, data: Json, headers: Headers, conn: DbConn) -> JsonResult { let mut folder = match Folder::find_by_uuid(&uuid, &conn) { Some(folder) => folder, _ => err!("Invalid folder") @@ -78,13 +77,13 @@ fn put_folder(uuid: String, data: Json, headers: Headers, conn: DbConn) - } #[post("/folders//delete", data = "<_data>")] -fn delete_folder_post(uuid: String, _data: Json, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_folder_post(uuid: String, _data: Json, headers: Headers, conn: DbConn) -> EmptyResult { // Data contains a json object with the id, but we don't need it delete_folder(uuid, headers, conn) } #[delete("/folders/")] -fn delete_folder(uuid: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest> { +fn delete_folder(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { let folder = match Folder::find_by_uuid(&uuid, &conn) { Some(folder) => folder, _ => err!("Invalid folder") diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index f92f31f..e0dfaa1 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -64,18 +64,18 @@ pub fn routes() -> Vec { /// use rocket::Route; -use rocket::response::status::BadRequest; -use rocket_contrib::Json; +use rocket_contrib::{Json, Value}; use db::DbConn; +use api::JsonResult; use auth::Headers; // GET /api/collections?writeOnly=false #[get("/collections")] -fn get_collections() -> Result> { +fn get_collections() -> JsonResult { Ok(Json(json!({ "Data": [], "Object": "list" @@ -84,10 +84,14 @@ fn get_collections() -> Result> { #[put("/devices/identifier//clear-token")] -fn clear_device_token(uuid: String) -> Result> { err!("Not implemented") } +fn clear_device_token(uuid: String, conn: DbConn) -> JsonResult { + err!("Not implemented") +} #[put("/devices/identifier//token")] -fn put_device_token(uuid: String) -> Result> { err!("Not implemented") } +fn put_device_token(uuid: String, conn: DbConn) -> JsonResult { + err!("Not implemented") +} #[derive(Deserialize, Debug)] @@ -98,12 +102,12 @@ struct EquivDomainData { } #[get("/settings/domains")] -fn get_eq_domains() -> Result> { +fn get_eq_domains() -> JsonResult { err!("Not implemented") } #[post("/settings/domains", data = "")] -fn post_eq_domains(data: Json, headers: Headers, conn: DbConn) -> Result> { +fn post_eq_domains(data: Json, headers: Headers, conn: DbConn) -> JsonResult { let excluded_globals = &data.ExcludedGlobalEquivalentDomains; let equivalent_domains = &data.EquivalentDomains; diff --git a/src/api/core/two_factor.rs b/src/api/core/two_factor.rs index e413e56..90320e9 100644 --- a/src/api/core/two_factor.rs +++ b/src/api/core/two_factor.rs @@ -1,5 +1,3 @@ -use rocket::response::status::BadRequest; - use rocket_contrib::{Json, Value}; use data_encoding::BASE32; @@ -9,11 +7,12 @@ use db::DbConn; use util; use crypto; +use api::{JsonResult, EmptyResult}; use auth::Headers; #[get("/two-factor")] -fn get_twofactor(headers: Headers) -> Result> { +fn get_twofactor(headers: Headers) -> JsonResult { let data = if headers.user.totp_secret.is_none() { Value::Null } else { @@ -31,7 +30,7 @@ fn get_twofactor(headers: Headers) -> Result> { } #[post("/two-factor/get-recover", data = "")] -fn get_recover(data: Json, headers: Headers) -> Result> { +fn get_recover(data: Json, headers: Headers) -> JsonResult { let password_hash = data["masterPasswordHash"].as_str().unwrap(); if !headers.user.check_valid_password(password_hash) { @@ -45,7 +44,7 @@ fn get_recover(data: Json, headers: Headers) -> Result, conn: DbConn) -> Result> { +fn recover(data: Json, conn: DbConn) -> JsonResult { println!("{:#?}", data); use db::models::User; @@ -78,7 +77,7 @@ fn recover(data: Json, conn: DbConn) -> Result> { } #[post("/two-factor/get-authenticator", data = "")] -fn generate_authenticator(data: Json, headers: Headers) -> Result> { +fn generate_authenticator(data: Json, headers: Headers) -> JsonResult { let password_hash = data["masterPasswordHash"].as_str().unwrap(); if !headers.user.check_valid_password(password_hash) { @@ -98,7 +97,7 @@ fn generate_authenticator(data: Json, headers: Headers) -> Result, headers: Headers, conn: DbConn) -> Result> { +fn activate_authenticator(data: Json, headers: Headers, conn: DbConn) -> JsonResult { let password_hash = data["masterPasswordHash"].as_str().unwrap(); if !headers.user.check_valid_password(password_hash) { @@ -140,7 +139,7 @@ fn activate_authenticator(data: Json, headers: Headers, conn: DbConn) -> } #[post("/two-factor/disable", data = "")] -fn disable_authenticator(data: Json, headers: Headers, conn: DbConn) -> Result> { +fn disable_authenticator(data: Json, headers: Headers, conn: DbConn) -> JsonResult { let _type = &data["type"]; let password_hash = data["masterPasswordHash"].as_str().unwrap(); diff --git a/src/api/identity.rs b/src/api/identity.rs index 5a57b7c..11d868c 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -1,21 +1,23 @@ use std::collections::HashMap; -use rocket::Route; -use rocket::request::{Form, FormItems, FromForm}; -use rocket::response::status::BadRequest; +use rocket::{Route, Outcome}; +use rocket::request::{self, Request, FromRequest, Form, FormItems, FromForm}; use rocket_contrib::Json; use db::DbConn; use db::models::*; + use util; +use api::{JsonResult, EmptyResult}; + pub fn routes() -> Vec { routes![ login] } #[post("/connect/token", data = "")] -fn login(connect_data: Form, conn: DbConn) -> Result> { +fn login(connect_data: Form, device_type: DeviceType, conn: DbConn) -> JsonResult { let data = connect_data.get(); println!("{:#?}", data); @@ -64,8 +66,7 @@ fn login(connect_data: Form, conn: DbConn) -> Result { (format!("web-{}", user.uuid), String::from("web")) } @@ -110,6 +111,22 @@ fn login(connect_data: Form, conn: DbConn) -> Result FromRequest<'a, 'r> for DeviceType { + type Error = &'static str; + + fn from_request(request: &'a Request<'r>) -> request::Outcome { + let headers = request.headers(); + let type_opt = headers.get_one("Device-Type"); + let type_num = util::parse_option_string(type_opt).unwrap_or(0); + + Outcome::Success(DeviceType(type_num)) + } +} + + #[derive(Debug)] struct ConnectData { grant_type: GrantType, @@ -174,4 +191,4 @@ fn check_values(map: &HashMap, values: &[&str]) -> Result>; +type EmptyResult = Result<(), BadRequest>;