0
0
Fork 0
mirror of https://github.com/dani-garcia/vaultwarden synced 2024-11-16 15:01:34 +01:00
bitwarden_rs/src/api/core/mod.rs

240 lines
7.4 KiB
Rust
Raw Normal View History

pub mod accounts;
2018-02-10 01:00:55 +01:00
mod ciphers;
2021-07-04 23:02:56 +02:00
mod emergency_access;
mod events;
2018-02-10 01:00:55 +01:00
mod folders;
mod organizations;
mod public;
2021-03-14 23:35:55 +01:00
mod sends;
2021-03-31 22:18:35 +02:00
pub mod two_factor;
2018-02-10 01:00:55 +01:00
2023-08-04 21:12:23 +02:00
pub use accounts::purge_auth_requests;
pub use ciphers::{purge_trashed_ciphers, CipherData, CipherSyncData, CipherSyncType};
pub use emergency_access::{emergency_notification_reminder_job, emergency_request_timeout_job};
pub use events::{event_cleanup_job, log_event, log_user_event};
pub use sends::purge_sends;
2018-02-10 01:00:55 +01:00
pub fn routes() -> Vec<Route> {
let mut eq_domains_routes = routes![get_eq_domains, post_eq_domains, put_eq_domains];
let mut hibp_routes = routes![hibp_breach];
2022-09-08 17:38:00 +02:00
let mut meta_routes = routes![alive, now, version, config];
let mut routes = Vec::new();
routes.append(&mut accounts::routes());
routes.append(&mut ciphers::routes());
2021-07-04 23:02:56 +02:00
routes.append(&mut emergency_access::routes());
routes.append(&mut events::routes());
routes.append(&mut folders::routes());
routes.append(&mut organizations::routes());
routes.append(&mut two_factor::routes());
2021-03-14 23:35:55 +01:00
routes.append(&mut sends::routes());
routes.append(&mut public::routes());
routes.append(&mut eq_domains_routes);
routes.append(&mut hibp_routes);
routes.append(&mut meta_routes);
2018-04-20 18:35:11 +02:00
routes
2018-02-10 01:00:55 +01:00
}
pub fn events_routes() -> Vec<Route> {
let mut routes = Vec::new();
routes.append(&mut events::main_routes());
routes
}
//
// Move this somewhere else
//
use rocket::{serde::json::Json, Catcher, Route};
use serde_json::Value;
2018-02-10 01:00:55 +01:00
use crate::{
api::{JsonResult, JsonUpcase, Notify, UpdateType},
auth::Headers,
db::DbConn,
error::Error,
util::get_reqwest_client,
};
2018-02-10 01:00:55 +01:00
2018-02-17 23:21:04 +01:00
#[derive(Serialize, Deserialize, Debug)]
#[allow(non_snake_case)]
struct GlobalDomain {
Type: i32,
Domains: Vec<String>,
Excluded: bool,
}
const GLOBAL_DOMAINS: &str = include_str!("../../static/global_domains.json");
2018-02-17 23:21:04 +01:00
2018-02-10 01:00:55 +01:00
#[get("/settings/domains")]
2021-03-27 16:07:26 +01:00
fn get_eq_domains(headers: Headers) -> Json<Value> {
_get_eq_domains(headers, false)
}
2021-03-27 16:07:26 +01:00
fn _get_eq_domains(headers: Headers, no_excluded: bool) -> Json<Value> {
2018-02-17 23:21:04 +01:00
let user = headers.user;
use serde_json::from_str;
let equivalent_domains: Vec<Vec<String>> = from_str(&user.equivalent_domains).unwrap();
let excluded_globals: Vec<i32> = from_str(&user.excluded_globals).unwrap();
let mut globals: Vec<GlobalDomain> = from_str(GLOBAL_DOMAINS).unwrap();
for global in &mut globals {
global.Excluded = excluded_globals.contains(&global.Type);
}
if no_excluded {
globals.retain(|g| !g.Excluded);
}
2021-03-27 16:07:26 +01:00
Json(json!({
2018-02-17 23:21:04 +01:00
"EquivalentDomains": equivalent_domains,
2018-02-20 14:09:00 +01:00
"GlobalEquivalentDomains": globals,
"Object": "domains",
2021-03-27 16:07:26 +01:00
}))
2018-02-10 01:00:55 +01:00
}
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct EquivDomainData {
ExcludedGlobalEquivalentDomains: Option<Vec<i32>>,
EquivalentDomains: Option<Vec<Vec<String>>>,
}
#[post("/settings/domains", data = "<data>")]
async fn post_eq_domains(
data: JsonUpcase<EquivDomainData>,
headers: Headers,
mut conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
let data: EquivDomainData = data.into_inner().data;
let excluded_globals = data.ExcludedGlobalEquivalentDomains.unwrap_or_default();
let equivalent_domains = data.EquivalentDomains.unwrap_or_default();
2018-02-17 23:21:04 +01:00
let mut user = headers.user;
use serde_json::to_string;
user.excluded_globals = to_string(&excluded_globals).unwrap_or_else(|_| "[]".to_string());
user.equivalent_domains = to_string(&equivalent_domains).unwrap_or_else(|_| "[]".to_string());
2018-02-17 23:21:04 +01:00
2022-05-20 23:39:47 +02:00
user.save(&mut conn).await?;
nt.send_user_update(UpdateType::SyncSettings, &user).await;
Ok(Json(json!({})))
2018-02-10 01:00:55 +01:00
}
#[put("/settings/domains", data = "<data>")]
async fn put_eq_domains(
data: JsonUpcase<EquivDomainData>,
headers: Headers,
conn: DbConn,
nt: Notify<'_>,
) -> JsonResult {
post_eq_domains(data, headers, conn, nt).await
}
#[get("/hibp/breach?<username>")]
async fn hibp_breach(username: &str) -> JsonResult {
let url = format!(
"https://haveibeenpwned.com/api/v3/breachedaccount/{username}?truncateResponse=false&includeUnverified=false"
);
if let Some(api_key) = crate::CONFIG.hibp_api_key() {
let hibp_client = get_reqwest_client();
let res = hibp_client.get(&url).header("hibp-api-key", api_key).send().await?;
// If we get a 404, return a 404, it means no breached accounts
if res.status() == 404 {
return Err(Error::empty().with_code(404));
}
let value: Value = res.error_for_status()?.json().await?;
Ok(Json(value))
} else {
Ok(Json(json!([{
"Name": "HaveIBeenPwned",
"Title": "Manual HIBP Check",
"Domain": "haveibeenpwned.com",
"BreachDate": "2019-08-18T00:00:00Z",
"AddedDate": "2019-08-18T00:00:00Z",
"Description": format!("Go to: <a href=\"https://haveibeenpwned.com/account/{username}\" target=\"_blank\" rel=\"noreferrer\">https://haveibeenpwned.com/account/{username}</a> for a manual check.<br/><br/>HaveIBeenPwned API key not set!<br/>Go to <a href=\"https://haveibeenpwned.com/API/Key\" target=\"_blank\" rel=\"noreferrer\">https://haveibeenpwned.com/API/Key</a> to purchase an API key from HaveIBeenPwned.<br/><br/>"),
Remove references to "bwrs" #2195 Squashed commit of the following: commit 1bdf1c7954e0731c95703d10118f3874ab5155d3 Merge: 8ba6e61 7257251 Author: Daniel García <dani-garcia@users.noreply.github.com> Date: Sun Jan 23 23:40:17 2022 +0100 Merge branch 'remove-bwrs' of https://github.com/RealOrangeOne/vaultwarden into RealOrangeOne-remove-bwrs commit 7257251ecf23af18deb894e8f2e5519a15360c76 Author: Jake Howard <git@theorangeone.net> Date: Thu Jan 6 17:48:18 2022 +0000 Use `or_else` to save potentially unnecessary function call commit 40ae81dd3c43a596375d5bfdcc00053e786328cc Author: Jake Howard <git@theorangeone.net> Date: Wed Jan 5 21:18:24 2022 +0000 Move $BWRS_VERSION fallback into build.rs commit 743ef74b307a662960f3ca1b9636f3608506516d Author: Jake Howard <git@theorangeone.net> Date: Sat Jan 1 23:08:27 2022 +0000 Revert "Add feature to enable use of `Option::or` in const context" This reverts commit fe8e043b8aaf77c083747bf11760f29b53df0bba. We want to run on stable soon, where these features are not supported commit a1f0da638c8b6ba32209318b105bde1efdd47082 Author: Jake Howard <git@theorangeone.net> Date: Sat Jan 1 13:04:47 2022 +0000 Rename web vault version file https://github.com/dani-garcia/bw_web_builds/pull/58 commit fe8e043b8aaf77c083747bf11760f29b53df0bba Author: Jake Howard <git@theorangeone.net> Date: Sat Jan 1 12:56:44 2022 +0000 Add feature to enable use of `Option::or` in const context commit 687435c8b2b995e90bf6f0ee619bc305e37bc183 Author: Jake Howard <git@theorangeone.net> Date: Sat Jan 1 12:27:28 2022 +0000 Continue to allow using `$BWRS_VERSION` commit 8e2f708e5037db8071251c582ebaf1a97d8e5923 Author: Jake Howard <git@theorangeone.net> Date: Fri Dec 31 11:41:34 2021 +0000 Remove references to "bwrs" The only remaining one is getting the version of the web vault, which requires coordinating with the web vault patching.
2022-01-23 23:40:59 +01:00
"LogoPath": "vw_static/hibp.png",
"PwnCount": 0,
"DataClasses": [
"Error - No API key set!"
]
}])))
}
}
// We use DbConn here to let the alive healthcheck also verify the database connection.
#[get("/alive")]
fn alive(_conn: DbConn) -> Json<String> {
now()
}
#[get("/now")]
pub fn now() -> Json<String> {
Json(crate::util::format_date(&chrono::Utc::now().naive_utc()))
}
#[get("/version")]
fn version() -> Json<&'static str> {
Json(crate::VERSION.unwrap_or_default())
}
2022-09-08 17:38:00 +02:00
#[get("/config")]
fn config() -> Json<Value> {
let domain = crate::CONFIG.domain();
Json(json!({
// Note: The clients use this version to handle backwards compatibility concerns
// This means they expect a version that closely matches the Bitwarden server version
// We should make sure that we keep this updated when we support the new server features
// Version history:
// - Individual cipher key encryption: 2023.9.1
"version": "2023.9.1",
"gitHash": option_env!("GIT_REV"),
2022-09-08 17:38:00 +02:00
"server": {
"name": "Vaultwarden",
"url": "https://github.com/dani-garcia/vaultwarden",
"version": crate::VERSION
2022-09-08 17:38:00 +02:00
},
"environment": {
"vault": domain,
"api": format!("{domain}/api"),
"identity": format!("{domain}/identity"),
"notifications": format!("{domain}/notifications"),
"sso": "",
},
"featureStates": {
// Any feature flags that we want the clients to use
// Can check the enabled ones at:
// https://vault.bitwarden.com/api/config
"fido2-vault-credentials": true, // Passkey support
"autofill-v2": false, // Disabled because it is causing issues https://github.com/dani-garcia/vaultwarden/discussions/4052
},
"object": "config",
2022-09-08 17:38:00 +02:00
}))
}
pub fn catchers() -> Vec<Catcher> {
catchers![api_not_found]
}
#[catch(404)]
fn api_not_found() -> Json<Value> {
Json(json!({
"error": {
"code": 404,
"reason": "Not Found",
"description": "The requested resource could not be found."
}
}))
}