mod.rs (5182B)
1 pub mod accounts; 2 mod ciphers; 3 mod emergency_access; 4 mod events; 5 mod folders; 6 mod organizations; 7 mod public; 8 mod sends; 9 pub mod two_factor; 10 use crate::config as config_file; 11 use crate::error::Error; 12 use crate::util; 13 pub use ciphers::{CipherData, CipherSyncData, CipherSyncType}; 14 pub fn routes() -> Vec<Route> { 15 let mut eq_domains_routes = routes![get_eq_domains, post_eq_domains, put_eq_domains]; 16 let mut hibp_routes = routes![hibp_breach]; 17 let mut meta_routes = routes![alive, config, now, version]; 18 let mut routes = Vec::new(); 19 routes.append(&mut accounts::routes()); 20 routes.append(&mut ciphers::routes()); 21 routes.append(&mut emergency_access::routes()); 22 routes.append(&mut eq_domains_routes); 23 routes.append(&mut events::routes()); 24 routes.append(&mut folders::routes()); 25 routes.append(&mut hibp_routes); 26 routes.append(&mut meta_routes); 27 routes.append(&mut organizations::routes()); 28 routes.append(&mut public::routes()); 29 routes.append(&mut sends::routes()); 30 routes.append(&mut two_factor::routes()); 31 routes 32 } 33 34 pub fn events_routes() -> Vec<Route> { 35 let mut routes = Vec::new(); 36 routes.append(&mut events::main_routes()); 37 routes 38 } 39 40 // 41 // Move this somewhere else 42 // 43 use crate::{api::JsonResult, auth::Headers, db::DbConn}; 44 use rocket::{serde::json::Json, Catcher, Route}; 45 use serde_json::Value; 46 47 #[derive(Serialize, Deserialize)] 48 #[serde(rename_all = "camelCase")] 49 struct GlobalDomain { 50 r#type: i32, 51 domains: Vec<String>, 52 excluded: bool, 53 } 54 55 const GLOBAL_DOMAINS: &str = include_str!("../../static/global_domains.json"); 56 57 #[get("/settings/domains")] 58 fn get_eq_domains(headers: Headers) -> Json<Value> { 59 _get_eq_domains(headers, false) 60 } 61 62 fn _get_eq_domains(headers: Headers, no_excluded: bool) -> Json<Value> { 63 let user = headers.user; 64 use serde_json::from_str; 65 let equivalent_domains: Vec<Vec<String>> = from_str(&user.equivalent_domains).unwrap(); 66 let excluded_globals: Vec<i32> = from_str(&user.excluded_globals).unwrap(); 67 let mut globals: Vec<GlobalDomain> = from_str(GLOBAL_DOMAINS).unwrap(); 68 for global in &mut globals { 69 global.excluded = excluded_globals.contains(&global.r#type); 70 } 71 if no_excluded { 72 globals.retain(|g| !g.excluded); 73 } 74 Json(json!({ 75 "equivalentDomains": equivalent_domains, 76 "globalEquivalentDomains": globals, 77 "object": "domains", 78 })) 79 } 80 81 #[derive(Deserialize)] 82 #[serde(rename_all = "camelCase")] 83 struct EquivDomainData { 84 excluded_global_equivalent_domains: Option<Vec<i32>>, 85 equivalent_domains: Option<Vec<Vec<String>>>, 86 } 87 88 #[post("/settings/domains", data = "<data>")] 89 async fn post_eq_domains( 90 data: Json<EquivDomainData>, 91 headers: Headers, 92 conn: DbConn, 93 ) -> JsonResult { 94 let data: EquivDomainData = data.into_inner(); 95 let excluded_globals = data.excluded_global_equivalent_domains.unwrap_or_default(); 96 let equivalent_domains = data.equivalent_domains.unwrap_or_default(); 97 let mut user = headers.user; 98 use serde_json::to_string; 99 user.excluded_globals = to_string(&excluded_globals).unwrap_or_else(|_| "[]".to_owned()); 100 user.equivalent_domains = to_string(&equivalent_domains).unwrap_or_else(|_| "[]".to_owned()); 101 user.save(&conn).await?; 102 Ok(Json(json!({}))) 103 } 104 105 #[put("/settings/domains", data = "<data>")] 106 async fn put_eq_domains(data: Json<EquivDomainData>, headers: Headers, conn: DbConn) -> JsonResult { 107 post_eq_domains(data, headers, conn).await 108 } 109 #[allow(unused_variables)] 110 #[get("/hibp/breach?<username>")] 111 fn hibp_breach(username: &str) -> Error { 112 Error::empty().with_code(404) 113 } 114 115 #[get("/alive")] 116 fn alive() -> Json<String> { 117 now() 118 } 119 120 #[get("/now")] 121 pub fn now() -> Json<String> { 122 Json(util::format_date(&chrono::Utc::now().naive_utc())) 123 } 124 125 #[get("/version")] 126 const fn version() -> Json<&'static str> { 127 Json(crate::VERSION) 128 } 129 130 #[get("/config")] 131 fn config() -> Json<Value> { 132 let domain = &config_file::get_config().domain_url(); 133 Json(json!({ 134 // Note: The clients use this version to handle backwards compatibility concerns 135 // This means they expect a version that closely matches the Bitwarden server version 136 // We should make sure that we keep this updated when we support the new server features 137 "version": "2024.2.0", 138 "gitHash": "", 139 "server": { 140 "name": "Vaultwarden", 141 "url": "https://github.com/dani-garcia/vaultwarden", 142 }, 143 "environment": { 144 "vault": domain, 145 "api": format!("{domain}/api"), 146 "identity": format!("{domain}/identity"), 147 "notifications": "", 148 "sso": "" 149 }, 150 "featureStates": { 151 "flexible-collections-v-1": false, 152 "key-rotation-improvements": true, 153 }, 154 "object": "config", 155 })) 156 } 157 158 pub fn catchers() -> Vec<Catcher> { 159 catchers![api_not_found] 160 } 161 162 #[catch(404)] 163 fn api_not_found() -> Json<Value> { 164 Json(json!({ 165 "error": { 166 "code": 404i32, 167 "reason": "Not Found", 168 "description": "The requested resource could not be found." 169 } 170 })) 171 }