Reorder and merge imports

Signed-off-by: BlackDex <black.dex@gmail.com>
This commit is contained in:
BlackDex 2026-05-08 17:16:47 +02:00
parent 8f7f25fefe
commit af5b795bb0
No known key found for this signature in database
GPG Key ID: 58C80A2AA6C765E1
42 changed files with 329 additions and 295 deletions

View File

@ -1,4 +1,4 @@
edition = "2021"
edition = "2024"
max_width = 120
newline_style = "Unix"
use_small_heuristics = "Off"

View File

@ -1,7 +1,11 @@
use std::collections::HashSet;
use crate::db::DbPool;
use chrono::Utc;
use rocket::{
http::Status,
request::{FromRequest, Outcome, Request},
serde::json::Json,
};
use serde_json::Value;
use crate::{
@ -14,7 +18,7 @@ use crate::{
auth::{ClientHeaders, Headers, decode_delete, decode_invite, decode_verify_email},
crypto,
db::{
DbConn,
DbConn, DbPool,
models::{
AuthRequest, AuthRequestId, Cipher, CipherId, Device, DeviceId, DeviceType, DeviceWithAuthRequest,
EmergencyAccess, EmergencyAccessId, EventType, Folder, FolderId, Invitation, Membership, MembershipId,
@ -25,13 +29,9 @@ use crate::{
util::{NumberOrString, deser_opt_nonempty_str, format_date},
};
use super::ciphers::{CipherData, update_cipher_from_data};
use super::sends::{SendData, update_send_from_data};
use rocket::{
http::Status,
request::{FromRequest, Outcome, Request},
serde::json::Json,
use super::{
ciphers::{CipherData, update_cipher_from_data},
sends::{SendData, update_send_from_data},
};
pub fn routes() -> Vec<rocket::Route> {
@ -1282,8 +1282,6 @@ async fn verify_password(data: Json<SecretVerificationRequest>, headers: Headers
}
async fn update_api_key(data: Json<PasswordOrOtpData>, rotate: bool, headers: Headers, conn: DbConn) -> JsonResult {
use crate::util::format_date;
let data: PasswordOrOtpData = data.into_inner();
let mut user = headers.user;

View File

@ -2,19 +2,18 @@ use std::collections::{HashMap, HashSet};
use chrono::{NaiveDateTime, Utc};
use num_traits::ToPrimitive;
use rocket::fs::TempFile;
use rocket::serde::json::Json;
use rocket::{
Route,
form::{Form, FromForm},
fs::TempFile,
serde::json::Json,
};
use serde_json::Value;
use crate::auth::ClientVersion;
use crate::util::{NumberOrString, deser_opt_nonempty_str, save_temp_file};
use crate::{
CONFIG,
api::{self, EmptyResult, JsonResult, Notify, PasswordOrOtpData, UpdateType, core::log_event},
auth::ClientVersion,
auth::{Headers, OrgIdGuard, OwnerHeaders},
config::PathType,
crypto,
@ -26,6 +25,7 @@ use crate::{
MembershipType, OrgPolicy, OrgPolicyType, OrganizationId, RepromptType, Send, UserId,
},
},
util::{NumberOrString, deser_opt_nonempty_str, save_temp_file},
};
use super::folders::FolderData;

View File

@ -1,4 +1,6 @@
pub mod accounts;
pub mod two_factor;
mod ciphers;
mod emergency_access;
mod events;
@ -6,15 +8,30 @@ mod folders;
mod organizations;
mod public;
mod sends;
pub mod two_factor;
pub use accounts::purge_auth_requests;
pub use ciphers::{CipherData, CipherSyncData, CipherSyncType, purge_trashed_ciphers};
pub use emergency_access::{emergency_notification_reminder_job, emergency_request_timeout_job};
pub use events::{event_cleanup_job, log_event, log_user_event};
use reqwest::Method;
pub use sends::purge_sends;
use reqwest::Method;
use rocket::{Catcher, Route, serde::json::Json, serde::json::Value};
use crate::{
CONFIG,
api::{EmptyResult, JsonResult, Notify, UpdateType},
auth::Headers,
db::{
DbConn,
models::{Membership, MembershipStatus, OrgPolicy, Organization, User},
},
error::Error,
http_client::make_http_request,
mail,
util::{FeatureFlagFilter, parse_experimental_client_feature_flags},
};
pub fn routes() -> Vec<Route> {
let mut eq_domains_routes = routes![get_settings_domains, post_settings_domains, put_settings_domains];
let mut hibp_routes = routes![hibp_breach];
@ -44,25 +61,6 @@ pub fn events_routes() -> Vec<Route> {
routes
}
//
// Move this somewhere else
//
use rocket::{Catcher, Route, serde::json::Json, serde::json::Value};
use crate::{
CONFIG,
api::{EmptyResult, JsonResult, Notify, UpdateType},
auth::Headers,
db::{
DbConn,
models::{Membership, MembershipStatus, OrgPolicy, Organization, User},
},
error::Error,
http_client::make_http_request,
mail,
util::{FeatureFlagFilter, parse_experimental_client_feature_flags},
};
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct GlobalDomain {

View File

@ -1,12 +1,12 @@
use num_traits::FromPrimitive;
use rocket::Route;
use rocket::serde::json::Json;
use serde_json::Value;
use std::collections::{HashMap, HashSet};
use crate::api::admin::FAKE_ADMIN_UUID;
use num_traits::FromPrimitive;
use rocket::{Route, serde::json::Json};
use serde_json::Value;
use crate::{
CONFIG,
api::admin::FAKE_ADMIN_UUID,
api::{
EmptyResult, JsonResult, Notify, PasswordOrOtpData, UpdateType,
core::{CipherSyncData, CipherSyncType, accept_org_invite, log_event, two_factor},

View File

@ -1,3 +1,5 @@
use std::collections::HashSet;
use chrono::Utc;
use rocket::{
Request, Route,
@ -5,8 +7,6 @@ use rocket::{
serde::json::Json,
};
use std::collections::HashSet;
use crate::{
CONFIG,
api::EmptyResult,

View File

@ -1,6 +1,5 @@
use data_encoding::BASE32;
use rocket::Route;
use rocket::serde::json::Json;
use rocket::{Route, serde::json::Json};
use crate::{
api::{EmptyResult, JsonResult, PasswordOrOtpData, core::log_user_event, core::two_factor::generate_recover_code},

View File

@ -1,7 +1,6 @@
use chrono::Utc;
use data_encoding::BASE64;
use rocket::Route;
use rocket::serde::json::Json;
use rocket::{Route, serde::json::Json};
use crate::{
CONFIG,

View File

@ -1,10 +1,12 @@
use std::collections::HashMap;
use chrono::Utc;
use data_encoding::HEXLOWER;
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
use reqwest::{StatusCode, header};
use ring::digest::{Digest, SHA512_256, digest};
use serde::Serialize;
use std::collections::HashMap;
use url::Url;
use crate::{
CONFIG,
@ -17,7 +19,6 @@ use crate::{
error::Error,
http_client::make_http_request,
};
use url::Url;
// The location on this service that Duo should redirect users to. For us, this is a bridge
// built in to the Bitwarden clients.

View File

@ -1,6 +1,5 @@
use chrono::{DateTime, TimeDelta, Utc};
use rocket::Route;
use rocket::serde::json::Json;
use rocket::{Route, serde::json::Json};
use crate::{
CONFIG,

View File

@ -1,8 +1,7 @@
use chrono::{TimeDelta, Utc};
use data_encoding::BASE32;
use num_traits::FromPrimitive;
use rocket::Route;
use rocket::serde::json::Json;
use rocket::{Route, serde::json::Json};
use serde::Deserialize;
use serde_json::Value;

View File

@ -1,3 +1,19 @@
use std::{str::FromStr, sync::LazyLock, time::Duration};
use rocket::{Route, serde::json::Json};
use serde_json::Value;
use url::Url;
use uuid::Uuid;
use webauthn_rs::{
Webauthn, WebauthnBuilder,
prelude::{Base64UrlSafeData, Credential, Passkey, PasskeyAuthentication, PasskeyRegistration},
};
use webauthn_rs_proto::{
AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponseRaw, AuthenticatorAttestationResponseRaw,
PublicKeyCredential, RegisterPublicKeyCredential, RegistrationExtensionsClientOutputs,
RequestAuthenticationExtensions, UserVerificationPolicy,
};
use crate::{
CONFIG,
api::{
@ -13,21 +29,6 @@ use crate::{
error::Error,
util::NumberOrString,
};
use rocket::Route;
use rocket::serde::json::Json;
use serde_json::Value;
use std::str::FromStr;
use std::sync::LazyLock;
use std::time::Duration;
use url::Url;
use uuid::Uuid;
use webauthn_rs::prelude::{Base64UrlSafeData, Credential, Passkey, PasskeyAuthentication, PasskeyRegistration};
use webauthn_rs::{Webauthn, WebauthnBuilder};
use webauthn_rs_proto::{
AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponseRaw, AuthenticatorAttestationResponseRaw,
PublicKeyCredential, RegisterPublicKeyCredential, RegistrationExtensionsClientOutputs,
RequestAuthenticationExtensions, UserVerificationPolicy,
};
static WEBAUTHN: LazyLock<Webauthn> = LazyLock::new(|| {
let domain = CONFIG.domain();

View File

@ -1,5 +1,4 @@
use rocket::Route;
use rocket::serde::json::Json;
use rocket::{Route, serde::json::Json};
use serde_json::Value;
use yubico::{config::Config, verify_async};

View File

@ -9,7 +9,6 @@ mod web;
use rocket::serde::json::Json;
use serde_json::Value;
use crate::CONFIG;
pub use crate::api::{
admin::catchers as admin_catchers,
admin::routes as admin_routes,
@ -33,9 +32,12 @@ pub use crate::api::{
web::routes as web_routes,
web::static_files,
};
use crate::db::{
DbConn,
models::{OrgPolicy, OrgPolicyType, User},
use crate::{
CONFIG,
db::{
DbConn,
models::{OrgPolicy, OrgPolicyType, User},
},
};
// Type aliases for API methods results

View File

@ -19,6 +19,11 @@ use crate::{
},
};
use super::{
push::push_auth_request, push::push_auth_response, push_cipher_update, push_folder_update, push_logout,
push_send_update, push_user_update,
};
pub static WS_USERS: LazyLock<Arc<WebSocketUsers>> = LazyLock::new(|| {
Arc::new(WebSocketUsers {
map: Arc::new(dashmap::DashMap::new()),
@ -31,11 +36,6 @@ pub static WS_ANONYMOUS_SUBSCRIPTIONS: LazyLock<Arc<AnonymousWebSocketSubscripti
})
});
use super::{
push::push_auth_request, push::push_auth_response, push_cipher_update, push_folder_update, push_logout,
push_send_update, push_user_update,
};
static NOTIFICATIONS_DISABLED: LazyLock<bool> = LazyLock::new(|| !CONFIG.enable_websocket() && !CONFIG.push_enabled());
pub fn routes() -> Vec<Route> {

View File

@ -13,7 +13,10 @@ use crate::{
CONFIG,
api::{ApiResult, EmptyResult, core::now},
auth::decode_file_download,
db::models::{AttachmentId, CipherId},
db::{
DbConn,
models::{AttachmentId, CipherId},
},
error::Error,
util::Cached,
};
@ -178,7 +181,6 @@ async fn attachments(cipher_id: CipherId, file_id: AttachmentId, token: String)
}
// We use DbConn here to let the alive healthcheck also verify the database connection.
use crate::db::DbConn;
#[get("/alive")]
fn alive(_conn: DbConn) -> Json<String> {
now()

View File

@ -8,16 +8,24 @@ use chrono::{DateTime, TimeDelta, Utc};
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, errors::ErrorKind};
use num_traits::FromPrimitive;
use openssl::rsa::Rsa;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use serde::{de::DeserializeOwned, ser::Serialize};
use rocket::{
outcome::try_outcome,
request::{FromRequest, Outcome, Request},
};
use crate::{
CONFIG,
api::ApiResult,
config::PathType,
db::models::{
AttachmentId, CipherId, CollectionId, DeviceId, DeviceType, EmergencyAccessId, MembershipId, OrgApiKeyId,
OrganizationId, SendFileId, SendId, UserId,
db::{
DbConn,
models::{
AttachmentId, CipherId, Collection, CollectionId, Device, DeviceId, DeviceType, EmergencyAccessId,
Membership, MembershipId, MembershipStatus, MembershipType, OrgApiKeyId, OrganizationId, SendFileId,
SendId, User, UserId, UserStampException,
},
},
error::Error,
sso,
@ -53,16 +61,16 @@ static PRIVATE_RSA_KEY: OnceLock<EncodingKey> = OnceLock::new();
static PUBLIC_RSA_KEY: OnceLock<DecodingKey> = OnceLock::new();
pub async fn initialize_keys() -> Result<(), Error> {
use std::io::Error;
use std::io::Error as IoError;
let rsa_key_filename = std::path::PathBuf::from(CONFIG.private_rsa_key())
.file_name()
.ok_or_else(|| Error::other("Private RSA key path missing filename"))?
.ok_or_else(|| IoError::other("Private RSA key path missing filename"))?
.to_str()
.ok_or_else(|| Error::other("Private RSA key path filename is not valid UTF-8"))?
.ok_or_else(|| IoError::other("Private RSA key path filename is not valid UTF-8"))?
.to_owned();
let operator = CONFIG.opendal_operator_for_path_type(&PathType::RsaKey).map_err(Error::other)?;
let operator = CONFIG.opendal_operator_for_path_type(&PathType::RsaKey).map_err(IoError::other)?;
let priv_key_buffer = match operator.read(&rsa_key_filename).await {
Ok(buffer) => Some(buffer),
@ -528,16 +536,6 @@ pub fn generate_send_claims(send_id: &SendId, file_id: &SendFileId) -> BasicJwtC
//
// Bearer token authentication
//
use rocket::{
outcome::try_outcome,
request::{FromRequest, Outcome, Request},
};
use crate::db::{
DbConn,
models::{Collection, Device, Membership, MembershipStatus, MembershipType, User, UserStampException},
};
pub struct Host {
pub host: String,
}

View File

@ -10,13 +10,11 @@ use diesel::{
connection::SimpleConnection,
r2d2::{CustomizeConnection, Pool, PooledConnection},
};
use rocket::{
Request,
http::Status,
request::{FromRequest, Outcome},
};
use tokio::{
sync::{Mutex, OwnedSemaphorePermit, Semaphore},
time::timeout,

View File

@ -1,11 +1,13 @@
use chrono::NaiveDateTime;
use diesel::prelude::*;
use crate::{
api::EmptyResult,
db::{DbConn, schema::archives},
error::MapResult,
};
use super::{CipherId, User, UserId};
use crate::api::EmptyResult;
use crate::db::DbConn;
use crate::db::schema::archives;
use crate::error::MapResult;
#[derive(Identifiable, Queryable, Insertable)]
#[diesel(table_name = archives)]

View File

@ -1,13 +1,24 @@
use std::time::Duration;
use bigdecimal::{BigDecimal, ToPrimitive};
use derive_more::{AsRef, Deref, Display};
use diesel::prelude::*;
use serde_json::Value;
use std::time::Duration;
use crate::{
CONFIG,
api::EmptyResult,
auth::{encode_jwt, generate_file_download_claims},
config::PathType,
db::{
DbConn,
schema::{attachments, ciphers},
},
error::MapResult,
};
use macros::IdFromParam;
use super::{CipherId, OrganizationId, UserId};
use crate::db::schema::{attachments, ciphers};
use crate::{CONFIG, config::PathType};
use macros::IdFromParam;
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = attachments)]
@ -67,12 +78,6 @@ impl Attachment {
}
}
use crate::auth::{encode_jwt, generate_file_download_claims};
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
/// Database methods
impl Attachment {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {

View File

@ -1,12 +1,19 @@
use super::{DeviceId, OrganizationId, UserId};
use crate::db::schema::auth_requests;
use crate::{crypto::ct_eq, util::format_date};
use chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use macros::UuidFromParam;
use serde_json::Value;
use crate::{
api::EmptyResult,
crypto::ct_eq,
db::{DbConn, schema::auth_requests},
error::MapResult,
util::format_date,
};
use macros::UuidFromParam;
use super::{DeviceId, OrganizationId, UserId};
#[derive(Identifiable, Queryable, Insertable, AsChangeset, Deserialize, Serialize)]
#[diesel(table_name = auth_requests)]
#[diesel(treat_none_as_null = true)]
@ -74,11 +81,6 @@ impl AuthRequest {
}
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
impl AuthRequest {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
db_run! { conn:

View File

@ -1,22 +1,32 @@
use crate::CONFIG;
use crate::db::schema::{
ciphers, ciphers_collections, collections, collections_groups, folders, folders_ciphers, groups, groups_users,
users_collections, users_organizations,
};
use crate::util::LowerCase;
use std::borrow::Cow;
use chrono::{NaiveDateTime, TimeDelta, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use serde_json::Value;
use crate::{
CONFIG,
api::{
EmptyResult,
core::{CipherData, CipherSyncData, CipherSyncType},
},
db::{
DbConn,
schema::{
ciphers, ciphers_collections, collections, collections_groups, folders, folders_ciphers, groups,
groups_users, users_collections, users_organizations,
},
},
error::MapResult,
util::LowerCase,
};
use macros::UuidFromParam;
use super::{
Archive, Attachment, CollectionCipher, CollectionId, Favorite, FolderCipher, FolderId, Group, Membership,
MembershipStatus, MembershipType, OrganizationId, User, UserId,
};
use crate::api::core::{CipherData, CipherSyncData, CipherSyncType};
use macros::UuidFromParam;
use std::borrow::Cow;
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = ciphers)]
@ -130,11 +140,6 @@ impl Cipher {
}
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
/// Database methods
impl Cipher {
pub async fn to_json(

View File

@ -1,16 +1,25 @@
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use serde_json::Value;
use crate::{
CONFIG,
api::EmptyResult,
db::{
DbConn,
schema::{
ciphers_collections, collections, collections_groups, groups, groups_users, users_collections,
users_organizations,
},
},
error::MapResult,
};
use macros::UuidFromParam;
use super::{
CipherId, CollectionGroup, GroupUser, Membership, MembershipId, MembershipStatus, MembershipType, OrganizationId,
User, UserId,
};
use crate::CONFIG;
use crate::db::schema::{
ciphers_collections, collections, collections_groups, groups, groups_users, users_collections, users_organizations,
};
use diesel::prelude::*;
use macros::UuidFromParam;
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = collections)]
@ -147,11 +156,6 @@ impl Collection {
}
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
/// Database methods
impl Collection {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {

View File

@ -1,18 +1,20 @@
use chrono::{NaiveDateTime, Utc};
use data_encoding::BASE64URL;
use derive_more::{Display, From};
use diesel::prelude::*;
use serde_json::Value;
use super::{AuthRequest, UserId};
use crate::db::schema::devices;
use crate::{
api::EmptyResult,
crypto,
db::{DbConn, schema::devices},
error::MapResult,
util::{format_date, get_uuid},
};
use diesel::prelude::*;
use macros::{IdFromParam, UuidFromParam};
use super::{AuthRequest, UserId};
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = devices)]
#[diesel(treat_none_as_null = true)]
@ -135,10 +137,6 @@ impl DeviceWithAuthRequest {
}
}
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
/// Database methods
impl Device {

View File

@ -1,13 +1,17 @@
use chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use serde_json::Value;
use super::{User, UserId};
use crate::db::schema::emergency_access;
use crate::{api::EmptyResult, db::DbConn, error::MapResult};
use diesel::prelude::*;
use crate::{
api::EmptyResult,
db::{DbConn, schema::emergency_access},
error::MapResult,
};
use macros::UuidFromParam;
use super::{User, UserId};
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = emergency_access)]
#[diesel(treat_none_as_null = true)]

View File

@ -1,11 +1,18 @@
use chrono::{NaiveDateTime, TimeDelta, Utc};
//use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use serde_json::Value;
use crate::{
CONFIG,
api::EmptyResult,
db::{
DbConn,
schema::{event, users_organizations},
},
error::MapResult,
};
use super::{CipherId, CollectionId, GroupId, MembershipId, OrgPolicyId, OrganizationId, UserId};
use crate::db::schema::{event, users_organizations};
use crate::{CONFIG, api::EmptyResult, db::DbConn, error::MapResult};
use diesel::prelude::*;
// https://bitwarden.com/help/event-logs/

View File

@ -1,7 +1,13 @@
use super::{CipherId, User, UserId};
use crate::db::schema::favorites;
use diesel::prelude::*;
use crate::{
api::EmptyResult,
db::{DbConn, schema::favorites},
error::MapResult,
};
use super::{CipherId, User, UserId};
#[derive(Identifiable, Queryable, Insertable)]
#[diesel(table_name = favorites)]
#[diesel(primary_key(user_uuid, cipher_uuid))]
@ -10,11 +16,6 @@ pub struct Favorite {
pub cipher_uuid: CipherId,
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
impl Favorite {
// Returns whether the specified cipher is a favorite of the specified user.
pub async fn is_favorite(cipher_uuid: &CipherId, user_uuid: &UserId, conn: &DbConn) -> bool {

View File

@ -1,12 +1,20 @@
use chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use serde_json::Value;
use super::{CipherId, User, UserId};
use crate::db::schema::{folders, folders_ciphers};
use diesel::prelude::*;
use crate::{
api::EmptyResult,
db::{
DbConn,
schema::{folders, folders_ciphers},
},
error::MapResult,
};
use macros::UuidFromParam;
use super::{CipherId, User, UserId};
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = folders)]
#[diesel(primary_key(uuid))]
@ -62,11 +70,6 @@ impl FolderCipher {
}
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
/// Database methods
impl Folder {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {

View File

@ -1,14 +1,20 @@
use super::{CollectionId, Membership, MembershipId, OrganizationId, User, UserId};
use crate::api::EmptyResult;
use crate::db::DbConn;
use crate::db::schema::{collections, collections_groups, groups, groups_users, users_organizations};
use crate::error::MapResult;
use chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use macros::UuidFromParam;
use serde_json::Value;
use crate::{
api::EmptyResult,
db::{
DbConn,
schema::{collections, collections_groups, groups, groups_users, users_organizations},
},
error::MapResult,
};
use macros::UuidFromParam;
use super::{CollectionId, Membership, MembershipId, OrganizationId, User, UserId};
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = groups)]
#[diesel(treat_none_as_null = true)]

View File

@ -1,14 +1,17 @@
use derive_more::{AsRef, From};
use diesel::prelude::*;
use serde::Deserialize;
use serde_json::Value;
use crate::CONFIG;
use crate::api::EmptyResult;
use crate::api::core::two_factor;
use crate::db::DbConn;
use crate::db::schema::{org_policies, users_organizations};
use crate::error::MapResult;
use diesel::prelude::*;
use crate::{
CONFIG,
api::{EmptyResult, core::two_factor},
db::{
DbConn,
schema::{org_policies, users_organizations},
},
error::MapResult,
};
use super::{Membership, MembershipId, MembershipStatus, MembershipType, OrganizationId, TwoFactor, UserId};

View File

@ -1,24 +1,33 @@
use chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use num_traits::FromPrimitive;
use serde_json::Value;
use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
};
use super::{
CipherId, Collection, CollectionGroup, CollectionId, CollectionUser, Group, GroupId, GroupUser, OrgPolicy,
OrgPolicyType, TwoFactor, User, UserId,
};
use crate::CONFIG;
use crate::db::schema::{
ciphers, ciphers_collections, collections_groups, groups, groups_users, org_policies, organization_api_key,
organizations, users, users_collections, users_organizations,
use chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use num_traits::FromPrimitive;
use serde_json::Value;
use crate::{
CONFIG,
api::EmptyResult,
db::{
DbConn,
schema::{
ciphers, ciphers_collections, collections_groups, groups, groups_users, org_policies, organization_api_key,
organizations, users, users_collections, users_organizations,
},
},
error::MapResult,
};
use macros::UuidFromParam;
use super::{
Cipher, CipherId, Collection, CollectionGroup, CollectionId, CollectionUser, Group, GroupId, GroupUser, OrgPolicy,
OrgPolicyType, TwoFactor, User, UserId,
};
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = organizations)]
#[diesel(treat_none_as_null = true)]
@ -325,11 +334,6 @@ impl OrganizationApiKey {
}
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
/// Database methods
impl Organization {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
@ -373,8 +377,6 @@ impl Organization {
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
use super::{Cipher, Collection};
Cipher::delete_all_by_organization(&self.uuid, conn).await?;
Collection::delete_all_by_organization(&self.uuid, conn).await?;
Membership::delete_all_by_organization(&self.uuid, conn).await?;

View File

@ -1,11 +1,19 @@
use chrono::{NaiveDateTime, Utc};
use data_encoding::BASE64URL_NOPAD;
use diesel::prelude::*;
use serde_json::Value;
use uuid::Uuid;
use crate::{CONFIG, config::PathType, util::LowerCase};
use crate::{
CONFIG,
api::EmptyResult,
config::PathType,
db::{DbConn, schema::sends},
error::MapResult,
util::{LowerCase, NumberOrString, format_date},
};
use super::{OrganizationId, User, UserId};
use crate::db::schema::sends;
use diesel::prelude::*;
use id::SendId;
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
@ -130,10 +138,6 @@ impl Send {
}
pub fn to_json(&self) -> Value {
use crate::util::format_date;
use data_encoding::BASE64URL_NOPAD;
use uuid::Uuid;
let mut data = serde_json::from_str::<LowerCase<Value>>(&self.data).map(|d| d.data).unwrap_or_default();
// Mobile clients expect size to be a string instead of a number
@ -167,8 +171,6 @@ impl Send {
}
pub async fn to_json_access(&self, conn: &DbConn) -> Value {
use crate::util::format_date;
let mut data = serde_json::from_str::<LowerCase<Value>>(&self.data).map(|d| d.data).unwrap_or_default();
// Mobile clients expect size to be a string instead of a number
@ -191,12 +193,6 @@ impl Send {
}
}
use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
use crate::util::NumberOrString;
impl Send {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
self.update_users_revision(conn).await;
@ -273,9 +269,6 @@ impl Send {
}
pub async fn find_by_access_id(access_id: &str, conn: &DbConn) -> Option<Self> {
use data_encoding::BASE64URL_NOPAD;
use uuid::Uuid;
let Ok(uuid_vec) = BASE64URL_NOPAD.decode(access_id.as_bytes()) else {
return None;
};

View File

@ -1,17 +1,20 @@
use chrono::{NaiveDateTime, Utc};
use std::time::Duration;
use crate::api::EmptyResult;
use crate::db::schema::sso_auth;
use crate::db::{DbConn, DbPool};
use crate::error::MapResult;
use crate::sso::{OIDCCode, OIDCCodeChallenge, OIDCIdentifier, OIDCState, SSO_AUTH_EXPIRATION};
use chrono::{NaiveDateTime, Utc};
use diesel::{
deserialize::FromSql,
expression::AsExpression,
prelude::*,
serialize::{Output, ToSql},
sql_types::Text,
};
use diesel::deserialize::FromSql;
use diesel::expression::AsExpression;
use diesel::prelude::*;
use diesel::serialize::{Output, ToSql};
use diesel::sql_types::Text;
use crate::{
api::EmptyResult,
db::{DbConn, DbPool, schema::sso_auth},
error::MapResult,
sso::{OIDCCode, OIDCCodeChallenge, OIDCIdentifier, OIDCState, SSO_AUTH_EXPIRATION},
};
#[derive(AsExpression, Clone, Debug, Serialize, Deserialize, FromSqlRow)]
#[diesel(sql_type = Text)]

View File

@ -1,13 +1,17 @@
use super::UserId;
use crate::api::core::two_factor::webauthn::WebauthnRegistration;
use crate::db::schema::twofactor;
use crate::{api::EmptyResult, db::DbConn, error::MapResult};
use diesel::prelude::*;
use serde_json::Value;
use webauthn_rs::prelude::{Credential, ParsedAttestation};
use webauthn_rs_core::proto::CredentialV3;
use webauthn_rs_proto::{AttestationFormat, RegisteredExtensions};
use crate::{
api::{EmptyResult, core::two_factor::webauthn::WebauthnRegistration},
db::{DbConn, schema::twofactor},
error::MapResult,
};
use super::UserId;
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = twofactor)]
#[diesel(primary_key(uuid))]

View File

@ -1,9 +1,12 @@
use chrono::Utc;
use crate::db::schema::twofactor_duo_ctx;
use crate::{api::EmptyResult, db::DbConn, error::MapResult};
use diesel::prelude::*;
use crate::{
api::EmptyResult,
db::{DbConn, schema::twofactor_duo_ctx},
error::MapResult,
};
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = twofactor_duo_ctx)]
#[diesel(primary_key(state))]

View File

@ -1,6 +1,6 @@
use chrono::{NaiveDateTime, Utc};
use diesel::prelude::*;
use crate::db::schema::twofactor_incomplete;
use crate::{
CONFIG,
api::EmptyResult,
@ -8,10 +8,10 @@ use crate::{
db::{
DbConn,
models::{DeviceId, UserId},
schema::twofactor_incomplete,
},
error::MapResult,
};
use diesel::prelude::*;
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = twofactor_incomplete)]

View File

@ -1,23 +1,27 @@
use crate::db::schema::{invitations, sso_users, twofactor_incomplete, users};
use chrono::{NaiveDateTime, TimeDelta, Utc};
use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*;
use serde_json::Value;
use super::{
Cipher, Device, EmergencyAccess, Favorite, Folder, Membership, MembershipType, TwoFactor, TwoFactorIncomplete,
};
use crate::{
CONFIG,
api::EmptyResult,
crypto,
db::{DbConn, models::DeviceId},
db::{
DbConn,
models::DeviceId,
schema::{invitations, sso_users, twofactor_incomplete, users},
},
error::MapResult,
sso::OIDCIdentifier,
util::{format_date, get_uuid, retry},
};
use macros::UuidFromParam;
use super::{
Cipher, Device, EmergencyAccess, Favorite, Folder, Membership, MembershipType, TwoFactor, TwoFactorIncomplete,
};
#[derive(Identifiable, Queryable, Insertable, AsChangeset, Selectable)]
#[diesel(table_name = users)]
#[diesel(treat_none_as_null = true)]

View File

@ -1,6 +1,7 @@
use diesel::connection::{Instrumentation, InstrumentationEvent};
use std::{cell::RefCell, collections::HashMap, time::Instant};
use diesel::connection::{Instrumentation, InstrumentationEvent};
thread_local! {
static QUERY_PERF_TRACKER: RefCell<HashMap<String, Instant>> = RefCell::new(HashMap::new());
}

View File

@ -1,10 +1,11 @@
//
// Error generator macro
//
use std::error::Error as StdError;
use crate::db::models::EventType;
use crate::http_client::CustomHttpClientError;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use std::error::Error as StdError;
macro_rules! make_error {
( $( $name:ident ( $ty:ty ): $src_fn:expr, $usr_msg_fun:expr ),+ $(,)? ) => {
@ -300,9 +301,11 @@ fn compact_api_error(_: &impl std::any::Any, msg: &str) -> String {
//
use std::io::Cursor;
use rocket::http::{ContentType, Status};
use rocket::request::Request;
use rocket::response::{self, Responder, Response};
use rocket::{
http::{ContentType, Status},
request::Request,
response::{self, Responder, Response},
};
impl Responder<'_, 'static> for Error {
fn respond_to(self, _: &Request<'_>) -> response::Result<'static> {

View File

@ -1,7 +1,6 @@
use chrono::NaiveDateTime;
use percent_encoding::{NON_ALPHANUMERIC, percent_encode};
use std::{env::consts::EXE_SUFFIX, str::FromStr};
use chrono::NaiveDateTime;
use lettre::{
Address, AsyncSendmailTransport, AsyncSmtpTransport, AsyncTransport, Tokio1Executor,
message::{Attachment, Body, Mailbox, Message, MultiPart, SinglePart},
@ -9,6 +8,7 @@ use lettre::{
transport::smtp::client::{Tls, TlsParameters},
transport::smtp::extension::ClientId,
};
use percent_encoding::{NON_ALPHANUMERIC, percent_encode};
use crate::{
CONFIG,
@ -19,6 +19,7 @@ use crate::{
},
db::models::{Device, DeviceType, EmergencyAccessId, MembershipId, OrganizationId, User, UserId},
error::Error,
util::upcase_first,
};
fn sendmail_transport() -> AsyncSendmailTransport<Tokio1Executor> {
@ -505,8 +506,6 @@ pub async fn send_invite_confirmed(address: &str, org_name: &str) -> EmptyResult
}
pub async fn send_new_device_logged_in(address: &str, ip: &str, dt: &NaiveDateTime, device: &Device) -> EmptyResult {
use crate::util::upcase_first;
let fmt = "%A, %B %_d, %Y at %r %Z";
let (subject, body_html, body_text) = get_text(
"email/new_device_logged_in",
@ -530,8 +529,6 @@ pub async fn send_incomplete_2fa_login(
device_name: &str,
device_type: &str,
) -> EmptyResult {
use crate::util::upcase_first;
let fmt = "%A, %B %_d, %Y at %r %Z";
let (subject, body_html, body_text) = get_text(
"email/incomplete_2fa_login",

View File

@ -33,6 +33,7 @@ use std::{
path::Path,
process::exit,
str::FromStr,
sync::{Arc, atomic::Ordering},
thread,
};
@ -44,6 +45,8 @@ use tokio::{
#[cfg(unix)]
use tokio::signal::unix::SignalKind;
use rocket::data::{Limits, ToByteUnit};
#[macro_use]
mod error;
mod api;
@ -59,13 +62,11 @@ mod sso;
mod sso_client;
mod util;
use crate::api::core::two_factor::duo_oidc::purge_duo_contexts;
use crate::api::purge_auth_requests;
use crate::api::{WS_ANONYMOUS_SUBSCRIPTIONS, WS_USERS};
use crate::api::{
WS_ANONYMOUS_SUBSCRIPTIONS, WS_USERS, core::two_factor::duo_oidc::purge_duo_contexts, purge_auth_requests,
};
pub use config::{CONFIG, PathType};
pub use error::{Error, MapResult};
use rocket::data::{Limits, ToByteUnit};
use std::sync::{Arc, atomic::Ordering};
pub use util::is_running_in_container;
#[rocket::main]

View File

@ -1,9 +1,18 @@
//
// Web Headers and caching
//
use std::{collections::HashMap, io::Cursor, path::Path};
use std::{collections::HashMap, env, fmt, io::Cursor, path::Path, str::FromStr};
use chrono::{DateTime, Local, NaiveDateTime, TimeZone};
use num_traits::ToPrimitive;
use tokio::{
runtime::Handle,
time::{Duration, sleep},
};
use serde::de::{self, DeserializeOwned, Deserializer, MapAccess, SeqAccess, Visitor};
use serde_json::Value;
use rocket::{
Data, Orbit, Request, Response, Rocket,
fairing::{Fairing, Info, Kind},
@ -11,11 +20,6 @@ use rocket::{
response::{self, Responder},
};
use tokio::{
runtime::Handle,
time::{Duration, sleep},
};
use crate::{
CONFIG,
config::{PathType, SUPPORTED_FEATURE_FLAGS},
@ -356,9 +360,6 @@ pub fn get_uuid() -> String {
//
// String util methods
//
use std::str::FromStr;
#[inline]
pub fn upcase_first(s: &str) -> String {
let mut c = s.chars();
@ -392,9 +393,6 @@ where
//
// Env methods
//
use std::env;
pub fn get_env_str_value(key: &str) -> Option<String> {
let key_file = format!("{key}_FILE");
let value_from_env = env::var(key);
@ -433,8 +431,6 @@ pub fn get_env_bool(key: &str) -> Option<bool> {
// Date util methods
//
use chrono::{DateTime, Local, NaiveDateTime, TimeZone};
/// Formats a UTC-offset `NaiveDateTime` in the format used by Bitwarden API
/// responses with "date" fields (`CreationDate`, `RevisionDate`, etc.).
pub fn format_date(dt: &NaiveDateTime) -> String {
@ -559,12 +555,6 @@ pub fn get_active_web_release() -> String {
//
// Deserialization methods
//
use std::fmt;
use serde::de::{self, DeserializeOwned, Deserializer, MapAccess, SeqAccess, Visitor};
use serde_json::Value;
pub type JsonMap = serde_json::Map<String, Value>;
#[derive(Serialize, Deserialize)]