Browse Source

Reorder and merge imports

Signed-off-by: BlackDex <black.dex@gmail.com>
pull/7200/head
BlackDex 2 weeks ago
parent
commit
b3861e8765
No known key found for this signature in database GPG Key ID: 58C80A2AA6C765E1
  1. 2
      rustfmt.toml
  2. 20
      src/api/core/accounts.rs
  3. 8
      src/api/core/ciphers.rs
  4. 40
      src/api/core/mod.rs
  5. 8
      src/api/core/organizations.rs
  6. 4
      src/api/core/public.rs
  7. 3
      src/api/core/two_factor/authenticator.rs
  8. 3
      src/api/core/two_factor/duo.rs
  9. 5
      src/api/core/two_factor/duo_oidc.rs
  10. 3
      src/api/core/two_factor/email.rs
  11. 3
      src/api/core/two_factor/mod.rs
  12. 31
      src/api/core/two_factor/webauthn.rs
  13. 3
      src/api/core/two_factor/yubikey.rs
  14. 10
      src/api/mod.rs
  15. 10
      src/api/notifications.rs
  16. 6
      src/api/web.rs
  17. 34
      src/auth.rs
  18. 2
      src/db/mod.rs
  19. 10
      src/db/models/archive.rs
  20. 25
      src/db/models/attachment.rs
  21. 20
      src/db/models/auth_request.rs
  22. 35
      src/db/models/cipher.rs
  23. 26
      src/db/models/collection.rs
  24. 14
      src/db/models/device.rs
  25. 12
      src/db/models/emergency_access.rs
  26. 15
      src/db/models/event.rs
  27. 15
      src/db/models/favorite.rs
  28. 19
      src/db/models/folder.rs
  29. 18
      src/db/models/group.rs
  30. 17
      src/db/models/org_policy.rs
  31. 36
      src/db/models/organization.rs
  32. 29
      src/db/models/send.rs
  33. 25
      src/db/models/sso_auth.rs
  34. 12
      src/db/models/two_factor.rs
  35. 9
      src/db/models/two_factor_duo_context.rs
  36. 4
      src/db/models/two_factor_incomplete.rs
  37. 14
      src/db/models/user.rs
  38. 3
      src/db/query_logger.rs
  39. 11
      src/error.rs
  40. 9
      src/mail.rs
  41. 11
      src/main.rs
  42. 30
      src/util.rs

2
rustfmt.toml

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

20
src/api/core/accounts.rs

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

8
src/api/core/ciphers.rs

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

40
src/api/core/mod.rs

@ -1,4 +1,6 @@
pub mod accounts; pub mod accounts;
pub mod two_factor;
mod ciphers; mod ciphers;
mod emergency_access; mod emergency_access;
mod events; mod events;
@ -6,15 +8,30 @@ mod folders;
mod organizations; mod organizations;
mod public; mod public;
mod sends; mod sends;
pub mod two_factor;
pub use accounts::purge_auth_requests; pub use accounts::purge_auth_requests;
pub use ciphers::{CipherData, CipherSyncData, CipherSyncType, purge_trashed_ciphers}; pub use ciphers::{CipherData, CipherSyncData, CipherSyncType, purge_trashed_ciphers};
pub use emergency_access::{emergency_notification_reminder_job, emergency_request_timeout_job}; 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 events::{event_cleanup_job, log_event, log_user_event};
use reqwest::Method;
pub use sends::purge_sends; 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> { pub fn routes() -> Vec<Route> {
let mut eq_domains_routes = routes![get_settings_domains, post_settings_domains, put_settings_domains]; let mut eq_domains_routes = routes![get_settings_domains, post_settings_domains, put_settings_domains];
let mut hibp_routes = routes![hibp_breach]; let mut hibp_routes = routes![hibp_breach];
@ -44,25 +61,6 @@ pub fn events_routes() -> Vec<Route> {
routes 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)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GlobalDomain { struct GlobalDomain {

8
src/api/core/organizations.rs

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

4
src/api/core/public.rs

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

3
src/api/core/two_factor/authenticator.rs

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

3
src/api/core/two_factor/duo.rs

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

5
src/api/core/two_factor/duo_oidc.rs

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

3
src/api/core/two_factor/email.rs

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

3
src/api/core/two_factor/mod.rs

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

31
src/api/core/two_factor/webauthn.rs

@ -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::{ use crate::{
CONFIG, CONFIG,
api::{ api::{
@ -13,21 +29,6 @@ use crate::{
error::Error, error::Error,
util::NumberOrString, 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(|| { static WEBAUTHN: LazyLock<Webauthn> = LazyLock::new(|| {
let domain = CONFIG.domain(); let domain = CONFIG.domain();

3
src/api/core/two_factor/yubikey.rs

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

10
src/api/mod.rs

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

10
src/api/notifications.rs

@ -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(|| { pub static WS_USERS: LazyLock<Arc<WebSocketUsers>> = LazyLock::new(|| {
Arc::new(WebSocketUsers { Arc::new(WebSocketUsers {
map: Arc::new(dashmap::DashMap::new()), 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()); static NOTIFICATIONS_DISABLED: LazyLock<bool> = LazyLock::new(|| !CONFIG.enable_websocket() && !CONFIG.push_enabled());
pub fn routes() -> Vec<Route> { pub fn routes() -> Vec<Route> {

6
src/api/web.rs

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

34
src/auth.rs

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

2
src/db/mod.rs

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

10
src/db/models/archive.rs

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

25
src/db/models/attachment.rs

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

20
src/db/models/auth_request.rs

@ -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 chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From}; use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*; use diesel::prelude::*;
use macros::UuidFromParam;
use serde_json::Value; 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)] #[derive(Identifiable, Queryable, Insertable, AsChangeset, Deserialize, Serialize)]
#[diesel(table_name = auth_requests)] #[diesel(table_name = auth_requests)]
#[diesel(treat_none_as_null = true)] #[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 { impl AuthRequest {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult { pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
db_run! { conn: db_run! { conn:

35
src/db/models/cipher.rs

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

26
src/db/models/collection.rs

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

14
src/db/models/device.rs

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

12
src/db/models/emergency_access.rs

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

15
src/db/models/event.rs

@ -1,11 +1,18 @@
use chrono::{NaiveDateTime, TimeDelta, Utc}; use chrono::{NaiveDateTime, TimeDelta, Utc};
//use derive_more::{AsRef, Deref, Display, From}; use diesel::prelude::*;
use serde_json::Value; 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 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/ // https://bitwarden.com/help/event-logs/

15
src/db/models/favorite.rs

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

19
src/db/models/folder.rs

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

18
src/db/models/group.rs

@ -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 chrono::{NaiveDateTime, Utc};
use derive_more::{AsRef, Deref, Display, From}; use derive_more::{AsRef, Deref, Display, From};
use diesel::prelude::*; use diesel::prelude::*;
use macros::UuidFromParam;
use serde_json::Value; 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)] #[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = groups)] #[diesel(table_name = groups)]
#[diesel(treat_none_as_null = true)] #[diesel(treat_none_as_null = true)]

17
src/db/models/org_policy.rs

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

36
src/db/models/organization.rs

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

29
src/db/models/send.rs

@ -1,11 +1,19 @@
use chrono::{NaiveDateTime, Utc}; use chrono::{NaiveDateTime, Utc};
use data_encoding::BASE64URL_NOPAD;
use diesel::prelude::*;
use serde_json::Value; 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 super::{OrganizationId, User, UserId};
use crate::db::schema::sends;
use diesel::prelude::*;
use id::SendId; use id::SendId;
#[derive(Identifiable, Queryable, Insertable, AsChangeset)] #[derive(Identifiable, Queryable, Insertable, AsChangeset)]
@ -130,10 +138,6 @@ impl Send {
} }
pub fn to_json(&self) -> Value { 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(); 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 // 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 { 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(); 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 // 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 { impl Send {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult { pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
self.update_users_revision(conn).await; 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> { 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 { let Ok(uuid_vec) = BASE64URL_NOPAD.decode(access_id.as_bytes()) else {
return None; return None;
}; };

25
src/db/models/sso_auth.rs

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

12
src/db/models/two_factor.rs

@ -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 diesel::prelude::*;
use serde_json::Value; use serde_json::Value;
use webauthn_rs::prelude::{Credential, ParsedAttestation}; use webauthn_rs::prelude::{Credential, ParsedAttestation};
use webauthn_rs_core::proto::CredentialV3; use webauthn_rs_core::proto::CredentialV3;
use webauthn_rs_proto::{AttestationFormat, RegisteredExtensions}; 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)] #[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = twofactor)] #[diesel(table_name = twofactor)]
#[diesel(primary_key(uuid))] #[diesel(primary_key(uuid))]

9
src/db/models/two_factor_duo_context.rs

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

4
src/db/models/two_factor_incomplete.rs

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

14
src/db/models/user.rs

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

3
src/db/query_logger.rs

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

11
src/error.rs

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

9
src/mail.rs

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

11
src/main.rs

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

30
src/util.rs

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

Loading…
Cancel
Save