From e683deb74ec48ce49fed2fc5226aafbdbc820257 Mon Sep 17 00:00:00 2001 From: mdecimus Date: Tue, 9 Jul 2024 09:47:51 +0200 Subject: [PATCH] EE code reorganisation --- Cargo.lock | 22 ------- Cargo.toml | 2 - crates/common/Cargo.toml | 3 +- crates/common/src/config/mod.rs | 65 +------------------ crates/common/src/enterprise/config.rs | 64 ++++++++++++++++++ .../src => common/src/enterprise}/license.rs | 0 .../lib.rs => common/src/enterprise/mod.rs} | 27 ++++---- .../src => common/src/enterprise}/undelete.rs | 25 ++----- crates/common/src/lib.rs | 19 +----- crates/jmap/Cargo.toml | 3 +- crates/jmap/src/api/management/enterprise.rs | 2 +- crates/jmap/src/api/management/mod.rs | 3 - crates/jmap/src/auth/oauth/auth.rs | 3 - crates/jmap/src/email/delete.rs | 2 - crates/main/Cargo.toml | 3 +- crates/main/src/main.rs | 2 - crates/se-common/Cargo.toml | 17 ----- crates/se-licensing/Cargo.toml | 13 ---- crates/se-licensing/src/lib.rs | 11 ---- 19 files changed, 94 insertions(+), 192 deletions(-) create mode 100644 crates/common/src/enterprise/config.rs rename crates/{se-licensing/src => common/src/enterprise}/license.rs (100%) rename crates/{se-common/src/lib.rs => common/src/enterprise/mod.rs} (78%) rename crates/{se-common/src => common/src/enterprise}/undelete.rs (87%) delete mode 100644 crates/se-common/Cargo.toml delete mode 100644 crates/se-licensing/Cargo.toml delete mode 100644 crates/se-licensing/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 745568bc..329f4bce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1054,7 +1054,6 @@ dependencies = [ "rustls 0.23.10", "rustls-pemfile 2.1.2", "rustls-pki-types", - "se_licensing", "serde", "serde_json", "sha1", @@ -3180,7 +3179,6 @@ dependencies = [ "reqwest 0.12.5", "rev_lines", "rsa", - "se_common", "sequoia-openpgp", "serde", "serde_json", @@ -3589,7 +3587,6 @@ dependencies = [ "jmap_proto", "managesieve", "pop3", - "se_common", "smtp", "store", "tokio", @@ -5627,25 +5624,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" -[[package]] -name = "se_common" -version = "0.8.5" -dependencies = [ - "common", - "serde", - "store", - "tracing", - "utils", -] - -[[package]] -name = "se_licensing" -version = "0.8.5" -dependencies = [ - "base64 0.22.1", - "ring 0.17.8", -] - [[package]] name = "seahash" version = "4.1.0" diff --git a/Cargo.toml b/Cargo.toml index 066915a1..e1208b2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,6 @@ members = [ "crates/nlp", "crates/store", "crates/directory", - "crates/se-licensing", - "crates/se-common", "crates/utils", "crates/common", "crates/cli", diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 989f4798..8c05a597 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -10,7 +10,6 @@ nlp = { path = "../nlp" } store = { path = "../store" } directory = { path = "../directory" } jmap_proto = { path = "../jmap-proto" } -se_licensing = { path = "../se-licensing", optional = true } sieve-rs = { version = "0.5" } mail-parser = { version = "0.9", features = ["full_encoding", "ludicrous_mode"] } mail-auth = { version = "0.4" } @@ -67,4 +66,4 @@ tracing-journald = "0.3" [features] test_mode = [] -enterprise = ["se_licensing"] +enterprise = [] diff --git a/crates/common/src/config/mod.rs b/crates/common/src/config/mod.rs index 64f707a8..3d9d5829 100644 --- a/crates/common/src/config/mod.rs +++ b/crates/common/src/config/mod.rs @@ -16,13 +16,6 @@ use crate::{ Network, }; -#[cfg(feature = "enterprise")] -use crate::Enterprise; -#[cfg(feature = "enterprise")] -use jmap_proto::types::collection::Collection; -#[cfg(feature = "enterprise")] -use se_licensing::license::LicenseValidator; - use self::{ imap::ImapConfig, jmap::settings::JmapConfig, scripts::Scripting, smtp::SmtpConfig, storage::Storage, @@ -123,60 +116,6 @@ impl Core { .directories .insert("*".to_string(), directory.clone()); - // SPDX-SnippetBegin - // SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd - // SPDX-License-Identifier: LicenseRef-SEL - - #[cfg(feature = "enterprise")] - let enterprise = match config.value("enterprise.license-key").map(|key| { - LicenseValidator::new().try_parse(key).and_then(|key| { - key.into_validated_key(config.value("lookup.default.hostname").unwrap_or_default()) - }) - }) { - Some(Ok(license)) => { - match data - .get_bitmap(store::BitmapKey::document_ids( - u32::MAX, - Collection::Principal, - )) - .await - { - Ok(Some(bitmap)) if bitmap.len() > license.accounts as u64 => { - config.new_build_warning( - "enterprise.license-key", - format!( - "License key is valid but only allows {} accounts, found {}.", - license.accounts, - bitmap.len() - ), - ); - None - } - Err(e) => { - if !matches!(data, Store::None) { - config.new_build_error("enterprise.license-key", e.to_string()); - } - None - } - _ => Some(Enterprise { - license, - undelete_period: config - .property_or_default::>( - "enterprise.undelete-period", - "false", - ) - .unwrap_or_default(), - }), - } - } - Some(Err(e)) => { - config.new_build_warning("enterprise.license-key", e.to_string()); - None - } - None => None, - }; - // SPDX-SnippetEnd - // If any of the stores are missing, disable all stores to avoid data loss if matches!(data, Store::None) || matches!(&blob.backend, BlobBackend::Store(Store::None)) @@ -194,6 +133,8 @@ impl Core { } Self { + #[cfg(feature = "enterprise")] + enterprise: crate::enterprise::Enterprise::parse(config, &data).await, sieve: Scripting::parse(config, &stores).await, network: Network::parse(config), smtp: SmtpConfig::parse(config).await, @@ -215,8 +156,6 @@ impl Core { blobs: stores.blob_stores, ftss: stores.fts_stores, }, - #[cfg(feature = "enterprise")] - enterprise, } } diff --git a/crates/common/src/enterprise/config.rs b/crates/common/src/enterprise/config.rs new file mode 100644 index 00000000..b2b4a576 --- /dev/null +++ b/crates/common/src/enterprise/config.rs @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd + * + * SPDX-License-Identifier: LicenseRef-SEL + * + * This file is subject to the Stalwart Enterprise License Agreement (SEL) and + * is NOT open source software. + * + */ + +use std::time::Duration; + +use jmap_proto::types::collection::Collection; +use store::{BitmapKey, Store}; +use utils::config::Config; + +use super::{license::LicenseValidator, Enterprise}; + +impl Enterprise { + pub async fn parse(config: &mut Config, data: &Store) -> Option { + let license = match LicenseValidator::new() + .try_parse(config.value("enterprise.license-key")?) + .and_then(|key| { + key.into_validated_key(config.value("lookup.default.hostname").unwrap_or_default()) + }) { + Ok(key) => key, + Err(err) => { + config.new_build_warning("enterprise.license-key", err.to_string()); + return None; + } + }; + + match data + .get_bitmap(BitmapKey::document_ids(u32::MAX, Collection::Principal)) + .await + { + Ok(Some(bitmap)) if bitmap.len() > license.accounts as u64 => { + config.new_build_warning( + "enterprise.license-key", + format!( + "License key is valid but only allows {} accounts, found {}.", + license.accounts, + bitmap.len() + ), + ); + return None; + } + Err(e) => { + if !matches!(data, Store::None) { + config.new_build_error("enterprise.license-key", e.to_string()); + } + return None; + } + _ => (), + } + + Some(Enterprise { + license, + undelete_period: config + .property_or_default::>("enterprise.undelete-period", "false") + .unwrap_or_default(), + }) + } +} diff --git a/crates/se-licensing/src/license.rs b/crates/common/src/enterprise/license.rs similarity index 100% rename from crates/se-licensing/src/license.rs rename to crates/common/src/enterprise/license.rs diff --git a/crates/se-common/src/lib.rs b/crates/common/src/enterprise/mod.rs similarity index 78% rename from crates/se-common/src/lib.rs rename to crates/common/src/enterprise/mod.rs index ec6e9e79..08c32041 100644 --- a/crates/se-common/src/lib.rs +++ b/crates/common/src/enterprise/mod.rs @@ -8,18 +8,23 @@ * */ -#[cfg(feature = "enterprise")] +pub mod config; +pub mod license; pub mod undelete; -#[cfg(feature = "enterprise")] -pub trait EnterpriseCore { - fn is_enterprise_edition(&self) -> bool; - fn log_license_details(&self); - fn licensed_accounts(&self) -> u32; +use std::time::Duration; + +use license::LicenseKey; + +use crate::Core; + +#[derive(Clone)] +pub struct Enterprise { + pub license: LicenseKey, + pub undelete_period: Option, } -#[cfg(feature = "enterprise")] -impl EnterpriseCore for common::Core { +impl Core { // WARNING: TAMPERING WITH THIS FUNCTION IS STRICTLY PROHIBITED // Any attempt to modify, bypass, or disable this license validation mechanism // constitutes a severe violation of the Stalwart Enterprise License Agreement. @@ -29,17 +34,17 @@ impl EnterpriseCore for common::Core { // violators to the fullest extent of the law, including but not limited to claims // for copyright infringement, breach of contract, and fraud. - fn is_enterprise_edition(&self) -> bool { + pub fn is_enterprise_edition(&self) -> bool { self.enterprise .as_ref() .map_or(false, |e| !e.license.is_expired()) } - fn licensed_accounts(&self) -> u32 { + pub fn licensed_accounts(&self) -> u32 { self.enterprise.as_ref().map_or(0, |e| e.license.accounts) } - fn log_license_details(&self) { + pub fn log_license_details(&self) { if let Some(enterprise) = &self.enterprise { tracing::info!( licensed_to = enterprise.license.hostname, diff --git a/crates/se-common/src/undelete.rs b/crates/common/src/enterprise/undelete.rs similarity index 87% rename from crates/se-common/src/undelete.rs rename to crates/common/src/enterprise/undelete.rs index 6bf641c1..cf5ec4cb 100644 --- a/crates/se-common/src/undelete.rs +++ b/crates/common/src/enterprise/undelete.rs @@ -8,9 +8,6 @@ * */ -use std::future::Future; - -use common::Core; use serde::{Deserialize, Serialize}; use store::{ write::{ @@ -21,6 +18,8 @@ use store::{ }; use utils::{BlobHash, BLOB_HASH_LEN}; +use crate::Core; + #[derive(Debug, Serialize, Deserialize)] pub struct DeletedBlob { pub hash: H, @@ -32,22 +31,8 @@ pub struct DeletedBlob { pub collection: C, } -pub trait Undelete: Sync + Send { - fn hold_undelete( - &self, - batch: &mut BatchBuilder, - collection: u8, - blob_hash: &BlobHash, - blob_size: usize, - ); - fn list_deleted( - &self, - account_id: u32, - ) -> impl Future>>> + Send; -} - -impl Undelete for Core { - fn hold_undelete( +impl Core { + pub fn hold_undelete( &self, batch: &mut BatchBuilder, collection: u8, @@ -71,7 +56,7 @@ impl Undelete for Core { } } - async fn list_deleted( + pub async fn list_deleted( &self, account_id: u32, ) -> store::Result>> { diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index 3d3bc1aa..28ae5f18 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -35,8 +35,6 @@ use opentelemetry_sdk::{ Resource, }; use opentelemetry_semantic_conventions::resource::{SERVICE_NAME, SERVICE_VERSION}; -#[cfg(feature = "enterprise")] -use se_licensing::license::LicenseKey; use sieve::Sieve; use store::LookupStore; use tokio::sync::{mpsc, oneshot}; @@ -49,6 +47,8 @@ use webhooks::{manager::WebhookEvent, WebhookPayload, WebhookType, Webhooks}; pub mod addresses; pub mod config; +#[cfg(feature = "enterprise")] +pub mod enterprise; pub mod expr; pub mod listener; pub mod manager; @@ -73,7 +73,7 @@ pub struct Core { pub imap: ImapConfig, pub web_hooks: Webhooks, #[cfg(feature = "enterprise")] - pub enterprise: Option, + pub enterprise: Option, } #[derive(Clone)] @@ -83,19 +83,6 @@ pub struct Network { pub url: IfBlock, } -// SPDX-SnippetBegin -// SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd -// SPDX-License-Identifier: LicenseRef-SEL - -#[cfg(feature = "enterprise")] -#[derive(Clone)] -pub struct Enterprise { - pub license: LicenseKey, - pub undelete_period: Option, -} - -// SPDX-SnippetEnd - pub enum AuthResult { Success(T), Failure(AuthFailureReason), diff --git a/crates/jmap/Cargo.toml b/crates/jmap/Cargo.toml index 9f20abf3..24fe11d8 100644 --- a/crates/jmap/Cargo.toml +++ b/crates/jmap/Cargo.toml @@ -11,7 +11,6 @@ jmap_proto = { path = "../jmap-proto" } smtp = { path = "../smtp" } utils = { path = "../utils" } common = { path = "../common" } -se_common = { path = "../se-common", optional = true } directory = { path = "../directory" } smtp-proto = { version = "0.1" } mail-parser = { version = "0.9", features = ["full_encoding", "serde_support", "ludicrous_mode"] } @@ -61,4 +60,4 @@ quick-xml = "0.35" [features] test_mode = [] -enterprise = ["se_common"] +enterprise = [] diff --git a/crates/jmap/src/api/management/enterprise.rs b/crates/jmap/src/api/management/enterprise.rs index 702a17d7..bb6038e7 100644 --- a/crates/jmap/src/api/management/enterprise.rs +++ b/crates/jmap/src/api/management/enterprise.rs @@ -11,11 +11,11 @@ use std::str::FromStr; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; +use common::enterprise::undelete::DeletedBlob; use directory::backend::internal::manage::ManageDirectory; use hyper::Method; use jmap_proto::{error::request::RequestError, types::collection::Collection}; use mail_parser::{DateTime, MessageParser}; -use se_common::undelete::{DeletedBlob, Undelete}; use serde_json::json; use store::write::{BatchBuilder, BlobOp, ValueClass}; use utils::{url_params::UrlParams, BlobHash}; diff --git a/crates/jmap/src/api/management/mod.rs b/crates/jmap/src/api/management/mod.rs index be90eea1..9297b2b4 100644 --- a/crates/jmap/src/api/management/mod.rs +++ b/crates/jmap/src/api/management/mod.rs @@ -26,9 +26,6 @@ use serde::Serialize; use super::{http::ToHttpResponse, HttpRequest, HttpResponse, JsonResponse}; use crate::{auth::AccessToken, JMAP}; -#[cfg(feature = "enterprise")] -use se_common::EnterpriseCore; - #[derive(Serialize)] #[serde(tag = "error")] pub enum ManagementApiError { diff --git a/crates/jmap/src/auth/oauth/auth.rs b/crates/jmap/src/auth/oauth/auth.rs index 0c938e3f..ebdc49f5 100644 --- a/crates/jmap/src/auth/oauth/auth.rs +++ b/crates/jmap/src/auth/oauth/auth.rs @@ -24,9 +24,6 @@ use crate::{ JMAP, }; -#[cfg(feature = "enterprise")] -use se_common::EnterpriseCore; - use super::{ DeviceAuthResponse, FormData, OAuthCode, OAuthCodeRequest, CLIENT_ID_MAX_LEN, DEVICE_CODE_LEN, MAX_POST_LEN, USER_CODE_ALPHABET, USER_CODE_LEN, diff --git a/crates/jmap/src/email/delete.rs b/crates/jmap/src/email/delete.rs index 2926c90f..9f39ee74 100644 --- a/crates/jmap/src/email/delete.rs +++ b/crates/jmap/src/email/delete.rs @@ -13,8 +13,6 @@ use jmap_proto::{ type_state::DataType, }, }; -#[cfg(feature = "enterprise")] -use se_common::undelete::Undelete; use store::{ ahash::AHashMap, roaring::RoaringBitmap, diff --git a/crates/main/Cargo.toml b/crates/main/Cargo.toml index 899631bf..ba4f83ba 100644 --- a/crates/main/Cargo.toml +++ b/crates/main/Cargo.toml @@ -26,7 +26,6 @@ managesieve = { path = "../managesieve" } common = { path = "../common" } directory = { path = "../directory" } utils = { path = "../utils" } -se_common = { path = "../se-common", optional = true } tokio = { version = "1.23", features = ["full"] } tracing = "0.1" @@ -44,4 +43,4 @@ rocks = ["store/rocks"] elastic = ["store/elastic"] s3 = ["store/s3"] redis = ["store/redis"] -enterprise = ["se_common", "se_common/enterprise", "jmap/enterprise", "common/enterprise"] +enterprise = ["jmap/enterprise", "common/enterprise"] diff --git a/crates/main/src/main.rs b/crates/main/src/main.rs index 90443741..879963f9 100644 --- a/crates/main/src/main.rs +++ b/crates/main/src/main.rs @@ -14,8 +14,6 @@ use imap::core::{ImapSessionManager, IMAP}; use jmap::{api::JmapSessionManager, services::gossip::spawn::GossiperBuilder, JMAP}; use managesieve::core::ManageSieveSessionManager; use pop3::Pop3SessionManager; -#[cfg(feature = "enterprise")] -use se_common::EnterpriseCore; use smtp::core::{SmtpSessionManager, SMTP}; use tokio::sync::mpsc; use utils::wait_for_shutdown; diff --git a/crates/se-common/Cargo.toml b/crates/se-common/Cargo.toml deleted file mode 100644 index 46e1a51d..00000000 --- a/crates/se-common/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "se_common" -version = "0.8.5" -edition = "2021" -license = "LicenseRef-SEL" -resolver = "2" - -[dependencies] -common = { path = "../common" } -store = { path = "../store" } -utils = { path = "../utils" } -tracing = "0.1" -serde = { version = "1.0", features = ["derive"]} - -[features] -test_mode = [] -enterprise = ["common/enterprise"] diff --git a/crates/se-licensing/Cargo.toml b/crates/se-licensing/Cargo.toml deleted file mode 100644 index cd3f489a..00000000 --- a/crates/se-licensing/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "se_licensing" -version = "0.8.5" -edition = "2021" -license = "LicenseRef-SEL" -resolver = "2" - -[dependencies] -base64 = "0.22.1" -ring = "0.17.8" - -[features] -test_mode = [] diff --git a/crates/se-licensing/src/lib.rs b/crates/se-licensing/src/lib.rs deleted file mode 100644 index c74269aa..00000000 --- a/crates/se-licensing/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd - * - * SPDX-License-Identifier: LicenseRef-SEL - * - * This file is subject to the Stalwart Enterprise License Agreement (SEL) and - * is NOT open source software. - * - */ - -pub mod license;