vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit d6a1a9b27471d4d861f6c8756860db8d08faa246
parent 0e644d27118d436a59c6a8f72b2e281684dcccb8
Author: Daniel GarcĂ­a <dani-garcia@users.noreply.github.com>
Date:   Sat, 17 Feb 2018 20:47:13 +0100

Detect device type correctly and shorten return types of functions

Diffstat:
Msrc/api/core/accounts.rs | 21++++++++++-----------
Msrc/api/core/ciphers.rs | 30+++++++++++++++---------------
Msrc/api/core/folders.rs | 17++++++++---------
Msrc/api/core/mod.rs | 18+++++++++++-------
Msrc/api/core/two_factor.rs | 15+++++++--------
Msrc/api/identity.rs | 32++++++++++++++++++++++++--------
Msrc/api/mod.rs | 6++++++
7 files changed, 81 insertions(+), 58 deletions(-)

diff --git 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 = "<data>")] -fn register(data: Json<RegisterData>, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn register(data: Json<RegisterData>, conn: DbConn) -> EmptyResult { if !CONFIG.signups_allowed { err!(format!("Signups not allowed")) } @@ -62,12 +61,12 @@ fn register(data: Json<RegisterData>, conn: DbConn) -> Result<(), BadRequest<Jso } #[get("/accounts/profile")] -fn profile(headers: Headers) -> Result<Json, BadRequest<Json>> { +fn profile(headers: Headers) -> JsonResult { Ok(Json(headers.user.to_json())) } #[post("/accounts/keys", data = "<data>")] -fn post_keys(data: Json<KeysData>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn post_keys(data: Json<KeysData>, 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<KeysData>, headers: Headers, conn: DbConn) -> Result<Jso } #[post("/accounts/password", data = "<data>")] -fn post_password(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn post_password(data: Json<Value>, 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<Value>, headers: Headers, conn: DbConn) -> Result<() } #[post("/accounts/security-stamp", data = "<data>")] -fn post_sstamp(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn post_sstamp(data: Json<Value>, 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<Value>, headers: Headers, conn: DbConn) -> Result<(), } #[post("/accounts/email-token", data = "<data>")] -fn post_email(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn post_email(data: Json<Value>, 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<Value>, headers: Headers, conn: DbConn) -> Result<(), B } #[post("/accounts/delete", data = "<data>")] -fn delete_account(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn delete_account(data: Json<Value>, 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<Value>, headers: Headers, conn: DbConn) -> Result<( } #[get("/accounts/revision-date")] -fn revision_date(headers: Headers) -> Result<String, BadRequest<Json>> { +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 @@ -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<Json, BadRequest<Json>> { +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<Json, BadRequest<Json>> { #[get("/ciphers")] -fn get_ciphers(headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn get_ciphers(headers: Headers, conn: DbConn) -> JsonResult { let ciphers = Cipher::find_by_user(&headers.user.uuid, &conn); let ciphers_json: Vec<Value> = ciphers.iter().map(|c| c.to_json(&headers.host, &conn)).collect(); @@ -58,7 +58,7 @@ fn get_ciphers(headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> } #[get("/ciphers/<uuid>")] -fn get_cipher(uuid: String, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +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 = "<data>")] -fn post_ciphers(data: Json<CipherData>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn post_ciphers(data: Json<CipherData>, 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<CipherData>, 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<Json>> { +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 = "<data>")] -fn post_ciphers_import(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn post_ciphers_import(data: Json<Value>, 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<Value>, headers: Headers, conn: DbConn) -> Res } #[post("/ciphers/<uuid>", data = "<data>")] -fn post_cipher(uuid: String, data: Json<CipherData>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn post_cipher(uuid: String, data: Json<CipherData>, headers: Headers, conn: DbConn) -> JsonResult { put_cipher(uuid, data, headers, conn) } #[put("/ciphers/<uuid>", data = "<data>")] -fn put_cipher(uuid: String, data: Json<CipherData>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn put_cipher(uuid: String, data: Json<CipherData>, 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<CipherData>, headers: Headers, conn: DbCo #[post("/ciphers/<uuid>/attachment", format = "multipart/form-data", data = "<data>")] -fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +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/<uuid>/attachment/<attachment_id>/delete", data = "<_data>")] -fn delete_attachment_post(uuid: String, attachment_id: String, _data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn delete_attachment_post(uuid: String, attachment_id: String, _data: Json<Value>, 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/<uuid>/attachment/<attachment_id>")] -fn delete_attachment(uuid: String, attachment_id: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +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/<uuid>/delete")] -fn delete_cipher_post(uuid: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn delete_cipher_post(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { delete_cipher(uuid, headers, conn) } #[delete("/ciphers/<uuid>")] -fn delete_cipher(uuid: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +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 = "<data>")] -fn delete_all(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn delete_all(data: Json<Value>, 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 @@ -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<Json, BadRequest<Json>> { +fn get_folders(headers: Headers, conn: DbConn) -> JsonResult { let folders = Folder::find_by_user(&headers.user.uuid, &conn); let folders_json: Vec<Value> = folders.iter().map(|c| c.to_json()).collect(); @@ -20,7 +19,7 @@ fn get_folders(headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> } #[get("/folders/<uuid>")] -fn get_folder(uuid: String, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +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<Json, BadR } #[post("/folders", data = "<data>")] -fn post_folders(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn post_folders(data: Json<Value>, headers: Headers, conn: DbConn) -> JsonResult { let name = &data["name"].as_str(); if name.is_none() { @@ -49,12 +48,12 @@ fn post_folders(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<Jso } #[post("/folders/<uuid>", data = "<data>")] -fn post_folder(uuid: String, data: Json<Value>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn post_folder(uuid: String, data: Json<Value>, headers: Headers, conn: DbConn) -> JsonResult { put_folder(uuid, data, headers, conn) } #[put("/folders/<uuid>", data = "<data>")] -fn put_folder(uuid: String, data: Json<Value>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn put_folder(uuid: String, data: Json<Value>, 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<Value>, headers: Headers, conn: DbConn) - } #[post("/folders/<uuid>/delete", data = "<_data>")] -fn delete_folder_post(uuid: String, _data: Json<Value>, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +fn delete_folder_post(uuid: String, _data: Json<Value>, 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/<uuid>")] -fn delete_folder(uuid: String, headers: Headers, conn: DbConn) -> Result<(), BadRequest<Json>> { +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 @@ -64,18 +64,18 @@ pub fn routes() -> Vec<Route> { /// 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<Json, BadRequest<Json>> { +fn get_collections() -> JsonResult { Ok(Json(json!({ "Data": [], "Object": "list" @@ -84,10 +84,14 @@ fn get_collections() -> Result<Json, BadRequest<Json>> { #[put("/devices/identifier/<uuid>/clear-token")] -fn clear_device_token(uuid: String) -> Result<Json, BadRequest<Json>> { err!("Not implemented") } +fn clear_device_token(uuid: String, conn: DbConn) -> JsonResult { + err!("Not implemented") +} #[put("/devices/identifier/<uuid>/token")] -fn put_device_token(uuid: String) -> Result<Json, BadRequest<Json>> { 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<Json, BadRequest<Json>> { +fn get_eq_domains() -> JsonResult { err!("Not implemented") } #[post("/settings/domains", data = "<data>")] -fn post_eq_domains(data: Json<EquivDomainData>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn post_eq_domains(data: Json<EquivDomainData>, 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 @@ -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<Json, BadRequest<Json>> { +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<Json, BadRequest<Json>> { } #[post("/two-factor/get-recover", data = "<data>")] -fn get_recover(data: Json<Value>, headers: Headers) -> Result<Json, BadRequest<Json>> { +fn get_recover(data: Json<Value>, 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<Value>, headers: Headers) -> Result<Json, BadRequest<J } #[post("/two-factor/recover", data = "<data>")] -fn recover(data: Json<Value>, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn recover(data: Json<Value>, conn: DbConn) -> JsonResult { println!("{:#?}", data); use db::models::User; @@ -78,7 +77,7 @@ fn recover(data: Json<Value>, conn: DbConn) -> Result<Json, BadRequest<Json>> { } #[post("/two-factor/get-authenticator", data = "<data>")] -fn generate_authenticator(data: Json<Value>, headers: Headers) -> Result<Json, BadRequest<Json>> { +fn generate_authenticator(data: Json<Value>, 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<Value>, headers: Headers) -> Result<Json, B } #[post("/two-factor/authenticator", data = "<data>")] -fn activate_authenticator(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn activate_authenticator(data: Json<Value>, 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<Value>, headers: Headers, conn: DbConn) -> } #[post("/two-factor/disable", data = "<data>")] -fn disable_authenticator(data: Json<Value>, headers: Headers, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn disable_authenticator(data: Json<Value>, 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 @@ -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<Route> { routes![ login] } #[post("/connect/token", data = "<connect_data>")] -fn login(connect_data: Form<ConnectData>, conn: DbConn) -> Result<Json, BadRequest<Json>> { +fn login(connect_data: Form<ConnectData>, device_type: DeviceType, conn: DbConn) -> JsonResult { let data = connect_data.get(); println!("{:#?}", data); @@ -64,8 +66,7 @@ fn login(connect_data: Form<ConnectData>, conn: DbConn) -> Result<Json, BadReque } // Let's only use the header and ignore the 'devicetype' parameter - // TODO Get header Device-Type - let device_type_num = 0;// headers.device_type; + let device_type_num = device_type.0; let (device_id, device_name) = match data.is_device { false => { (format!("web-{}", user.uuid), String::from("web")) } @@ -110,6 +111,22 @@ fn login(connect_data: Form<ConnectData>, conn: DbConn) -> Result<Json, BadReque }))) } + +struct DeviceType(i32); + +impl<'a, 'r> FromRequest<'a, 'r> for DeviceType { + type Error = &'static str; + + fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> { + 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<String, String>, values: &[&str]) -> Result<bool, } } Ok(true) -} -\ No newline at end of file +} diff --git a/src/api/mod.rs b/src/api/mod.rs @@ -7,3 +7,9 @@ pub use self::core::routes as core_routes; pub use self::icons::routes as icons_routes; pub use self::identity::routes as identity_routes; pub use self::web::routes as web_routes; + +use rocket::response::status::BadRequest; +use rocket_contrib::Json; + +type JsonResult = Result<Json, BadRequest<Json>>; +type EmptyResult = Result<(), BadRequest<Json>>;