Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2024-05-18 23:10:05 +02:00
clippy and format
Dieser Commit ist enthalten in:
Ursprung
3a66772077
Commit
12bdcd447d
|
@ -669,7 +669,12 @@ async fn get_ntp_time(has_http_access: bool) -> String {
|
|||
}
|
||||
|
||||
#[get("/diagnostics")]
|
||||
async fn diagnostics(_token: AdminToken, ip_header: IpHeader, host_info: HostInfo, mut conn: DbConn) -> ApiResult<Html<String>> {
|
||||
async fn diagnostics(
|
||||
_token: AdminToken,
|
||||
ip_header: IpHeader,
|
||||
host_info: HostInfo,
|
||||
mut conn: DbConn,
|
||||
) -> ApiResult<Html<String>> {
|
||||
use chrono::prelude::*;
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
|
|
|
@ -113,8 +113,15 @@ async fn sync(data: SyncData, headers: Headers, mut conn: DbConn) -> Json<Value>
|
|||
let mut ciphers_json = Vec::with_capacity(ciphers.len());
|
||||
for c in ciphers {
|
||||
ciphers_json.push(
|
||||
c.to_json(&headers.base_url, &headers.user.uuid, Some(&cipher_sync_data), CipherSyncType::User, &mut conn, ())
|
||||
.await,
|
||||
c.to_json(
|
||||
&headers.base_url,
|
||||
&headers.user.uuid,
|
||||
Some(&cipher_sync_data),
|
||||
CipherSyncType::User,
|
||||
&mut conn,
|
||||
(),
|
||||
)
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -160,8 +167,15 @@ async fn get_ciphers(headers: Headers, mut conn: DbConn) -> Json<Value> {
|
|||
let mut ciphers_json = Vec::with_capacity(ciphers.len());
|
||||
for c in ciphers {
|
||||
ciphers_json.push(
|
||||
c.to_json(&headers.base_url, &headers.user.uuid, Some(&cipher_sync_data), CipherSyncType::User, &mut conn, ())
|
||||
.await,
|
||||
c.to_json(
|
||||
&headers.base_url,
|
||||
&headers.user.uuid,
|
||||
Some(&cipher_sync_data),
|
||||
CipherSyncType::User,
|
||||
&mut conn,
|
||||
(),
|
||||
)
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -777,8 +777,9 @@ async fn _get_org_details(org_id: &str, base_url: &str, user_uuid: &str, conn: &
|
|||
|
||||
let mut ciphers_json = Vec::with_capacity(ciphers.len());
|
||||
for c in ciphers {
|
||||
ciphers_json
|
||||
.push(c.to_json(base_url, user_uuid, Some(&cipher_sync_data), CipherSyncType::Organization, conn, ()).await);
|
||||
ciphers_json.push(
|
||||
c.to_json(base_url, user_uuid, Some(&cipher_sync_data), CipherSyncType::Organization, conn, ()).await,
|
||||
);
|
||||
}
|
||||
json!(ciphers_json)
|
||||
}
|
||||
|
|
|
@ -249,7 +249,12 @@ impl From<PublicKeyCredentialCopy> for PublicKeyCredential {
|
|||
}
|
||||
|
||||
#[post("/two-factor/webauthn", data = "<data>")]
|
||||
async fn activate_webauthn(data: JsonUpcase<EnableWebauthnData>, headers: Headers, host_info: HostInfo, mut conn: DbConn) -> JsonResult {
|
||||
async fn activate_webauthn(
|
||||
data: JsonUpcase<EnableWebauthnData>,
|
||||
headers: Headers,
|
||||
host_info: HostInfo,
|
||||
mut conn: DbConn,
|
||||
) -> JsonResult {
|
||||
let data: EnableWebauthnData = data.into_inner().data;
|
||||
let mut user = headers.user;
|
||||
|
||||
|
@ -272,8 +277,11 @@ async fn activate_webauthn(data: JsonUpcase<EnableWebauthnData>, headers: Header
|
|||
};
|
||||
|
||||
// Verify the credentials with the saved state
|
||||
let (credential, _data) =
|
||||
WebauthnConfig::load(&host_info.base_url, &host_info.origin).register_credential(&data.DeviceResponse.into(), &state, |_| Ok(false))?;
|
||||
let (credential, _data) = WebauthnConfig::load(&host_info.base_url, &host_info.origin).register_credential(
|
||||
&data.DeviceResponse.into(),
|
||||
&state,
|
||||
|_| Ok(false),
|
||||
)?;
|
||||
|
||||
let mut registrations: Vec<_> = get_webauthn_registrations(&user.uuid, &mut conn).await?.1;
|
||||
// TODO: Check for repeated ID's
|
||||
|
@ -302,7 +310,12 @@ async fn activate_webauthn(data: JsonUpcase<EnableWebauthnData>, headers: Header
|
|||
}
|
||||
|
||||
#[put("/two-factor/webauthn", data = "<data>")]
|
||||
async fn activate_webauthn_put(data: JsonUpcase<EnableWebauthnData>, headers: Headers, host_info: HostInfo, conn: DbConn) -> JsonResult {
|
||||
async fn activate_webauthn_put(
|
||||
data: JsonUpcase<EnableWebauthnData>,
|
||||
headers: Headers,
|
||||
host_info: HostInfo,
|
||||
conn: DbConn,
|
||||
) -> JsonResult {
|
||||
activate_webauthn(data, headers, host_info, conn).await
|
||||
}
|
||||
|
||||
|
@ -385,7 +398,8 @@ pub async fn generate_webauthn_login(user_uuid: &str, base_url: &str, origin: &s
|
|||
|
||||
// Generate a challenge based on the credentials
|
||||
let ext = RequestAuthenticationExtensions::builder().appid(format!("{}/app-id.json", base_url)).build();
|
||||
let (response, state) = WebauthnConfig::load(base_url, origin).generate_challenge_authenticate_options(creds, Some(ext))?;
|
||||
let (response, state) =
|
||||
WebauthnConfig::load(base_url, origin).generate_challenge_authenticate_options(creds, Some(ext))?;
|
||||
|
||||
// Save the challenge state for later validation
|
||||
TwoFactor::new(user_uuid.into(), TwoFactorType::WebauthnLoginChallenge, serde_json::to_string(&state)?)
|
||||
|
@ -396,7 +410,13 @@ pub async fn generate_webauthn_login(user_uuid: &str, base_url: &str, origin: &s
|
|||
Ok(Json(serde_json::to_value(response.public_key)?))
|
||||
}
|
||||
|
||||
pub async fn validate_webauthn_login(user_uuid: &str, response: &str, base_url: &str, origin: &str, conn: &mut DbConn) -> EmptyResult {
|
||||
pub async fn validate_webauthn_login(
|
||||
user_uuid: &str,
|
||||
response: &str,
|
||||
base_url: &str,
|
||||
origin: &str,
|
||||
conn: &mut DbConn,
|
||||
) -> EmptyResult {
|
||||
let type_ = TwoFactorType::WebauthnLoginChallenge as i32;
|
||||
let state = match TwoFactor::find_by_user_and_type(user_uuid, type_, conn).await {
|
||||
Some(tf) => {
|
||||
|
|
|
@ -28,7 +28,12 @@ pub fn routes() -> Vec<Route> {
|
|||
}
|
||||
|
||||
#[post("/connect/token", data = "<data>")]
|
||||
async fn login(data: Form<ConnectData>, client_header: ClientHeaders, host_info: HostInfo, mut conn: DbConn) -> JsonResult {
|
||||
async fn login(
|
||||
data: Form<ConnectData>,
|
||||
client_header: ClientHeaders,
|
||||
host_info: HostInfo,
|
||||
mut conn: DbConn,
|
||||
) -> JsonResult {
|
||||
let data: ConnectData = data.into_inner();
|
||||
|
||||
let mut user_uuid: Option<String> = None;
|
||||
|
@ -48,7 +53,8 @@ async fn login(data: Form<ConnectData>, client_header: ClientHeaders, host_info:
|
|||
_check_is_some(&data.device_name, "device_name cannot be blank")?;
|
||||
_check_is_some(&data.device_type, "device_type cannot be blank")?;
|
||||
|
||||
_password_login(data, &mut user_uuid, &mut conn, &client_header.ip, &host_info.base_url, &host_info.origin).await
|
||||
_password_login(data, &mut user_uuid, &mut conn, &client_header.ip, &host_info.base_url, &host_info.origin)
|
||||
.await
|
||||
}
|
||||
"client_credentials" => {
|
||||
_check_is_some(&data.client_id, "client_id cannot be blank")?;
|
||||
|
@ -501,7 +507,10 @@ async fn twofactor_auth(
|
|||
|
||||
let twofactor_code = match data.two_factor_token {
|
||||
Some(ref code) => code,
|
||||
None => err_json!(_json_err_twofactor(&twofactor_ids, &user.uuid, base_url, origin, conn).await?, "2FA token not provided"),
|
||||
None => err_json!(
|
||||
_json_err_twofactor(&twofactor_ids, &user.uuid, base_url, origin, conn).await?,
|
||||
"2FA token not provided"
|
||||
),
|
||||
};
|
||||
|
||||
let selected_twofactor = twofactors.into_iter().find(|tf| tf.atype == selected_id && tf.enabled);
|
||||
|
@ -559,7 +568,13 @@ fn _selected_data(tf: Option<TwoFactor>) -> ApiResult<String> {
|
|||
tf.map(|t| t.data).map_res("Two factor doesn't exist")
|
||||
}
|
||||
|
||||
async fn _json_err_twofactor(providers: &[i32], user_uuid: &str, base_url: &str, origin: &str, conn: &mut DbConn) -> ApiResult<Value> {
|
||||
async fn _json_err_twofactor(
|
||||
providers: &[i32],
|
||||
user_uuid: &str,
|
||||
base_url: &str,
|
||||
origin: &str,
|
||||
conn: &mut DbConn,
|
||||
) -> ApiResult<Value> {
|
||||
let mut result = json!({
|
||||
"error" : "invalid_grant",
|
||||
"error_description" : "Two factor required.",
|
||||
|
|
16
src/auth.rs
16
src/auth.rs
|
@ -9,8 +9,8 @@ use openssl::rsa::Rsa;
|
|||
use serde::de::DeserializeOwned;
|
||||
use serde::ser::Serialize;
|
||||
|
||||
use crate::{error::Error, CONFIG};
|
||||
use crate::config::extract_url_origin;
|
||||
use crate::{error::Error, CONFIG};
|
||||
|
||||
const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
|
||||
|
||||
|
@ -394,11 +394,15 @@ impl<'r> FromRequest<'r> for HostInfo {
|
|||
|
||||
// TODO fix error handling
|
||||
// This is probably a 421 misdirected request
|
||||
let (base_url, origin) = CONFIG.host_to_domain(host).and_then(|base_url| {
|
||||
Some((base_url, CONFIG.domain_origin(host)?))
|
||||
}).expect("This should not be merged like this!!!");
|
||||
|
||||
return Outcome::Success(HostInfo { base_url, origin });
|
||||
let (base_url, origin) = CONFIG
|
||||
.host_to_domain(host)
|
||||
.and_then(|base_url| Some((base_url, CONFIG.domain_origin(host)?)))
|
||||
.expect("This should not be merged like this!!!");
|
||||
|
||||
return Outcome::Success(HostInfo {
|
||||
base_url,
|
||||
origin,
|
||||
});
|
||||
} else if let Some(referer) = headers.get_one("Referer") {
|
||||
return Outcome::Success(HostInfo {
|
||||
base_url: referer.to_string(),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{env::consts::EXE_SUFFIX, collections::HashMap};
|
||||
use std::process::exit;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::RwLock;
|
||||
use std::{collections::HashMap, env::consts::EXE_SUFFIX};
|
||||
|
||||
use job_scheduler_ng::Schedule;
|
||||
use once_cell::sync::Lazy;
|
||||
|
@ -1050,7 +1050,7 @@ fn generate_smtp_img_src(embed_images: bool, domains: &str) -> String {
|
|||
if embed_images {
|
||||
"cid:".to_string()
|
||||
} else {
|
||||
let domain = domains.split(',').nth(0).expect("Domain missing");
|
||||
let domain = domains.split(',').next().expect("Domain missing");
|
||||
format!("{domain}/vw_static/")
|
||||
}
|
||||
}
|
||||
|
@ -1288,33 +1288,37 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn get_domain_hostmap(&self, host: &str) -> Option<HostInfo> {
|
||||
// This is done to prevent deadlock, when read-locking an rwlock twice
|
||||
let domains = self.domain_change_back();
|
||||
|
||||
self.inner.read().unwrap().domain_hostmap.get_or_init(|| {
|
||||
domains.split(',')
|
||||
.map(|d| {
|
||||
let host_info = HostInfo {
|
||||
base_url: d.to_string(),
|
||||
origin: extract_url_origin(d),
|
||||
};
|
||||
self.inner
|
||||
.read()
|
||||
.unwrap()
|
||||
.domain_hostmap
|
||||
.get_or_init(|| {
|
||||
domains
|
||||
.split(',')
|
||||
.map(|d| {
|
||||
let host_info = HostInfo {
|
||||
base_url: d.to_string(),
|
||||
origin: extract_url_origin(d),
|
||||
};
|
||||
|
||||
(extract_url_host(d), host_info)
|
||||
})
|
||||
.collect()
|
||||
}).get(host).cloned()
|
||||
(extract_url_host(d), host_info)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.get(host)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn domain_origin(&self, host: &str) -> Option<String> {
|
||||
self.get_domain_hostmap(host)
|
||||
.map(|v| v.origin)
|
||||
self.get_domain_hostmap(host).map(|v| v.origin)
|
||||
}
|
||||
|
||||
pub fn host_to_domain(&self, host: &str) -> Option<String> {
|
||||
self.get_domain_hostmap(host)
|
||||
.map(|v| v.base_url)
|
||||
self.get_domain_hostmap(host).map(|v| v.base_url)
|
||||
}
|
||||
|
||||
// Yes this is a base_url
|
||||
|
|
|
@ -17,7 +17,7 @@ use tokio::{
|
|||
time::{sleep, Duration},
|
||||
};
|
||||
|
||||
use crate::{CONFIG, config::extract_url_host};
|
||||
use crate::{config::extract_url_host, CONFIG};
|
||||
|
||||
pub struct AppHeaders();
|
||||
|
||||
|
|
Laden …
In neuem Issue referenzieren