Skip to content

Commit

Permalink
Add commercial license
Browse files Browse the repository at this point in the history
  • Loading branch information
amaury1093 committed Dec 11, 2024
1 parent d6912cd commit 4bc8df1
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 7 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tokio-reactor-trait = { version = "1.1.0" }
openssl = { version = "0.10.64", features = ["vendored"] }
reqwest = { version = "0.12.5", features = ["json", "socks"] }
sentry = "0.23"
sentry-anyhow = "0.23"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sqlx = { version = "0.7", features = [
Expand Down
21 changes: 16 additions & 5 deletions backend/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ pub struct BackendConfig {
pub worker: WorkerConfig,

/// Configuration on where to store the email verification results.
pub storage: StorageConfig,
pub storage: Option<StorageConfig>,

/// Whether to enable the Commercial License Trial. Setting this to true
pub commercial_license_trial: Option<CommercialLicenseTrialConfig>,

// Internal fields, not part of the configuration.
#[serde(skip)]
Expand Down Expand Up @@ -100,14 +103,16 @@ impl BackendConfig {
/// the internal `pg_pool` and `channel` fields with the connections.
pub async fn connect(&mut self) -> Result<(), anyhow::Error> {
match &self.storage {
StorageConfig::Postgres(config) => {
Some(StorageConfig::Postgres(config)) => {
let storage = PostgresStorage::new(&config.db_url, config.extra.clone())
.await
.with_context(|| format!("Connecting to postgres DB {}", config.db_url))?;

self.storage_adapter = Arc::new(StorageAdapter::Postgres(storage));
}
StorageConfig::Noop => {}
_ => {
self.storage_adapter = Arc::new(StorageAdapter::Noop);
}
}

let channel = if self.worker.enable {
Expand Down Expand Up @@ -216,6 +221,12 @@ pub struct PostgresConfig {
pub extra: Option<serde_json::Value>,
}

#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct CommercialLicenseTrialConfig {
pub api_token: String,
pub url: String,
}

/// Load the worker configuration from the worker_config.toml file and from the
/// environment.
pub async fn load_config() -> Result<BackendConfig, anyhow::Error> {
Expand Down Expand Up @@ -245,10 +256,10 @@ mod tests {
assert_eq!(cfg.backend_name, "test-backend");
assert_eq!(
cfg.storage,
StorageConfig::Postgres(PostgresConfig {
Some(StorageConfig::Postgres(PostgresConfig {
db_url: "test2".to_string(),
extra: None,
})
}))
);
}

Expand Down
6 changes: 6 additions & 0 deletions backend/src/http/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ impl From<StorageError> for ReacherResponseError {
}
}

impl From<reqwest::Error> for ReacherResponseError {
fn from(e: reqwest::Error) -> Self {
ReacherResponseError::new(StatusCode::INTERNAL_SERVER_ERROR, e)
}
}

/// This function receives a `Rejection` and tries to return a custom value,
/// otherwise simply passes the rejection along.
pub async fn handle_rejection(err: warp::Rejection) -> Result<impl warp::Reply, warp::Rejection> {
Expand Down
7 changes: 7 additions & 0 deletions backend/src/http/v1/check_email/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::config::BackendConfig;
use crate::http::v0::check_email::post::{with_config, CheckEmailRequest};
use crate::http::v1::bulk::post::publish_task;
use crate::http::{check_header, ReacherResponseError};
use crate::storage::commercial_license_trial::send_to_reacher;
use crate::worker::consume::MAX_QUEUE_PRIORITY;
use crate::worker::do_work::{CheckEmailJobId, CheckEmailTask};
use crate::worker::single_shot::SingleShotReply;
Expand Down Expand Up @@ -70,6 +71,12 @@ async fn http_handler(
.map_err(ReacherResponseError::from)
.await?;

// If we're in the Commercial License Trial, we also store the
// result by sending it to back to Reacher.
send_to_reacher(Arc::clone(&config), &input.to_email, &value)
.await
.map_err(ReacherResponseError::from)?;

let result_bz = serde_json::to_vec(&value).map_err(ReacherResponseError::from)?;

return Ok(warp::reply::with_header(
Expand Down
43 changes: 43 additions & 0 deletions backend/src/storage/commercial_license_trial.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Reacher - Email Verification
// Copyright (C) 2018-2023 Reacher

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::config::{BackendConfig, CommercialLicenseTrialConfig};
use crate::worker::do_work::TaskError;
use check_if_email_exists::{CheckEmailOutput, LOG_TARGET};
use std::sync::Arc;
use tracing::debug;

/// If we're in the Commercial License Trial, we also store the
/// result by sending it to back to Reacher.
pub async fn send_to_reacher(
config: Arc<BackendConfig>,
email: &str,
worker_output: &Result<CheckEmailOutput, TaskError>,
) -> Result<(), reqwest::Error> {
if let Some(CommercialLicenseTrialConfig { api_token, url }) = &config.commercial_license_trial
{
let res = reqwest::Client::new()
.post(url)
.header("Authorization", api_token)
.json(worker_output)
.send()
.await?;
let res = res.text().await?;
debug!(target: LOG_TARGET, email=email, res=res, "Sent result to Reacher Commercial License Trial");
}

Ok(())
}
1 change: 1 addition & 0 deletions backend/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pub mod commercial_license_trial;
pub mod error;
pub mod postgres;

Expand Down
2 changes: 2 additions & 0 deletions backend/src/worker/consume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use anyhow::Context;
use check_if_email_exists::LOG_TARGET;
use futures::stream::StreamExt;
use lapin::{options::*, types::FieldTable, Channel, Connection, ConnectionProperties};
use sentry_anyhow::capture_anyhow;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::Mutex;
Expand Down Expand Up @@ -164,6 +165,7 @@ async fn consume_check_email(config: Arc<BackendConfig>) -> Result<(), anyhow::E
do_check_email_work(&payload, delivery, channel_clone2, config_clone2).await
{
error!(target: LOG_TARGET, email=payload.input.to_email, error=?e, "Error processing message");
capture_anyhow(&e);
}
});

Expand Down
5 changes: 5 additions & 0 deletions backend/src/worker/do_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::config::BackendConfig;
use crate::storage::commercial_license_trial::send_to_reacher;
use crate::worker::single_shot::send_single_shot_reply;
use check_if_email_exists::{
check_email, CheckEmailInput, CheckEmailOutput, Reachable, LOG_TARGET,
Expand Down Expand Up @@ -150,6 +151,10 @@ pub(crate) async fn do_check_email_work(
.store(task, &worker_output, storage.get_extra())
.await?;

// If we're in the Commercial License Trial, we also store the
// result by sending it to back to Reacher.
send_to_reacher(config, &task.input.to_email, &worker_output).await?;

info!(target: LOG_TARGET,
email=task.input.to_email,
worker_output=?worker_output.map(|o| o.is_reachable),
Expand Down
8 changes: 6 additions & 2 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ pub async fn check_email(input: &CheckEmailInput) -> CheckEmailOutput {

let end_time = SystemTime::now();

CheckEmailOutput {
let output = CheckEmailOutput {
input: to_email.to_string(),
is_reachable: calculate_reachable(&my_misc, &my_smtp),
misc: Ok(my_misc),
Expand All @@ -269,5 +269,9 @@ pub async fn check_email(input: &CheckEmailInput) -> CheckEmailOutput {
smtp: smtp_debug,
backend_name: input.backend_name.clone(),
},
}
};

log_unknown_errors(&output, &input.backend_name);

output
}

0 comments on commit 4bc8df1

Please sign in to comment.