diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index c89acd2..a2d3815 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -34,10 +34,10 @@ fn register(data: JsonUpcase, conn: DbConn) -> EmptyResult { let data: RegisterData = data.into_inner().data; if !CONFIG.signups_allowed { - err!(format!("Signups not allowed")) + err!("Signups not allowed") } - if let Some(_) = User::find_by_mail(&data.Email, &conn) { + if User::find_by_mail(&data.Email, &conn).is_some() { err!("Email already exists") } @@ -172,17 +172,15 @@ fn delete_account(data: JsonUpcase, headers: Headers, conn: DbConn // Delete ciphers and their attachments for cipher in Cipher::find_owned_by_user(&user.uuid, &conn) { - match cipher.delete(&conn) { - Ok(()) => (), - Err(_) => err!("Failed deleting cipher") + if cipher.delete(&conn).is_err() { + err!("Failed deleting cipher") } } // Delete folders for f in Folder::find_by_user(&user.uuid, &conn) { - match f.delete(&conn) { - Ok(()) => (), - Err(_) => err!("Failed deleting folder") + if f.delete(&conn).is_err() { + err!("Failed deleting folder") } } diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index 8d6dfef..85c8073 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -245,9 +245,9 @@ struct ImportData { #[allow(non_snake_case)] struct RelationsData { // Cipher id - key: u32, + key: usize, // Folder id - value: u32, + value: usize, } @@ -271,17 +271,14 @@ fn post_ciphers_import(data: JsonUpcase, headers: Headers, conn: DbC } // Read and create the ciphers - let mut index = 0; - for cipher_data in data.Ciphers { + for (index, cipher_data) in data.Ciphers.into_iter().enumerate() { let folder_uuid = relations_map.get(&index) - .map(|i| folders[*i as usize].uuid.clone()); + .map(|i| folders[*i].uuid.clone()); let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone()); update_cipher_from_data(&mut cipher, cipher_data, &headers, true, &conn)?; cipher.move_to_folder(folder_uuid, &headers.user.uuid.clone(), &conn).ok(); - - index += 1; } Ok(()) @@ -390,8 +387,8 @@ fn post_cipher_share(uuid: String, data: JsonUpcase, headers: H None => err!("Organization id not provided"), Some(_) => { update_cipher_from_data(&mut cipher, data.Cipher, &headers, true, &conn)?; - for collection in data.CollectionIds.iter() { - match Collection::find_by_uuid(&collection, &conn) { + for uuid in &data.CollectionIds { + match Collection::find_by_uuid(uuid, &conn) { None => err!("Invalid collection ID provided"), Some(collection) => { if collection.is_writable_by_user(&headers.user.uuid, &conn) { @@ -575,17 +572,15 @@ fn delete_all(data: JsonUpcase, headers: Headers, conn: DbConn) -> // Delete ciphers and their attachments for cipher in Cipher::find_owned_by_user(&user.uuid, &conn) { - match cipher.delete(&conn) { - Ok(()) => (), - Err(_) => err!("Failed deleting cipher") + if cipher.delete(&conn).is_err() { + err!("Failed deleting cipher") } } // Delete folders for f in Folder::find_by_user(&user.uuid, &conn) { - match f.delete(&conn) { - Ok(()) => (), - Err(_) => err!("Failed deleting folder") + if f.delete(&conn).is_err() { + err!("Failed deleting folder") } } diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index 99a8a52..4f29a61 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -150,7 +150,7 @@ struct GlobalDomain { Excluded: bool, } -const GLOBAL_DOMAINS: &'static str = include_str!("global_domains.json"); +const GLOBAL_DOMAINS: &str = include_str!("global_domains.json"); #[get("/settings/domains")] fn get_eq_domains(headers: Headers) -> JsonResult { @@ -185,8 +185,8 @@ struct EquivDomainData { fn post_eq_domains(data: JsonUpcase, headers: Headers, conn: DbConn) -> EmptyResult { let data: EquivDomainData = data.into_inner().data; - let excluded_globals = data.ExcludedGlobalEquivalentDomains.unwrap_or(Vec::new()); - let equivalent_domains = data.EquivalentDomains.unwrap_or(Vec::new()); + let excluded_globals = data.ExcludedGlobalEquivalentDomains.unwrap_or_default(); + let equivalent_domains = data.EquivalentDomains.unwrap_or_default(); let mut user = headers.user; use serde_json::to_string; diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 10c9b70..03afff5 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -305,7 +305,7 @@ struct InviteData { fn send_invite(org_id: String, data: JsonUpcase, headers: AdminHeaders, conn: DbConn) -> EmptyResult { let data: InviteData = data.into_inner().data; - let new_type = match UserOrgType::from_str(&data.Type.to_string()) { + let new_type = match UserOrgType::from_str(&data.Type.into_string()) { Some(new_type) => new_type as i32, None => err!("Invalid type") }; @@ -319,9 +319,8 @@ fn send_invite(org_id: String, data: JsonUpcase, headers: AdminHeade match user_opt { None => err!("User email does not exist"), Some(user) => { - match UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &conn) { - Some(_) => err!("User already in organization"), - None => () + if UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &conn).is_some() { + err!("User already in organization") } let mut new_user = UserOrganization::new(user.uuid.clone(), org_id.clone()); @@ -331,13 +330,12 @@ fn send_invite(org_id: String, data: JsonUpcase, headers: AdminHeade // If no accessAll, add the collections received if !access_all { - for col in data.Collections.iter() { + for col in &data.Collections { match Collection::find_by_uuid_and_org(&col.id, &org_id, &conn) { None => err!("Collection not found in Organization"), Some(collection) => { - match CollectionUser::save(&user.uuid, &collection.uuid, col.readOnly, &conn) { - Ok(()) => (), - Err(_) => err!("Failed saving collection access for user") + if CollectionUser::save(&user.uuid, &collection.uuid, col.readOnly, &conn).is_err() { + err!("Failed saving collection access for user") } } } @@ -411,7 +409,7 @@ struct EditUserData { fn edit_user(org_id: String, user_id: String, data: JsonUpcase, headers: AdminHeaders, conn: DbConn) -> EmptyResult { let data: EditUserData = data.into_inner().data; - let new_type = match UserOrgType::from_str(&data.Type.to_string()) { + let new_type = match UserOrgType::from_str(&data.Type.into_string()) { Some(new_type) => new_type as i32, None => err!("Invalid type") }; @@ -449,21 +447,19 @@ fn edit_user(org_id: String, user_id: String, data: JsonUpcase, he // Delete all the odd collections for c in CollectionUser::find_by_organization_and_user_uuid(&org_id, &user_to_edit.user_uuid, &conn) { - match c.delete(&conn) { - Ok(()) => (), - Err(_) => err!("Failed deleting old collection assignment") + if c.delete(&conn).is_err() { + err!("Failed deleting old collection assignment") } } // If no accessAll, add the collections received if !data.AccessAll { - for col in data.Collections.iter() { + for col in &data.Collections { match Collection::find_by_uuid_and_org(&col.id, &org_id, &conn) { None => err!("Collection not found in Organization"), Some(collection) => { - match CollectionUser::save(&user_to_edit.user_uuid, &collection.uuid, col.readOnly, &conn) { - Ok(()) => (), - Err(_) => err!("Failed saving collection access for user") + if CollectionUser::save(&user_to_edit.user_uuid, &collection.uuid, col.readOnly, &conn).is_err() { + err!("Failed saving collection access for user") } } } diff --git a/src/api/core/two_factor.rs b/src/api/core/two_factor.rs index c226519..3ecc48a 100644 --- a/src/api/core/two_factor.rs +++ b/src/api/core/two_factor.rs @@ -111,7 +111,7 @@ fn activate_authenticator(data: JsonUpcase, headers: Header let data: EnableTwoFactorData = data.into_inner().data; let password_hash = data.MasterPasswordHash; let key = data.Key; - let token = match data.Token.to_i32() { + let token = match data.Token.into_i32() { Some(n) => n as u64, None => err!("Malformed token") }; diff --git a/src/api/icons.rs b/src/api/icons.rs index 954a9e5..2ca29fa 100644 --- a/src/api/icons.rs +++ b/src/api/icons.rs @@ -53,16 +53,13 @@ fn get_icon_cached(key: &str, url: &str) -> io::Result> { let path = &format!("{}/{}.png", CONFIG.icon_cache_folder, key); // Try to read the cached icon, and return it if it exists - match File::open(path) { - Ok(mut f) => { - let mut buffer = Vec::new(); + if let Ok(mut f) = File::open(path) { + let mut buffer = Vec::new(); - if f.read_to_end(&mut buffer).is_ok() { - return Ok(buffer); - } - /* If error reading file continue */ + if f.read_to_end(&mut buffer).is_ok() { + return Ok(buffer); } - Err(_) => { /* Continue */ } + /* If error reading file continue */ } println!("Downloading icon for {}...", key); @@ -72,9 +69,8 @@ fn get_icon_cached(key: &str, url: &str) -> io::Result> { }; // Save the currently downloaded icon - match File::create(path) { - Ok(mut f) => { f.write_all(&icon).expect("Error writing icon file"); } - Err(_) => { /* Continue */ } + if let Ok(mut f) = File::create(path) { + f.write_all(&icon).expect("Error writing icon file"); }; Ok(icon) diff --git a/src/api/identity.rs b/src/api/identity.rs index df035e4..4eace64 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -29,7 +29,7 @@ fn login(connect_data: Form, device_type: DeviceType, conn: DbConn) fn _refresh_login(data: &ConnectData, _device_type: DeviceType, conn: DbConn) -> JsonResult { // Extract token - let token = data.get("refresh_token").unwrap(); + let token = data.get("refresh_token"); // Get device by refresh token let mut device = match Device::find_by_refresh_token(token, &conn) { @@ -56,20 +56,20 @@ fn _refresh_login(data: &ConnectData, _device_type: DeviceType, conn: DbConn) -> fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> JsonResult { // Validate scope - let scope = data.get("scope").unwrap(); + let scope = data.get("scope"); if scope != "api offline_access" { err!("Scope not supported") } // Get the user - let username = data.get("username").unwrap(); + let username = data.get("username"); let user = match User::find_by_mail(username, &conn) { Some(user) => user, None => err!("Username or password is incorrect. Try again.") }; // Check password - let password = data.get("password").unwrap(); + let password = data.get("password"); if !user.check_valid_password(password) { err!("Username or password is incorrect. Try again.") } @@ -77,14 +77,13 @@ fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> // Let's only use the header and ignore the 'devicetype' parameter let device_type_num = device_type.0; - let (device_id, device_name) = match data.is_device { - false => { (format!("web-{}", user.uuid), String::from("web")) } - true => { - ( - data.get("deviceidentifier").unwrap().clone(), - data.get("devicename").unwrap().clone(), - ) - } + let (device_id, device_name) = if data.is_device { + ( + data.get("deviceidentifier").clone(), + data.get("devicename").clone(), + ) + } else { + (format!("web-{}", user.uuid), String::from("web")) }; // Find device or create new @@ -105,8 +104,8 @@ fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> }; let twofactor_token = if user.requires_twofactor() { - let twofactor_provider = util::parse_option_string(data.get("twoFactorProvider")).unwrap_or(0); - let twofactor_code = match data.get("twoFactorToken") { + let twofactor_provider = util::parse_option_string(data.get_opt("twoFactorProvider")).unwrap_or(0); + let twofactor_code = match data.get_opt("twoFactorToken") { Some(code) => code, None => err_json!(_json_err_twofactor()) }; @@ -122,7 +121,7 @@ fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> err_json!(_json_err_twofactor()) } - if util::parse_option_string(data.get("twoFactorRemember")).unwrap_or(0) == 1 { + if util::parse_option_string(data.get_opt("twoFactorRemember")).unwrap_or(0) == 1 { device.refresh_twofactor_remember(); device.twofactor_remember.clone() } else { @@ -174,39 +173,7 @@ fn _json_err_twofactor() -> Value { }) } -/* -ConnectData { - grant_type: Password, - is_device: false, - data: { - "scope": "api offline_access", - "client_id": "web", - "grant_type": "password", - "username": "dani@mail", - "password": "8IuV1sJ94tPjyYIK+E+PTjblzjm4W6C4N5wqM0KKsSg=" - } -} - -RETURNS "TwoFactorToken": "11122233333444555666777888999" - -Next login -ConnectData { - grant_type: Password, - is_device: false, - data: { - "scope": "api offline_access", - "username": "dani@mail", - "client_id": "web", - "twofactorprovider": "5", - "twofactortoken": "11122233333444555666777888999", - "grant_type": "password", - "twofactorremember": "0", - "password": "8IuV1sJ94tPjyYIK+E+PTjblzjm4W6C4N5wqM0KKsSg=" - } -} -*/ - - +#[derive(Clone, Copy)] struct DeviceType(i32); impl<'a, 'r> FromRequest<'a, 'r> for DeviceType { @@ -233,7 +200,11 @@ struct ConnectData { enum GrantType { RefreshToken, Password } impl ConnectData { - fn get(&self, key: &str) -> Option<&String> { + fn get(&self, key: &str) -> &String { + &self.data[&key.to_lowercase()] + } + + fn get_opt(&self, key: &str) -> Option<&String> { self.data.get(&key.to_lowercase()) } } @@ -252,7 +223,7 @@ impl<'f> FromForm<'f> for ConnectData { for (key, value) in items { match (key.url_decode(), value.url_decode()) { (Ok(key), Ok(value)) => data.insert(key.to_lowercase(), value), - _ => return Err(format!("Error decoding key or value")), + _ => return Err("Error decoding key or value".to_string()), }; } @@ -266,13 +237,13 @@ impl<'f> FromForm<'f> for ConnectData { Some("password") => { check_values(&data, &VALUES_PASSWORD)?; - let is_device = match data.get("client_id").unwrap().as_ref() { + let is_device = match data["client_id"].as_ref() { "browser" | "mobile" => check_values(&data, &VALUES_DEVICE)?, _ => false }; (GrantType::Password, is_device) } - _ => return Err(format!("Grant type not supported")) + _ => return Err("Grant type not supported".to_string()) }; Ok(ConnectData { grant_type, is_device, data }) diff --git a/src/api/mod.rs b/src/api/mod.rs index f5cc71e..f56e609 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -33,14 +33,14 @@ enum NumberOrString { } impl NumberOrString { - fn to_string(self) -> String { + fn into_string(self) -> String { match self { NumberOrString::Number(n) => n.to_string(), NumberOrString::String(s) => s } } - fn to_i32(self) -> Option { + fn into_i32(self) -> Option { match self { NumberOrString::Number(n) => Some(n), NumberOrString::String(s) => s.parse().ok() diff --git a/src/auth.rs b/src/auth.rs index 211db57..0aa7a68 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -11,7 +11,8 @@ use serde::ser::Serialize; use CONFIG; const JWT_ALGORITHM: jwt::Algorithm = jwt::Algorithm::RS256; -pub const JWT_ISSUER: &'static str = "localhost:8000/identity"; + // TODO: This isn't used, but we should make sure it represents the correct address +pub const JWT_ISSUER: &str = "localhost:8000/identity"; lazy_static! { pub static ref DEFAULT_VALIDITY: Duration = Duration::hours(2); @@ -30,9 +31,9 @@ lazy_static! { pub fn encode_jwt(claims: &T) -> String { match jwt::encode(&JWT_HEADER, claims, &PRIVATE_RSA_KEY) { - Ok(token) => return token, + Ok(token) => token, Err(e) => panic!("Error encoding jwt {}", e) - }; + } } pub fn decode_jwt(token: &str) -> Result { diff --git a/src/util.rs b/src/util.rs index 7c9ea45..aaaecfe 100644 --- a/src/util.rs +++ b/src/util.rs @@ -70,7 +70,7 @@ pub fn delete_file(path: &str) -> bool { } -const UNITS: [&'static str; 6] = ["bytes", "KB", "MB", "GB", "TB", "PB"]; +const UNITS: [&str; 6] = ["bytes", "KB", "MB", "GB", "TB", "PB"]; pub fn get_display_size(size: i32) -> String { let mut size = size as f64; @@ -119,7 +119,7 @@ pub fn parse_option_string(string: Option) -> Option where S: AsRef< use chrono::NaiveDateTime; -const DATETIME_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%.6fZ"; +const DATETIME_FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.6fZ"; pub fn format_date(date: &NaiveDateTime) -> String { date.format(DATETIME_FORMAT).to_string()