From db00def1b9568423891fe37bfcd829e6412ad99f Mon Sep 17 00:00:00 2001 From: Diego Imbert Date: Fri, 30 May 2025 12:22:50 +0200 Subject: [PATCH] app compiles with every ee substituted --- backend/src/ee_oss.rs | 8 + backend/src/main.rs | 17 +- backend/src/monitor.rs | 14 +- backend/windmill-api/src/agent_workers_oss.rs | 52 +++++ backend/windmill-api/src/ai.rs | 2 +- backend/windmill-api/src/apps.rs | 4 +- backend/windmill-api/src/apps_oss.rs | 5 + backend/windmill-api/src/args.rs | 2 +- backend/windmill-api/src/audit.rs | 4 +- backend/windmill-api/src/auth.rs | 4 +- backend/windmill-api/src/capture.rs | 8 +- backend/windmill-api/src/configs.rs | 2 +- backend/windmill-api/src/db.rs | 2 +- backend/windmill-api/src/ee_oss.rs | 32 +++ backend/windmill-api/src/flows.rs | 2 +- backend/windmill-api/src/folders.rs | 2 +- backend/windmill-api/src/gcp_triggers_oss.rs | 147 +++++++++++++ backend/windmill-api/src/git_sync_oss.rs | 9 + backend/windmill-api/src/groups.rs | 2 +- backend/windmill-api/src/http_triggers.rs | 4 +- backend/windmill-api/src/indexer_oss.rs | 9 + backend/windmill-api/src/job_helpers_oss.rs | 121 +++++++++++ backend/windmill-api/src/jobs.rs | 4 +- .../windmill-api/src/kafka_triggers_oss.rs | 42 ++++ backend/windmill-api/src/lib.rs | 103 +++++---- backend/windmill-api/src/mqtt_triggers.rs | 2 +- backend/windmill-api/src/nats_triggers_oss.rs | 43 ++++ backend/windmill-api/src/oauth2_oss.rs | 184 ++++++++++++++++ backend/windmill-api/src/oidc_oss.rs | 17 ++ .../src/postgres_triggers/handler.rs | 4 +- backend/windmill-api/src/raw_apps.rs | 2 +- backend/windmill-api/src/resources.rs | 2 +- backend/windmill-api/src/saml_oss.rs | 25 +++ backend/windmill-api/src/schedule.rs | 2 +- backend/windmill-api/src/scim_oss.rs | 23 ++ backend/windmill-api/src/scripts.rs | 2 +- backend/windmill-api/src/settings.rs | 16 +- backend/windmill-api/src/smtp_server_oss.rs | 20 ++ backend/windmill-api/src/sqs_triggers_oss.rs | 33 +++ backend/windmill-api/src/stripe_oss.rs | 5 + .../windmill-api/src/teams_approvals_oss.rs | 7 + backend/windmill-api/src/teams_oss.rs | 39 ++++ backend/windmill-api/src/users.rs | 8 +- backend/windmill-api/src/users_oss.rs | 41 ++++ backend/windmill-api/src/variables.rs | 6 +- .../windmill-api/src/websocket_triggers.rs | 2 +- backend/windmill-api/src/workspaces.rs | 10 +- backend/windmill-api/src/workspaces_export.rs | 8 +- backend/windmill-api/src/workspaces_extra.rs | 2 +- backend/windmill-api/src/workspaces_oss.rs | 15 ++ backend/windmill-audit/src/audit_oss.rs | 74 +++++++ backend/windmill-audit/src/lib.rs | 3 +- .../src/autoscaling_oss.rs | 6 + backend/windmill-autoscaling/src/lib.rs | 3 +- backend/windmill-common/src/ee.rs | 16 +- backend/windmill-common/src/ee_oss.rs | 110 ++++++++++ backend/windmill-common/src/email_oss.rs | 11 + .../windmill-common/src/job_s3_helpers_oss.rs | 34 +++ backend/windmill-common/src/lib.rs | 25 ++- backend/windmill-common/src/oidc_oss.rs | 198 ++++++++++++++++++ backend/windmill-common/src/otel_oss.rs | 58 +++++ backend/windmill-common/src/s3_helpers.rs | 6 +- backend/windmill-common/src/stats_oss.rs | 47 +++++ backend/windmill-common/src/teams_oss.rs | 0 backend/windmill-common/src/tracing_init.rs | 8 +- backend/windmill-common/src/utils.rs | 4 +- backend/windmill-git-sync/src/git_sync_oss.rs | 16 ++ backend/windmill-git-sync/src/lib.rs | 5 +- .../src/completed_runs_oss.rs | 22 ++ backend/windmill-indexer/src/indexer_oss.rs | 1 + backend/windmill-indexer/src/lib.rs | 9 +- .../windmill-indexer/src/service_logs_oss.rs | 25 +++ backend/windmill-queue/src/jobs.rs | 4 +- backend/windmill-queue/src/jobs_oss.rs | 16 ++ backend/windmill-queue/src/lib.rs | 3 +- backend/windmill-queue/src/schedule.rs | 2 +- backend/windmill-worker/src/common.rs | 8 +- backend/windmill-worker/src/handle_child.rs | 2 +- backend/windmill-worker/src/job_logger.rs | 4 +- backend/windmill-worker/src/job_logger_oss.rs | 42 ++++ backend/windmill-worker/src/lib.rs | 2 + backend/windmill-worker/src/otel_oss.rs | 3 + .../windmill-worker/src/python_executor.rs | 2 +- .../windmill-worker/src/result_processor.rs | 12 +- backend/windmill-worker/src/worker.rs | 4 +- backend/windmill-worker/src/worker_flow.rs | 2 +- 86 files changed, 1747 insertions(+), 159 deletions(-) create mode 100644 backend/src/ee_oss.rs create mode 100644 backend/windmill-api/src/agent_workers_oss.rs create mode 100644 backend/windmill-api/src/apps_oss.rs create mode 100644 backend/windmill-api/src/ee_oss.rs create mode 100644 backend/windmill-api/src/gcp_triggers_oss.rs create mode 100644 backend/windmill-api/src/git_sync_oss.rs create mode 100644 backend/windmill-api/src/indexer_oss.rs create mode 100644 backend/windmill-api/src/job_helpers_oss.rs create mode 100644 backend/windmill-api/src/kafka_triggers_oss.rs create mode 100644 backend/windmill-api/src/nats_triggers_oss.rs create mode 100644 backend/windmill-api/src/oauth2_oss.rs create mode 100644 backend/windmill-api/src/oidc_oss.rs create mode 100644 backend/windmill-api/src/saml_oss.rs create mode 100644 backend/windmill-api/src/scim_oss.rs create mode 100644 backend/windmill-api/src/smtp_server_oss.rs create mode 100644 backend/windmill-api/src/sqs_triggers_oss.rs create mode 100644 backend/windmill-api/src/stripe_oss.rs create mode 100644 backend/windmill-api/src/teams_approvals_oss.rs create mode 100644 backend/windmill-api/src/teams_oss.rs create mode 100644 backend/windmill-api/src/users_oss.rs create mode 100644 backend/windmill-api/src/workspaces_oss.rs create mode 100644 backend/windmill-audit/src/audit_oss.rs create mode 100644 backend/windmill-autoscaling/src/autoscaling_oss.rs create mode 100644 backend/windmill-common/src/ee_oss.rs create mode 100644 backend/windmill-common/src/email_oss.rs create mode 100644 backend/windmill-common/src/job_s3_helpers_oss.rs create mode 100644 backend/windmill-common/src/oidc_oss.rs create mode 100644 backend/windmill-common/src/otel_oss.rs create mode 100644 backend/windmill-common/src/stats_oss.rs create mode 100644 backend/windmill-common/src/teams_oss.rs create mode 100644 backend/windmill-git-sync/src/git_sync_oss.rs create mode 100644 backend/windmill-indexer/src/completed_runs_oss.rs create mode 100644 backend/windmill-indexer/src/indexer_oss.rs create mode 100644 backend/windmill-indexer/src/service_logs_oss.rs create mode 100644 backend/windmill-queue/src/jobs_oss.rs create mode 100644 backend/windmill-worker/src/job_logger_oss.rs create mode 100644 backend/windmill-worker/src/otel_oss.rs diff --git a/backend/src/ee_oss.rs b/backend/src/ee_oss.rs new file mode 100644 index 0000000000..4bbcd4e53b --- /dev/null +++ b/backend/src/ee_oss.rs @@ -0,0 +1,8 @@ +pub async fn set_license_key(license_key: String) -> () { + crate::ee::set_license_key(license_key).await +} + +#[cfg(feature = "enterprise")] +pub async fn verify_license_key() -> () { + crate::ee::verify_license_key().await +} diff --git a/backend/src/main.rs b/backend/src/main.rs index a4148d93c6..d58d312b47 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -28,7 +28,9 @@ use uuid::Uuid; use windmill_api::HTTP_CLIENT; #[cfg(feature = "enterprise")] -use windmill_common::ee::{maybe_renew_license_key_on_start, LICENSE_KEY_ID, LICENSE_KEY_VALID}; +use windmill_common::ee_oss::{ + maybe_renew_license_key_on_start, LICENSE_KEY_ID, LICENSE_KEY_VALID, +}; use windmill_common::{ agent_workers::build_agent_http_client, @@ -49,7 +51,7 @@ use windmill_common::{ TIMEOUT_WAIT_RESULT_SETTING, }, scripts::ScriptLang, - stats_ee::schedule_stats, + stats_oss::schedule_stats, triggers::TriggerKind, utils::{hostname, rd_string, Mode, GIT_VERSION, MODE_AND_ADDONS}, worker::{ @@ -99,6 +101,7 @@ const DEFAULT_PORT: u16 = 8000; const DEFAULT_SERVER_BIND_ADDR: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0); mod ee; +mod ee_oss; mod monitor; pub fn setup_deno_runtime() -> anyhow::Result<()> { @@ -552,7 +555,7 @@ Windmill Community Edition {GIT_VERSION} _ = indexer_rx.recv() => { tracing::info!("Received killpill, aborting index initialization"); }, - res = windmill_indexer::completed_runs_ee::init_index(&db) => { + res = windmill_indexer::completed_runs_oss::init_index(&db) => { let res = res?; reader = Some(res.0); writer = Some(res.1); @@ -574,7 +577,7 @@ Windmill Community Edition {GIT_VERSION} async { if let Some(db) = conn.as_sql() { if let Some(index_writer) = index_writer2 { - windmill_indexer::completed_runs_ee::run_indexer( + windmill_indexer::completed_runs_oss::run_indexer( db.clone(), index_writer, indexer_rx, @@ -596,7 +599,7 @@ Windmill Community Edition {GIT_VERSION} _ = indexer_rx.recv() => { tracing::info!("Received killpill, aborting index initialization"); }, - res = windmill_indexer::service_logs_ee::init_index(&db, killpill_tx.clone()) => { + res = windmill_indexer::service_logs_oss::init_index(&db, killpill_tx.clone()) => { let res = res?; reader = Some(res.0); writer = Some(res.1); @@ -618,7 +621,7 @@ Windmill Community Edition {GIT_VERSION} async { if let Some(db) = conn.as_sql() { if let Some(log_index_writer) = log_index_writer2 { - windmill_indexer::service_logs_ee::run_indexer( + windmill_indexer::service_logs_oss::run_indexer( db.clone(), log_index_writer, log_indexer_rx, @@ -1086,7 +1089,7 @@ Windmill Community Edition {GIT_VERSION} tracing::info!("Reloading config after 12 hours"); initial_load(&conn, tx.clone(), worker_mode, server_mode, #[cfg(feature = "parquet")] disable_s3_store).await; #[cfg(feature = "enterprise")] - ee::verify_license_key().await; + ee_oss::verify_license_key().await; } } }, diff --git a/backend/src/monitor.rs b/backend/src/monitor.rs index d2a5657c6c..7d7f064f3d 100644 --- a/backend/src/monitor.rs +++ b/backend/src/monitor.rs @@ -29,9 +29,9 @@ use windmill_api::{ }; #[cfg(feature = "enterprise")] -use windmill_common::ee::low_disk_alerts; +use windmill_common::ee_oss::low_disk_alerts; #[cfg(feature = "enterprise")] -use windmill_common::ee::{jobs_waiting_alerts, worker_groups_alerts}; +use windmill_common::ee_oss::{jobs_waiting_alerts, worker_groups_alerts}; use windmill_common::client::AuthedClient; #[cfg(feature = "oauth2")] @@ -41,7 +41,7 @@ use windmill_common::s3_helpers::reload_object_store_setting; use windmill_common::{ agent_workers::DECODED_AGENT_TOKEN, auth::create_token_for_owner, - ee::CriticalErrorChannel, + ee_oss::CriticalErrorChannel, error, flow_status::{FlowStatus, FlowStatusModule}, global_settings::{ @@ -87,9 +87,9 @@ use windmill_worker::{ use windmill_common::s3_helpers::ObjectStoreReload; #[cfg(feature = "enterprise")] -use crate::ee::verify_license_key; +use crate::ee_oss::verify_license_key; -use crate::ee::set_license_key; +use crate::ee_oss::set_license_key; #[cfg(feature = "prometheus")] lazy_static::lazy_static! { @@ -1609,7 +1609,7 @@ pub async fn reload_base_url_setting(conn: &Connection) -> error::Result<()> { if let Some(q) = q_oauth { if let Ok(v) = serde_json::from_value::< - Option>, + Option>, >(q.clone()) { v @@ -1630,7 +1630,7 @@ pub async fn reload_base_url_setting(conn: &Connection) -> error::Result<()> { { if let Some(db) = conn.as_sql() { let mut l = windmill_api::OAUTH_CLIENTS.write().await; - *l = windmill_api::oauth2_ee::build_oauth_clients(&base_url, oauths, db).await + *l = windmill_api::oauth2_oss::build_oauth_clients(&base_url, oauths, db).await .map_err(|e| tracing::error!("Error building oauth clients (is the oauth.json mounted and in correct format? Use '{}' as minimal oauth.json): {}", "{}", e)) .unwrap(); } diff --git a/backend/windmill-api/src/agent_workers_oss.rs b/backend/windmill-api/src/agent_workers_oss.rs new file mode 100644 index 0000000000..1b5a210d13 --- /dev/null +++ b/backend/windmill-api/src/agent_workers_oss.rs @@ -0,0 +1,52 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2042 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ + +use crate::db::DB; + +use axum::Router; + +use serde::{Deserialize, Serialize}; + +pub fn global_service() -> Router { + Router::new() +} + +pub fn workspaced_service( + db: DB, + _base_internal_url: String, +) -> ( + Router, + Vec>, + Option, +) { + use windmill_common::worker::Connection; + use windmill_worker::JobCompletedSender; + + let (job_completed_tx, _job_completed_rx) = + JobCompletedSender::new(&Connection::Sql(db.clone()), 10); + + let router = Router::new(); + + (router, vec![], Some(job_completed_tx)) +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct AgentAuth { + pub worker_group: String, + pub suffix: Option, + pub tags: Vec, + pub exp: Option, +} + +pub struct AgentCache {} + +impl AgentCache { + pub fn new() -> Self { + AgentCache {} + } +} diff --git a/backend/windmill-api/src/ai.rs b/backend/windmill-api/src/ai.rs index 6b33a70730..86e69fe233 100644 --- a/backend/windmill-api/src/ai.rs +++ b/backend/windmill-api/src/ai.rs @@ -10,7 +10,7 @@ use reqwest::{Client, RequestBuilder}; use serde::{Deserialize, Serialize}; use serde_json::value::RawValue; use std::collections::HashMap; -use windmill_audit::{audit_ee::audit_log, ActionKind}; +use windmill_audit::{audit_oss::audit_log, ActionKind}; use windmill_common::error::{to_anyhow, Error, Result}; lazy_static::lazy_static! { diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index 533da11d1c..9dfe40b5b9 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -18,7 +18,7 @@ use crate::{ }; #[cfg(feature = "parquet")] use crate::{ - job_helpers_ee::{ + job_helpers_oss::{ download_s3_file_internal, get_random_file_name, get_s3_resource, get_workspace_s3_resource, upload_file_from_req, DownloadFileQuery, }, @@ -48,7 +48,7 @@ use sha2::{Digest, Sha256}; use sql_builder::{bind::Bind, SqlBuilder}; use sqlx::{types::Uuid, FromRow}; use std::str; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::{ apps::{AppScriptId, ListAppQuery}, diff --git a/backend/windmill-api/src/apps_oss.rs b/backend/windmill-api/src/apps_oss.rs new file mode 100644 index 0000000000..a7737664b9 --- /dev/null +++ b/backend/windmill-api/src/apps_oss.rs @@ -0,0 +1,5 @@ +use axum::Router; + +pub fn global_unauthed_service() -> Router { + Router::new() +} diff --git a/backend/windmill-api/src/args.rs b/backend/windmill-api/src/args.rs index e3a2adb38f..0b8f4d5210 100644 --- a/backend/windmill-api/src/args.rs +++ b/backend/windmill-api/src/args.rs @@ -85,7 +85,7 @@ impl RawWebhookArgs { db: &DB, w_id: &str, ) -> Result>, Error> { - use crate::job_helpers_ee::{ + use crate::job_helpers_oss::{ get_random_file_name, get_workspace_s3_resource, upload_file_internal, }; use futures::TryStreamExt; diff --git a/backend/windmill-api/src/audit.rs b/backend/windmill-api/src/audit.rs index 47ba881014..336fd32881 100644 --- a/backend/windmill-api/src/audit.rs +++ b/backend/windmill-api/src/audit.rs @@ -28,7 +28,7 @@ async fn get_audit( Path((w_id, id)): Path<(String, i32)>, ) -> JsonResult { let tx = user_db.begin(&authed).await?; - let audit = windmill_audit::audit_ee::get_audit(tx, id, &w_id).await?; + let audit = windmill_audit::audit_oss::get_audit(tx, id, &w_id).await?; Ok(Json(audit)) } async fn list_audit( @@ -39,6 +39,6 @@ async fn list_audit( Query(lq): Query, ) -> JsonResult> { let tx = user_db.begin(&authed).await?; - let rows = windmill_audit::audit_ee::list_audit(tx, w_id, pagination, lq).await?; + let rows = windmill_audit::audit_oss::list_audit(tx, w_id, pagination, lq).await?; Ok(Json(rows)) } diff --git a/backend/windmill-api/src/auth.rs b/backend/windmill-api/src/auth.rs index 2936b74957..25dc0efd4a 100644 --- a/backend/windmill-api/src/auth.rs +++ b/backend/windmill-api/src/auth.rs @@ -1,5 +1,5 @@ #[cfg(feature = "enterprise")] -use crate::ee::ExternalJwks; +use crate::ee_oss::ExternalJwks; use axum::{ async_trait, extract::{FromRequestParts, OriginalUri, Query}, @@ -71,7 +71,7 @@ impl AuthCache { } #[cfg(feature = "enterprise")] _ if token.starts_with("jwt_ext_") => { - let authed_and_exp = match crate::ee::jwt_ext_auth( + let authed_and_exp = match crate::ee_oss::jwt_ext_auth( w_id.as_ref(), token.trim_start_matches("jwt_ext_"), self.ext_jwks.clone(), diff --git a/backend/windmill-api/src/capture.rs b/backend/windmill-api/src/capture.rs index 07127e53a1..3b7b5fbbb7 100644 --- a/backend/windmill-api/src/capture.rs +++ b/backend/windmill-api/src/capture.rs @@ -15,7 +15,7 @@ use { #[cfg(all(feature = "enterprise", feature = "gcp_trigger"))] use { - crate::gcp_triggers_ee::{ + crate::gcp_triggers_oss::{ manage_google_subscription, process_google_push_request, validate_jwt_token, CreateUpdateConfig, SubscriptionMode, }, @@ -36,13 +36,13 @@ use windmill_common::auth::aws::AwsAuthResourceType; use {serde::de::DeserializeOwned, windmill_common::error::Error}; #[cfg(all(feature = "enterprise", feature = "kafka"))] -use crate::kafka_triggers_ee::KafkaTriggerConfigConnection; +use crate::kafka_triggers_oss::KafkaTriggerConfigConnection; #[cfg(feature = "mqtt_trigger")] use crate::mqtt_triggers::{MqttClientVersion, MqttV3Config, MqttV5Config, SubscribeTopic}; #[cfg(all(feature = "enterprise", feature = "nats"))] -use crate::nats_triggers_ee::NatsTriggerConfigConnection; +use crate::nats_triggers_oss::NatsTriggerConfigConnection; #[cfg(feature = "postgres_trigger")] use { @@ -903,7 +903,7 @@ async fn gcp_payload( headers: HeaderMap, request: Request, ) -> Result { - use crate::{gcp_triggers_ee::GcpTrigger, trigger_helpers::TriggerJobArgs}; + use crate::{gcp_triggers_oss::GcpTrigger, trigger_helpers::TriggerJobArgs}; let is_flow = matches!(runnable_kind, RunnableKind::Flow); let (gcp_trigger_config, owner, email): (GcpTriggerConfig, _, _) = diff --git a/backend/windmill-api/src/configs.rs b/backend/windmill-api/src/configs.rs index e8770b2b5e..9110d104c8 100644 --- a/backend/windmill-api/src/configs.rs +++ b/backend/windmill-api/src/configs.rs @@ -14,7 +14,7 @@ use axum::{ use serde::{Deserialize, Serialize}; use sqlx::FromRow; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::{ error::{self}, diff --git a/backend/windmill-api/src/db.rs b/backend/windmill-api/src/db.rs index 85f1ee485f..71afe9cb1f 100644 --- a/backend/windmill-api/src/db.rs +++ b/backend/windmill-api/src/db.rs @@ -16,7 +16,7 @@ use sqlx::{ }; use tokio::task::JoinHandle; -use windmill_audit::audit_ee::{AuditAuthor, AuditAuthorable}; +use windmill_audit::audit_oss::{AuditAuthor, AuditAuthorable}; use windmill_common::{ db::{Authable, Authed}, error::Error, diff --git a/backend/windmill-api/src/ee_oss.rs b/backend/windmill-api/src/ee_oss.rs new file mode 100644 index 0000000000..cddb639e95 --- /dev/null +++ b/backend/windmill-api/src/ee_oss.rs @@ -0,0 +1,32 @@ +use anyhow::anyhow; +#[cfg(feature = "enterprise")] +use std::sync::Arc; +#[cfg(feature = "enterprise")] +use tokio::sync::RwLock; + +pub async fn validate_license_key(_license_key: String) -> anyhow::Result<(String, bool)> { + // Implementation is not open source + Err(anyhow!("License can't be validated in Windmill CE")) +} + +#[cfg(feature = "enterprise")] +pub async fn jwt_ext_auth( + _w_id: Option<&String>, + _token: &str, + _external_jwks: Option>>, +) -> anyhow::Result<(crate::db::ApiAuthed, usize)> { + // Implementation is not open source + + Err(anyhow!("External JWT auth is not open source")) +} + +#[cfg(feature = "enterprise")] +pub struct ExternalJwks; + +#[cfg(feature = "enterprise")] +impl ExternalJwks { + pub async fn load() -> Option>> { + // Implementation is not open source + None + } +} diff --git a/backend/windmill-api/src/flows.rs b/backend/windmill-api/src/flows.rs index e34b2cacaf..505656da47 100644 --- a/backend/windmill-api/src/flows.rs +++ b/backend/windmill-api/src/flows.rs @@ -31,7 +31,7 @@ use hyper::StatusCode; use serde::{Deserialize, Serialize}; use sql_builder::prelude::*; use sqlx::{FromRow, Postgres, Transaction}; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::utils::query_elems_from_hub; use windmill_common::worker::to_raw_value; diff --git a/backend/windmill-api/src/folders.rs b/backend/windmill-api/src/folders.rs index 5047a96cad..1e4d2e09c0 100644 --- a/backend/windmill-api/src/folders.rs +++ b/backend/windmill-api/src/folders.rs @@ -23,7 +23,7 @@ use axum::{ }; use lazy_static::lazy_static; use regex::Regex; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::{ db::UserDB, diff --git a/backend/windmill-api/src/gcp_triggers_oss.rs b/backend/windmill-api/src/gcp_triggers_oss.rs new file mode 100644 index 0000000000..0dc672580c --- /dev/null +++ b/backend/windmill-api/src/gcp_triggers_oss.rs @@ -0,0 +1,147 @@ +use crate::db::{ApiAuthed, DB}; +use crate::trigger_helpers::TriggerJobArgs; +use axum::{extract::Request, Router}; +use http::HeaderMap; +use serde::{Deserialize, Serialize}; +use serde_json::value::RawValue; +use sqlx::prelude::FromRow; +use sqlx::types::Json as SqlxJson; +use std::collections::HashMap; +use windmill_common::db::UserDB; +use windmill_common::worker::to_raw_value; +use windmill_common::{ + error::{Error as WindmillError, Result as WindmillResult}, + triggers::TriggerKind, + utils::empty_as_none, +}; + +#[derive(sqlx::Type, Debug, Deserialize, Serialize)] +#[serde(rename_all(serialize = "lowercase", deserialize = "lowercase"))] +#[sqlx(type_name = "DELIVERY_MODE", rename_all = "lowercase")] +#[allow(unused)] +pub enum DeliveryType { + Pull, + Push, +} + +impl Default for DeliveryType { + fn default() -> Self { + Self::Pull + } +} + +#[derive(FromRow, Deserialize, Serialize, Debug)] +#[allow(unused)] +pub struct PushConfig { + #[serde(deserialize_with = "empty_as_none")] + route_path: Option, + #[serde(deserialize_with = "empty_as_none")] + audience: Option, + authenticate: bool, + base_endpoint: String, +} +#[derive(Default, Debug, Serialize, Deserialize)] +#[allow(unused)] +pub struct CreateUpdateConfig { + pub delivery_type: DeliveryType, + #[serde(default, deserialize_with = "empty_as_none")] + pub subscription_id: Option, + pub delivery_config: Option>, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct ExistingGcpSubscription { + pub subscription_id: String, + pub base_endpoint: String, +} + +#[derive(Debug, Deserialize, Serialize, sqlx::Type)] +#[serde(rename_all = "snake_case")] +#[sqlx(type_name = "GCP_SUBSCRIPTION_MODE", rename_all = "snake_case")] +pub enum SubscriptionMode { + Existing, + CreateUpdate, +} + +pub fn workspaced_service() -> Router { + Router::new() +} + +pub fn start_consuming_gcp_pubsub_event( + _db: DB, + mut _killpill_rx: tokio::sync::broadcast::Receiver<()>, +) -> () { + // implementation is not open source +} + +pub async fn manage_google_subscription( + _authed: ApiAuthed, + _db: &DB, + _workspace_id: &str, + _gcp_resource_path: &str, + _path: &str, + _topic_id: &str, + _subscription_id: &mut Option, + _base_endpoint: &mut Option, + _subscription_mode: SubscriptionMode, + _create_update_config: Option, + _trigger_mode: bool, + _is_flow: bool, +) -> WindmillResult { + Ok(CreateUpdateConfig::default()) +} + +pub async fn process_google_push_request( + _headers: HeaderMap, + _request: Request, +) -> Result<(String, HashMap>), WindmillError> { + Ok((String::new(), HashMap::new())) +} + +pub async fn validate_jwt_token( + _db: &DB, + _user_db: UserDB, + _authed: ApiAuthed, + _headers: &HeaderMap, + _gcp_resource_path: &str, + _workspace_id: &str, + _delivery_config: &PushConfig, +) -> Result<(), windmill_common::error::Error> { + Ok(()) +} + +pub fn gcp_push_route_handler() -> Router { + Router::new() +} + +#[derive(FromRow, Deserialize, Serialize, Debug)] +pub struct GcpTrigger { + pub gcp_resource_path: String, + pub subscription_id: String, + pub delivery_type: DeliveryType, + pub delivery_config: Option>, + pub subscription_mode: SubscriptionMode, + pub topic_id: String, + pub path: String, + pub script_path: String, + pub is_flow: bool, + pub workspace_id: String, + pub edited_by: String, + pub email: String, + pub edited_at: chrono::DateTime, + pub extra_perms: Option, + pub error: Option, + pub server_id: Option, + pub last_server_ping: Option>, + pub enabled: bool, +} + +impl TriggerJobArgs for GcpTrigger { + fn v1_payload_fn(payload: String) -> HashMap> { + HashMap::from([("payload".to_string(), to_raw_value(&payload))]) + } + + fn trigger_kind() -> TriggerKind { + TriggerKind::Gcp + } +} diff --git a/backend/windmill-api/src/git_sync_oss.rs b/backend/windmill-api/src/git_sync_oss.rs new file mode 100644 index 0000000000..b72afac189 --- /dev/null +++ b/backend/windmill-api/src/git_sync_oss.rs @@ -0,0 +1,9 @@ +use axum::routing::Router; + +pub fn workspaced_service() -> Router { + Router::new() +} + +pub fn global_service() -> Router { + Router::new() +} \ No newline at end of file diff --git a/backend/windmill-api/src/groups.rs b/backend/windmill-api/src/groups.rs index e25d3ee7da..d5da9c25f5 100644 --- a/backend/windmill-api/src/groups.rs +++ b/backend/windmill-api/src/groups.rs @@ -14,7 +14,7 @@ use axum::{ routing::{delete, get, post}, Json, Router, }; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::worker::CLOUD_HOSTED; use windmill_common::{ diff --git a/backend/windmill-api/src/http_triggers.rs b/backend/windmill-api/src/http_triggers.rs index b17c8205ad..b75f8a6ce8 100644 --- a/backend/windmill-api/src/http_triggers.rs +++ b/backend/windmill-api/src/http_triggers.rs @@ -1,7 +1,7 @@ #[cfg(feature = "http_trigger")] use crate::http_trigger_args::{HttpMethod, RawHttpTriggerArgs}; #[cfg(feature = "parquet")] -use crate::job_helpers_ee::get_workspace_s3_resource; +use crate::job_helpers_oss::get_workspace_s3_resource; use crate::resources::try_get_resource_from_db_as; use crate::trigger_helpers::{get_runnable_format, RunnableId}; use crate::utils::{non_empty_str, ExpiringCacheEntry}; @@ -33,7 +33,7 @@ use std::borrow::Cow; use std::{collections::HashMap, sync::Arc}; use tokio::sync::{RwLock, RwLockReadGuard}; use tower_http::cors::CorsLayer; -use windmill_audit::{audit_ee::audit_log, ActionKind}; +use windmill_audit::{audit_oss::audit_log, ActionKind}; use windmill_common::error::Error; #[cfg(feature = "parquet")] use windmill_common::s3_helpers::build_object_store_client; diff --git a/backend/windmill-api/src/indexer_oss.rs b/backend/windmill-api/src/indexer_oss.rs new file mode 100644 index 0000000000..2ccca92c27 --- /dev/null +++ b/backend/windmill-api/src/indexer_oss.rs @@ -0,0 +1,9 @@ +use axum::Router; + +pub fn workspaced_service() -> Router { + Router::new() +} + +pub fn global_service() -> Router { + Router::new() +} diff --git a/backend/windmill-api/src/job_helpers_oss.rs b/backend/windmill-api/src/job_helpers_oss.rs new file mode 100644 index 0000000000..4e14d16c5f --- /dev/null +++ b/backend/windmill-api/src/job_helpers_oss.rs @@ -0,0 +1,121 @@ +use axum::Router; +use serde::Serialize; +use uuid::Uuid; +use windmill_common::s3_helpers::StorageResourceType; + +#[cfg(feature = "parquet")] +use crate::db::{ApiAuthed, DB}; +#[cfg(feature = "parquet")] +use object_store::{ObjectStore, PutMultipartOpts}; +#[cfg(feature = "parquet")] +use std::sync::Arc; +use windmill_common::error; +#[cfg(feature = "parquet")] +use windmill_common::{db::UserDB, s3_helpers::ObjectStoreResource}; + +#[cfg(feature = "parquet")] +use bytes::Bytes; +#[cfg(feature = "parquet")] +use futures::Stream; + +#[cfg(feature = "parquet")] +use axum::response::Response; +#[cfg(feature = "parquet")] +use serde::Deserialize; + +#[derive(Serialize)] +pub struct UploadFileResponse { + pub file_key: String, +} + +#[derive(Deserialize)] +pub struct LoadImagePreviewQuery { + #[allow(dead_code)] + pub file_key: String, + #[allow(dead_code)] + pub storage: Option, +} + +#[derive(Deserialize)] +pub struct DownloadFileQuery { + #[allow(dead_code)] + pub file_key: String, + #[allow(dead_code)] + pub storage: Option, + #[allow(dead_code)] + pub s3_resource_path: Option, +} + +pub fn workspaced_service() -> Router { + Router::new() +} + +#[cfg(feature = "parquet")] +pub async fn get_workspace_s3_resource<'c>( + _authed: &ApiAuthed, + _db: &DB, + _user_db: Option, + _token: &str, + _w_id: &str, + _storage: Option, +) -> windmill_common::error::Result<(Option, Option)> { + // implementation is not open source + Ok((None, None)) +} + +pub fn get_random_file_name(_file_extension: Option) -> String { + unimplemented!("Not implemented in Windmill's Open Source repository") +} + +pub async fn get_s3_resource<'c>( + _authed: &ApiAuthed, + _db: &DB, + _user_db: Option, + _token: &str, + _w_id: &str, + _resource_path: &str, + _resource_type: Option, + _job_id: Option, +) -> error::Result { + Err(error::Error::internal_err( + "Not implemented in Windmill's Open Source repository".to_string(), + )) +} + +#[cfg(feature = "parquet")] +pub async fn upload_file_from_req( + _s3_client: Arc, + _file_key: &str, + _req: axum::extract::Request, + _options: PutMultipartOpts, +) -> error::Result<()> { + Err(error::Error::internal_err( + "Not implemented in Windmill's Open Source repository".to_string(), + )) +} + +#[cfg(feature = "parquet")] +pub async fn upload_file_internal( + _s3_client: Arc, + _file_key: &str, + _stream: impl Stream> + Unpin, + _options: PutMultipartOpts, +) -> error::Result<()> { + Err(error::Error::internal_err( + "Not implemented in Windmill's Open Source repository".to_string(), + )) +} + +#[cfg(feature = "parquet")] +pub async fn download_s3_file_internal( + _authed: ApiAuthed, + _db: &DB, + _user_db: Option, + _token: &str, + _w_id: &str, + _query: DownloadFileQuery, +) -> error::Result { + Err(error::Error::internal_err( + "Not implemented in Windmill's Open Source repository".to_string(), + )) +} diff --git a/backend/windmill-api/src/jobs.rs b/backend/windmill-api/src/jobs.rs index cf9e7d06de..5ac7348ef9 100644 --- a/backend/windmill-api/src/jobs.rs +++ b/backend/windmill-api/src/jobs.rs @@ -64,7 +64,7 @@ use sqlx::types::JsonRawValue; use sqlx::{types::Uuid, FromRow, Postgres, Transaction}; use tower_http::cors::{Any, CorsLayer}; use urlencoding::encode; -use windmill_audit::audit_ee::{audit_log, AuditAuthor}; +use windmill_audit::audit_oss::{audit_log, AuditAuthor}; use windmill_audit::ActionKind; use windmill_common::worker::{to_raw_value, CUSTOM_TAGS_PER_WORKSPACE}; use windmill_common::{ @@ -3183,7 +3183,7 @@ async fn check_tag_available_for_workspace( #[cfg(feature = "enterprise")] pub async fn check_license_key_valid() -> error::Result<()> { - use windmill_common::ee::LICENSE_KEY_VALID; + use windmill_common::ee_oss::LICENSE_KEY_VALID; let valid = *LICENSE_KEY_VALID.read().await; if !valid { diff --git a/backend/windmill-api/src/kafka_triggers_oss.rs b/backend/windmill-api/src/kafka_triggers_oss.rs new file mode 100644 index 0000000000..0a24151ae3 --- /dev/null +++ b/backend/windmill-api/src/kafka_triggers_oss.rs @@ -0,0 +1,42 @@ +use crate::db::DB; +use axum::Router; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct KafkaResourceSecurity {} + +pub fn workspaced_service() -> Router { + Router::new() +} + +pub fn start_kafka_consumers( + _db: DB, + mut _killpill_rx: tokio::sync::broadcast::Receiver<()>, +) -> () { + // implementation is not open source +} + +#[derive(Serialize, Deserialize)] +pub enum KafkaTriggerConfigConnection {} + +#[derive(Serialize, Clone)] +pub struct KafkaTrigger { + pub workspace_id: String, + pub path: String, + pub kafka_resource_path: String, + pub group_id: String, + pub topics: Vec, + pub script_path: String, + pub is_flow: bool, + pub edited_by: String, + pub email: String, + pub edited_at: chrono::DateTime, + #[serde(skip_serializing_if = "Option::is_none")] + pub server_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub last_server_ping: Option>, + pub extra_perms: serde_json::Value, + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + pub enabled: bool, +} \ No newline at end of file diff --git a/backend/windmill-api/src/lib.rs b/backend/windmill-api/src/lib.rs index d79639f0ab..5cfb5d42f6 100644 --- a/backend/windmill-api/src/lib.rs +++ b/backend/windmill-api/src/lib.rs @@ -8,15 +8,15 @@ use crate::db::ApiAuthed; #[cfg(feature = "enterprise")] -use crate::ee::ExternalJwks; +use crate::ee_oss::ExternalJwks; #[cfg(feature = "embedding")] use crate::embeddings::load_embeddings_db; #[cfg(feature = "oauth2")] -use crate::oauth2_ee::AllClients; +use crate::oauth2_oss::AllClients; #[cfg(feature = "oauth2")] -use crate::oauth2_ee::SlackVerifier; +use crate::oauth2_oss::SlackVerifier; #[cfg(feature = "smtp")] -use crate::smtp_server_ee::SmtpServer; +use crate::smtp_server_oss::SmtpServer; #[cfg(feature = "mcp")] use crate::mcp::{setup_mcp_server, Runner as McpRunner}; @@ -28,7 +28,7 @@ use crate::{ }; #[cfg(feature = "agent_worker_server")] -use agent_workers_ee::AgentCache; +use agent_workers_oss::AgentCache; use anyhow::Context; use argon2::Argon2; @@ -58,11 +58,13 @@ use windmill_common::db::UserDB; use windmill_common::worker::CLOUD_HOSTED; use windmill_common::{utils::GIT_VERSION, BASE_URL, INSTANCE_NAME}; -use crate::scim_ee::has_scim_token; +use crate::scim_oss::has_scim_token; use windmill_common::error::AppError; #[cfg(feature = "agent_worker_server")] mod agent_workers_ee; +#[cfg(feature = "agent_worker_server")] +mod agent_workers_oss; mod ai; mod apps; pub mod args; @@ -73,7 +75,8 @@ mod concurrency_groups; mod configs; mod db; mod drafts; -pub mod ee; +mod ee; +pub mod ee_oss; pub mod embeddings; mod favorite; mod flows; @@ -87,6 +90,7 @@ mod http_trigger_auth; #[cfg(feature = "http_trigger")] pub mod http_triggers; mod indexer_ee; +mod indexer_oss; mod inputs; mod integration; #[cfg(feature = "postgres_trigger")] @@ -95,47 +99,71 @@ mod postgres_triggers; mod approvals; #[cfg(feature = "enterprise")] mod apps_ee; +#[cfg(feature = "enterprise")] +mod apps_oss; #[cfg(all(feature = "enterprise", feature = "gcp_trigger"))] mod gcp_triggers_ee; +#[cfg(all(feature = "enterprise", feature = "gcp_trigger"))] +mod gcp_triggers_oss; #[cfg(feature = "enterprise")] mod git_sync_ee; +#[cfg(feature = "enterprise")] +mod git_sync_oss; #[cfg(feature = "parquet")] mod job_helpers_ee; +#[cfg(feature = "parquet")] +mod job_helpers_oss; pub mod job_metrics; pub mod jobs; #[cfg(all(feature = "enterprise", feature = "kafka"))] mod kafka_triggers_ee; +#[cfg(all(feature = "enterprise", feature = "kafka"))] +mod kafka_triggers_oss; #[cfg(feature = "mqtt_trigger")] mod mqtt_triggers; #[cfg(all(feature = "enterprise", feature = "nats"))] mod nats_triggers_ee; +#[cfg(all(feature = "enterprise", feature = "nats"))] +mod nats_triggers_oss; #[cfg(feature = "oauth2")] -pub mod oauth2_ee; +mod oauth2_ee; +pub mod oauth2_oss; mod oidc_ee; +mod oidc_oss; mod raw_apps; mod resources; mod saml_ee; +mod saml_oss; mod schedule; mod scim_ee; +mod scim_oss; mod scripts; mod service_logs; mod settings; mod slack_approvals; #[cfg(feature = "smtp")] mod smtp_server_ee; +#[cfg(feature = "smtp")] +mod smtp_server_oss; #[cfg(all(feature = "enterprise", feature = "sqs_trigger"))] mod sqs_triggers_ee; +mod sqs_triggers_oss; mod teams_approvals_ee; +mod teams_approvals_oss; mod trigger_helpers; mod static_assets; #[cfg(all(feature = "stripe", feature = "enterprise"))] mod stripe_ee; +#[cfg(all(feature = "stripe", feature = "enterprise"))] +mod stripe_oss; mod teams_ee; +mod teams_oss; mod tracing_init; mod triggers; mod users; mod users_ee; +mod users_oss; mod utils; mod variables; pub mod webhook_util; @@ -146,6 +174,7 @@ mod workspaces; mod workspaces_ee; mod workspaces_export; mod workspaces_extra; +mod workspaces_oss; #[cfg(feature = "mcp")] mod mcp; @@ -218,9 +247,9 @@ type IndexReader = (); type ServiceLogIndexReader = (); #[cfg(feature = "tantivy")] -type IndexReader = windmill_indexer::completed_runs_ee::IndexReader; +type IndexReader = windmill_indexer::completed_runs_oss::IndexReader; #[cfg(feature = "tantivy")] -type ServiceLogIndexReader = windmill_indexer::service_logs_ee::ServiceLogIndexReader; +type ServiceLogIndexReader = windmill_indexer::service_logs_oss::ServiceLogIndexReader; pub async fn run_server( db: DB, @@ -278,7 +307,7 @@ pub async fn run_server( .allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION]) .allow_origin(Any); - let sp_extension = Arc::new(saml_ee::build_sp_extension().await?); + let sp_extension = Arc::new(saml_oss::build_sp_extension().await?); if server_mode { #[cfg(feature = "embedding")] @@ -317,7 +346,7 @@ pub async fn run_server( let job_helpers_service = { #[cfg(feature = "parquet")] { - job_helpers_ee::workspaced_service() + job_helpers_oss::workspaced_service() } #[cfg(not(feature = "parquet"))] @@ -329,7 +358,7 @@ pub async fn run_server( let kafka_triggers_service = { #[cfg(all(feature = "enterprise", feature = "kafka"))] { - kafka_triggers_ee::workspaced_service() + kafka_triggers_oss::workspaced_service() } #[cfg(not(all(feature = "enterprise", feature = "kafka")))] @@ -341,7 +370,7 @@ pub async fn run_server( let nats_triggers_service = { #[cfg(all(feature = "enterprise", feature = "nats"))] { - nats_triggers_ee::workspaced_service() + nats_triggers_oss::workspaced_service() } #[cfg(not(all(feature = "enterprise", feature = "nats")))] @@ -365,7 +394,7 @@ pub async fn run_server( let gcp_triggers_service = { #[cfg(all(feature = "enterprise", feature = "gcp_trigger"))] { - gcp_triggers_ee::workspaced_service() + gcp_triggers_oss::workspaced_service() } #[cfg(not(all(feature = "enterprise", feature = "gcp_trigger")))] @@ -377,7 +406,7 @@ pub async fn run_server( let sqs_triggers_service = { #[cfg(all(feature = "enterprise", feature = "sqs_trigger"))] { - sqs_triggers_ee::workspaced_service() + sqs_triggers_oss::workspaced_service() } #[cfg(not(all(feature = "enterprise", feature = "sqs_trigger")))] @@ -432,13 +461,13 @@ pub async fn run_server( #[cfg(all(feature = "enterprise", feature = "kafka"))] { let kafka_killpill_rx = killpill_rx.resubscribe(); - kafka_triggers_ee::start_kafka_consumers(db.clone(), kafka_killpill_rx); + kafka_triggers_oss::start_kafka_consumers(db.clone(), kafka_killpill_rx); } #[cfg(all(feature = "enterprise", feature = "nats"))] { let nats_killpill_rx = killpill_rx.resubscribe(); - nats_triggers_ee::start_nats_consumers(db.clone(), nats_killpill_rx); + nats_triggers_oss::start_nats_consumers(db.clone(), nats_killpill_rx); } #[cfg(feature = "postgres_trigger")] @@ -456,13 +485,13 @@ pub async fn run_server( #[cfg(all(feature = "enterprise", feature = "sqs_trigger"))] { let sqs_killpill_rx = killpill_rx.resubscribe(); - sqs_triggers_ee::start_sqs(db.clone(), sqs_killpill_rx); + sqs_triggers_oss::start_sqs(db.clone(), sqs_killpill_rx); } #[cfg(all(feature = "enterprise", feature = "gcp_trigger"))] { let gcp_killpill_rx = killpill_rx.resubscribe(); - gcp_triggers_ee::start_consuming_gcp_pubsub_event(db.clone(), gcp_killpill_rx); + gcp_triggers_oss::start_consuming_gcp_pubsub_event(db.clone(), gcp_killpill_rx); } } @@ -497,7 +526,7 @@ pub async fn run_server( #[cfg(feature = "agent_worker_server")] let (agent_workers_router, agent_workers_bg_processor, agent_workers_killpill_tx) = if server_mode { - agent_workers_ee::workspaced_service(db.clone(), _base_internal_url.clone()) + agent_workers_oss::workspaced_service(db.clone(), _base_internal_url.clone()) } else { (Router::new(), vec![], None) }; @@ -535,7 +564,7 @@ pub async fn run_server( .nest("/oauth", { #[cfg(feature = "oauth2")] { - oauth2_ee::workspaced_service() + oauth2_oss::workspaced_service() } #[cfg(not(feature = "oauth2"))] @@ -552,7 +581,7 @@ pub async fn run_server( ) .nest("/variables", variables::workspaced_service()) .nest("/workspaces", workspaces::workspaced_service()) - .nest("/oidc", oidc_ee::workspaced_service()) + .nest("/oidc", oidc_oss::workspaced_service()) .nest("/http_triggers", http_triggers_service) .nest("/websocket_triggers", websocket_triggers_service) .nest("/kafka_triggers", kafka_triggers_service) @@ -584,17 +613,17 @@ pub async fn run_server( .nest("/jobs", jobs::global_root_service()) .nest( "/srch/w/:workspace_id/index", - indexer_ee::workspaced_service(), + indexer_oss::workspaced_service(), ) - .nest("/srch/index", indexer_ee::global_service()) - .nest("/oidc", oidc_ee::global_service()) + .nest("/srch/index", indexer_oss::global_service()) + .nest("/oidc", oidc_oss::global_service()) .nest( "/saml", - saml_ee::global_service().layer(Extension(Arc::clone(&sp_extension))), + saml_oss::global_service().layer(Extension(Arc::clone(&sp_extension))), ) .nest( "/scim", - scim_ee::global_service() + scim_oss::global_service() .route_layer(axum::middleware::from_fn(has_scim_token)), ) .nest("/concurrency_groups", concurrency_groups::global_service()) @@ -602,7 +631,7 @@ pub async fn run_server( .nest("/apps_u", { #[cfg(feature = "enterprise")] { - apps_ee::global_unauthed_service() + apps_oss::global_unauthed_service() } #[cfg(not(feature = "enterprise"))] @@ -621,7 +650,7 @@ pub async fn run_server( .nest("/agent_workers", { #[cfg(feature = "agent_worker_server")] { - agent_workers_ee::global_service().layer(Extension(agent_cache.clone())) + agent_workers_oss::global_service().layer(Extension(agent_cache.clone())) } #[cfg(not(feature = "agent_worker_server"))] { @@ -646,7 +675,7 @@ pub async fn run_server( .nest("/teams", { #[cfg(feature = "enterprise")] { - teams_ee::teams_service() + teams_oss::teams_service() } #[cfg(not(feature = "enterprise"))] @@ -660,12 +689,12 @@ pub async fn run_server( ) .route( "/w/:workspace_id/jobs/teams_approval/:job_id", - get(teams_approvals_ee::request_teams_approval), + get(teams_approvals_oss::request_teams_approval), ) .nest("/w/:workspace_id/github_app", { #[cfg(feature = "enterprise")] { - git_sync_ee::workspaced_service() + git_sync_oss::workspaced_service() } #[cfg(not(feature = "enterprise"))] @@ -674,7 +703,7 @@ pub async fn run_server( .nest("/github_app", { #[cfg(feature = "enterprise")] { - git_sync_ee::global_service() + git_sync_oss::global_service() } #[cfg(not(feature = "enterprise"))] @@ -695,7 +724,7 @@ pub async fn run_server( .nest("/oauth", { #[cfg(feature = "oauth2")] { - oauth2_ee::global_service().layer(Extension(Arc::clone(&sp_extension))) + oauth2_oss::global_service().layer(Extension(Arc::clone(&sp_extension))) } #[cfg(not(feature = "oauth2"))] @@ -721,7 +750,7 @@ pub async fn run_server( { #[cfg(all(feature = "enterprise", feature = "gcp_trigger"))] { - gcp_triggers_ee::gcp_push_route_handler() + gcp_triggers_oss::gcp_push_route_handler() } #[cfg(not(all(feature = "enterprise", feature = "gcp_trigger")))] { @@ -842,7 +871,7 @@ async fn ee_license() -> &'static str { #[cfg(feature = "enterprise")] async fn ee_license() -> String { - use windmill_common::ee::{LICENSE_KEY_ID, LICENSE_KEY_VALID}; + use windmill_common::ee_oss::{LICENSE_KEY_ID, LICENSE_KEY_VALID}; if *LICENSE_KEY_VALID.read().await { LICENSE_KEY_ID.read().await.clone() diff --git a/backend/windmill-api/src/mqtt_triggers.rs b/backend/windmill-api/src/mqtt_triggers.rs index 9f3fd19827..70b78ca913 100644 --- a/backend/windmill-api/src/mqtt_triggers.rs +++ b/backend/windmill-api/src/mqtt_triggers.rs @@ -39,7 +39,7 @@ use sql_builder::{bind::Bind, SqlBuilder}; use sqlx::{FromRow, Type}; use std::collections::HashMap; use std::time::Duration; -use windmill_audit::{audit_ee::audit_log, ActionKind}; +use windmill_audit::{audit_oss::audit_log, ActionKind}; use windmill_common::{ db::UserDB, error::{self, JsonResult}, diff --git a/backend/windmill-api/src/nats_triggers_oss.rs b/backend/windmill-api/src/nats_triggers_oss.rs new file mode 100644 index 0000000000..649d3a3837 --- /dev/null +++ b/backend/windmill-api/src/nats_triggers_oss.rs @@ -0,0 +1,43 @@ +use crate::db::DB; +use axum::Router; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct NatsResourceAuth {} + +pub fn workspaced_service() -> Router { + Router::new() +} + +pub fn start_nats_consumers(_db: DB, mut _killpill_rx: tokio::sync::broadcast::Receiver<()>) -> () { + // implementation is not open source +} + +#[derive(Serialize, Deserialize)] +pub enum NatsTriggerConfigConnection {} + +#[derive(Serialize, Clone)] +pub struct NatsTrigger { + pub workspace_id: String, + pub path: String, + pub nats_resource_path: String, + pub subjects: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub stream_name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub consumer_name: Option, + pub use_jetstream: bool, + pub script_path: String, + pub is_flow: bool, + pub edited_by: String, + pub email: String, + pub edited_at: chrono::DateTime, + #[serde(skip_serializing_if = "Option::is_none")] + pub server_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub last_server_ping: Option>, + pub extra_perms: serde_json::Value, + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + pub enabled: bool, +} \ No newline at end of file diff --git a/backend/windmill-api/src/oauth2_oss.rs b/backend/windmill-api/src/oauth2_oss.rs new file mode 100644 index 0000000000..49d2155cf3 --- /dev/null +++ b/backend/windmill-api/src/oauth2_oss.rs @@ -0,0 +1,184 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2022 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ + +use std::{collections::HashMap, fmt::Debug}; + +use axum::{routing::get, Json, Router}; +use hmac::Mac; + +#[cfg(feature = "oauth2")] +use itertools::Itertools; +#[cfg(feature = "oauth2")] +use oauth2::{Client as OClient, *}; +use serde::{Deserialize, Serialize}; +use sqlx::{Postgres, Transaction}; +#[cfg(feature = "oauth2")] +use windmill_common::more_serde::maybe_number_opt; + +#[cfg(feature = "oauth2")] +use crate::OAUTH_CLIENTS; +use windmill_common::error; +use windmill_common::oauth2::*; + +use crate::db::DB; +use std::str; + +pub fn global_service() -> Router { + Router::new() + .route("/list_logins", get(list_logins)) + .route("/list_connects", get(list_connects)) +} + +pub fn workspaced_service() -> Router { + Router::new() +} + +#[cfg(feature = "oauth2")] +#[derive(Debug, Clone)] +pub struct ClientWithScopes { + _client: OClient, + _scopes: Vec, + _extra_params: Option>, + _extra_params_callback: Option>, + _allowed_domains: Option>, + _userinfo_url: Option, +} +#[cfg(feature = "oauth2")] +pub type BasicClientsMap = HashMap; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct OAuthConfig { + auth_url: String, + token_url: String, + userinfo_url: Option, + scopes: Option>, + extra_params: Option>, + extra_params_callback: Option>, + req_body_auth: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct OAuthClient { + id: String, + secret: String, + allowed_domains: Option>, + connect_config: Option, + login_config: Option, +} + +#[cfg(feature = "oauth2")] +#[derive(Debug)] +pub struct AllClients { + pub logins: BasicClientsMap, + pub connects: BasicClientsMap, + pub slack: Option, +} + +#[cfg(feature = "oauth2")] +pub async fn build_oauth_clients( + _base_url: &str, + _oauths_from_config: Option>, + _db: &DB, +) -> anyhow::Result { + // Implementation is not open source + return Ok(AllClients { + logins: HashMap::default(), + connects: HashMap::default(), + slack: None, + }); +} + +#[cfg(feature = "oauth2")] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct TokenResponse { + access_token: AccessToken, + #[serde(deserialize_with = "maybe_number_opt")] + #[serde(default)] + expires_in: Option, + refresh_token: Option, + #[serde(deserialize_with = "helpers::deserialize_space_delimited_vec")] + #[serde(serialize_with = "helpers::serialize_space_delimited_vec")] + #[serde(default)] + scope: Option>, +} + +#[derive(Serialize)] +struct Logins { + oauth: Vec, + saml: Option, +} +async fn list_logins() -> error::JsonResult { + // Implementation is not open source + return Ok(Json(Logins { oauth: vec![], saml: None })); +} + +#[cfg(feature = "oauth2")] +async fn list_connects() -> error::JsonResult> { + Ok(Json( + (&OAUTH_CLIENTS.read().await.connects) + .keys() + .map(|x| x.to_owned()) + .collect_vec(), + )) +} + +#[cfg(not(feature = "oauth2"))] +async fn list_connects() -> error::JsonResult> { + // Implementation is not open source + return Ok(Json(vec![])); +} + +pub async fn _refresh_token<'c>( + _tx: Transaction<'c, Postgres>, + _path: &str, + _w_id: &str, + _id: i32, + _db: &DB, +) -> error::Result { + // Implementation is not open source + Err(error::Error::BadRequest( + "Not implemented in Windmill's Open Source repository".to_string(), + )) +} + +pub async fn check_nb_of_user(db: &DB) -> error::Result<()> { + let nb_users_sso = + sqlx::query_scalar!("SELECT COUNT(*) FROM password WHERE login_type != 'password'",) + .fetch_one(db) + .await?; + if nb_users_sso.unwrap_or(0) >= 10 { + return Err(error::Error::BadRequest( + "You have reached the maximum number of oauth users accounts (10) without an enterprise license" + .to_string(), + )); + } + + let nb_users = sqlx::query_scalar!("SELECT COUNT(*) FROM password",) + .fetch_one(db) + .await?; + if nb_users.unwrap_or(0) >= 50 { + return Err(error::Error::BadRequest( + "You have reached the maximum number of accounts (50) without an enterprise license" + .to_string(), + )); + } + return Ok(()); +} + +#[derive(Clone, Debug)] +pub struct SlackVerifier { + _mac: HmacSha256, +} + +impl SlackVerifier { + pub fn new>(secret: S) -> anyhow::Result { + HmacSha256::new_from_slice(secret.as_ref()) + .map(|mac| SlackVerifier { _mac: mac }) + .map_err(|_| anyhow::anyhow!("invalid secret")) + } +} diff --git a/backend/windmill-api/src/oidc_oss.rs b/backend/windmill-api/src/oidc_oss.rs new file mode 100644 index 0000000000..248b990f54 --- /dev/null +++ b/backend/windmill-api/src/oidc_oss.rs @@ -0,0 +1,17 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2023 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ + +use axum::Router; + +pub fn global_service() -> Router { + Router::new() +} + +pub fn workspaced_service() -> Router { + Router::new() +} diff --git a/backend/windmill-api/src/postgres_triggers/handler.rs b/backend/windmill-api/src/postgres_triggers/handler.rs index 933582670c..f9c6a47103 100644 --- a/backend/windmill-api/src/postgres_triggers/handler.rs +++ b/backend/windmill-api/src/postgres_triggers/handler.rs @@ -20,12 +20,12 @@ use rust_postgres::types::Type; use serde::{Deserialize, Deserializer, Serialize}; use sql_builder::{bind::Bind, SqlBuilder}; use sqlx::{postgres::types::Oid, FromRow, PgConnection}; -use windmill_audit::{audit_ee::audit_log, ActionKind}; +use windmill_audit::{audit_oss::audit_log, ActionKind}; use windmill_common::error::Error; use windmill_common::{ db::UserDB, error::{self, JsonResult, Result}, - utils::{not_found_if_none, paginate, Pagination, StripPath, empty_as_none}, + utils::{empty_as_none, not_found_if_none, paginate, Pagination, StripPath}, worker::CLOUD_HOSTED, }; use windmill_git_sync::{handle_deployment_metadata, DeployedObject}; diff --git a/backend/windmill-api/src/raw_apps.rs b/backend/windmill-api/src/raw_apps.rs index bb2763b73d..3a895bab97 100644 --- a/backend/windmill-api/src/raw_apps.rs +++ b/backend/windmill-api/src/raw_apps.rs @@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize}; use sql_builder::{bind::Bind, SqlBuilder}; use sqlx::FromRow; use std::str; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::{ apps::ListAppQuery, diff --git a/backend/windmill-api/src/resources.rs b/backend/windmill-api/src/resources.rs index 8a2fab0434..d2d58c918d 100644 --- a/backend/windmill-api/src/resources.rs +++ b/backend/windmill-api/src/resources.rs @@ -26,7 +26,7 @@ use serde_json::{value::RawValue, Value}; use sql_builder::{bind::Bind, quote, SqlBuilder}; use sqlx::{FromRow, Postgres, Transaction}; use uuid::Uuid; -use windmill_audit::audit_ee::{audit_log, AuditAuthor}; +use windmill_audit::audit_oss::{audit_log, AuditAuthor}; use windmill_audit::ActionKind; use windmill_common::{ db::UserDB, diff --git a/backend/windmill-api/src/saml_oss.rs b/backend/windmill-api/src/saml_oss.rs new file mode 100644 index 0000000000..b3f1d4653c --- /dev/null +++ b/backend/windmill-api/src/saml_oss.rs @@ -0,0 +1,25 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2023 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ +#![allow(non_snake_case)] + +use axum::{routing::post, Router}; + +pub struct ServiceProviderExt(); + +pub async fn build_sp_extension() -> anyhow::Result { + return Ok(ServiceProviderExt()); +} + +pub fn global_service() -> Router { + Router::new().route("/acs", post(acs)) +} + +pub async fn acs() -> String { + // Implementation is not open source as it is a Windmill Enterprise Edition feature + "SAML available only in enterprise version".to_string() +} diff --git a/backend/windmill-api/src/schedule.rs b/backend/windmill-api/src/schedule.rs index 90d91c846c..3cb13798d9 100644 --- a/backend/windmill-api/src/schedule.rs +++ b/backend/windmill-api/src/schedule.rs @@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize}; use sql_builder::{prelude::Bind, SqlBuilder}; use sqlx::{Postgres, Transaction}; use std::str::FromStr; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::{ db::UserDB, diff --git a/backend/windmill-api/src/scim_oss.rs b/backend/windmill-api/src/scim_oss.rs new file mode 100644 index 0000000000..f11097f874 --- /dev/null +++ b/backend/windmill-api/src/scim_oss.rs @@ -0,0 +1,23 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2023 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ + +use axum::{middleware::Next, response::Response, routing::get, Router}; +use hyper::Request; + +pub fn global_service() -> Router { + Router::new().route("/ee", get(ee)) +} + +pub async fn ee() -> String { + return "Enterprise Edition".to_string(); +} + +pub async fn has_scim_token(_request: Request, _next: Next) -> Response { + //Not implemented in open-source version + todo!() +} diff --git a/backend/windmill-api/src/scripts.rs b/backend/windmill-api/src/scripts.rs index a827fa5079..27ab296700 100644 --- a/backend/windmill-api/src/scripts.rs +++ b/backend/windmill-api/src/scripts.rs @@ -38,7 +38,7 @@ use std::{ hash::{Hash, Hasher}, sync::Arc, }; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_worker::process_relative_imports; diff --git a/backend/windmill-api/src/settings.rs b/backend/windmill-api/src/settings.rs index b589713b91..9dfb687e51 100644 --- a/backend/windmill-api/src/settings.rs +++ b/backend/windmill-api/src/settings.rs @@ -10,7 +10,7 @@ use std::time::Duration; use crate::{ db::{ApiAuthed, DB}, - ee::validate_license_key, + ee_oss::validate_license_key, utils::{generate_instance_username_for_all_users, require_super_admin}, HTTP_CLIENT, }; @@ -29,9 +29,9 @@ use crate::utils::require_devops_role; use serde::Deserialize; #[cfg(feature = "enterprise")] -use windmill_common::ee::{send_critical_alert, CriticalAlertKind, CriticalErrorChannel}; +use windmill_common::ee_oss::{send_critical_alert, CriticalAlertKind, CriticalErrorChannel}; use windmill_common::{ - email_ee::send_email, + email_oss::send_email, error::{self, JsonResult, Result}, global_settings::{ AUTOMATE_USERNAME_CREATION_SETTING, CRITICAL_ALERT_MUTE_UI_SETTING, EMAIL_DOMAIN_SETTING, @@ -326,10 +326,10 @@ async fn list_global_settings() -> JsonResult { pub async fn send_stats(Extension(db): Extension, authed: ApiAuthed) -> Result { require_super_admin(&db, &authed.email).await?; - windmill_common::stats_ee::send_stats( + windmill_common::stats_oss::send_stats( &HTTP_CLIENT, &db, - windmill_common::stats_ee::SendStatsReason::Manual, + windmill_common::stats_oss::SendStatsReason::Manual, ) .await?; @@ -390,11 +390,11 @@ pub async fn renew_license_key( authed: ApiAuthed, ) -> Result { require_super_admin(&db, &authed.email).await?; - let result = windmill_common::ee::renew_license_key( + let result = windmill_common::ee_oss::renew_license_key( &HTTP_CLIENT, &db, license_key, - windmill_common::ee::RenewReason::Manual, + windmill_common::ee_oss::RenewReason::Manual, ) .await; @@ -424,7 +424,7 @@ pub async fn create_customer_portal_session( Query(LicenseQuery { license_key }): Query, ) -> Result { let url = - windmill_common::ee::create_customer_portal_session(&HTTP_CLIENT, license_key).await?; + windmill_common::ee_oss::create_customer_portal_session(&HTTP_CLIENT, license_key).await?; return Ok(url); } diff --git a/backend/windmill-api/src/smtp_server_oss.rs b/backend/windmill-api/src/smtp_server_oss.rs new file mode 100644 index 0000000000..48e274f6a1 --- /dev/null +++ b/backend/windmill-api/src/smtp_server_oss.rs @@ -0,0 +1,20 @@ +use crate::{auth::AuthCache, db::DB}; +use std::{net::SocketAddr, sync::Arc}; +use windmill_common::db::UserDB; + +pub struct SmtpServer { + pub auth_cache: Arc, + pub db: DB, + pub user_db: UserDB, + pub base_internal_url: String, +} + +impl SmtpServer { + pub async fn start_listener_thread(self: Arc, _addr: SocketAddr) -> anyhow::Result<()> { + let _ = self.auth_cache; + let _ = self.db; + let _ = self.user_db; + let _ = self.base_internal_url; + Err(anyhow::anyhow!("Implementation not open source")) + } +} diff --git a/backend/windmill-api/src/sqs_triggers_oss.rs b/backend/windmill-api/src/sqs_triggers_oss.rs new file mode 100644 index 0000000000..da9b288f6b --- /dev/null +++ b/backend/windmill-api/src/sqs_triggers_oss.rs @@ -0,0 +1,33 @@ +use crate::db::DB; +use axum::Router; +use serde::{Deserialize, Serialize}; +use windmill_common::auth::aws::AwsAuthResourceType; + + +pub fn workspaced_service() -> Router { + Router::new() +} + +pub fn start_sqs(_db: DB, mut _killpill_rx: tokio::sync::broadcast::Receiver<()>) -> () { + // implementation is not open source +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct SqsTrigger { + pub queue_url: String, + pub aws_auth_resource_type: AwsAuthResourceType, + pub aws_resource_path: String, + pub message_attributes: Option>, + pub path: String, + pub script_path: String, + pub is_flow: bool, + pub workspace_id: String, + pub edited_by: String, + pub email: String, + pub edited_at: chrono::DateTime, + pub extra_perms: Option, + pub error: Option, + pub server_id: Option, + pub last_server_ping: Option>, + pub enabled: bool, +} \ No newline at end of file diff --git a/backend/windmill-api/src/stripe_oss.rs b/backend/windmill-api/src/stripe_oss.rs new file mode 100644 index 0000000000..6934cad3bc --- /dev/null +++ b/backend/windmill-api/src/stripe_oss.rs @@ -0,0 +1,5 @@ +use axum::Router; + +pub fn add_stripe_routes(router: Router) -> Router { + return router; +} diff --git a/backend/windmill-api/src/teams_approvals_oss.rs b/backend/windmill-api/src/teams_approvals_oss.rs new file mode 100644 index 0000000000..05698b98e3 --- /dev/null +++ b/backend/windmill-api/src/teams_approvals_oss.rs @@ -0,0 +1,7 @@ +use hyper::StatusCode; + +use windmill_common::error::Error; + +pub async fn request_teams_approval() -> Result { + Err(Error::InternalErr("enterprise feature only".to_string())) +} \ No newline at end of file diff --git a/backend/windmill-api/src/teams_oss.rs b/backend/windmill-api/src/teams_oss.rs new file mode 100644 index 0000000000..46cbe72059 --- /dev/null +++ b/backend/windmill-api/src/teams_oss.rs @@ -0,0 +1,39 @@ +use http::status::StatusCode; +#[cfg(feature = "enterprise")] +use axum::Router; +use windmill_common::error::Error; + +pub async fn edit_teams_command() -> Result { + return Err(Error::BadRequest( + "Teams only available on enterprise".to_string(), + )); +} + +pub async fn workspaces_list_available_teams_ids() -> Result { + return Err(Error::BadRequest( + "Teams only available on enterprise".to_string(), + )); +} + +pub async fn connect_teams() -> Result { + return Err(Error::BadRequest( + "Teams only available on enterprise".to_string(), + )); +} + +pub async fn run_teams_message_test_job() -> Result { + return Err(Error::BadRequest( + "Teams only available on enterprise".to_string(), + )); +} + +pub async fn workspaces_list_available_teams_channels() -> Result { + return Err(Error::BadRequest( + "Teams only available on enterprise".to_string(), + )); +} + +#[cfg(feature = "enterprise")] +pub fn teams_service() -> Router { + Router::new() +} \ No newline at end of file diff --git a/backend/windmill-api/src/users.rs b/backend/windmill-api/src/users.rs index 1f8529fe6a..f9aa6d3045 100644 --- a/backend/windmill-api/src/users.rs +++ b/backend/windmill-api/src/users.rs @@ -42,7 +42,7 @@ use sqlx::FromRow; use time::OffsetDateTime; use tower_cookies::{Cookie, Cookies}; use tracing::Instrument; -use windmill_audit::audit_ee::{audit_log, AuditAuthor}; +use windmill_audit::audit_oss::{audit_log, AuditAuthor}; use windmill_audit::ActionKind; use windmill_common::auth::fetch_authed_from_permissioned_as; use windmill_common::global_settings::AUTOMATE_USERNAME_CREATION_SETTING; @@ -1507,7 +1507,7 @@ async fn create_user( Extension(argon2): Extension>>, Json(nu): Json, ) -> Result<(StatusCode, String)> { - crate::users_ee::create_user(authed, db, webhook, argon2, nu).await + crate::users_oss::create_user(authed, db, webhook, argon2, nu).await } async fn delete_workspace_user( @@ -1581,7 +1581,7 @@ async fn set_password( Json(ep): Json, ) -> Result { let email = authed.email.clone(); - crate::users_ee::set_password(db, argon2, authed, &email, ep).await + crate::users_oss::set_password(db, argon2, authed, &email, ep).await } async fn set_password_of_user( @@ -1592,7 +1592,7 @@ async fn set_password_of_user( Json(ep): Json, ) -> Result { require_super_admin(&db, &authed.email).await?; - crate::users_ee::set_password(db, argon2, authed, &email, ep).await + crate::users_oss::set_password(db, argon2, authed, &email, ep).await } async fn set_login_type( diff --git a/backend/windmill-api/src/users_oss.rs b/backend/windmill-api/src/users_oss.rs new file mode 100644 index 0000000000..7a11239a2f --- /dev/null +++ b/backend/windmill-api/src/users_oss.rs @@ -0,0 +1,41 @@ +use std::sync::Arc; + +use crate::db::ApiAuthed; + +use crate::users::{EditPassword, NewUser}; +use crate::{db::DB, webhook_util::WebhookShared}; +use argon2::Argon2; + +use http::StatusCode; + +use windmill_common::error::{Error, Result}; + +pub async fn create_user( + _authed: ApiAuthed, + _db: DB, + _webhook: WebhookShared, + _argon2: Arc>, + mut _nu: NewUser, +) -> Result<(StatusCode, String)> { + Err(Error::internal_err( + "Not implemented in Windmill's Open Source repository".to_string(), + )) +} + +pub async fn set_password( + _db: DB, + _argon2: Arc>, + _authed: ApiAuthed, + _user_email: &str, + _ep: EditPassword, +) -> Result { + Err(Error::internal_err( + "Not implemented in Windmill's Open Source repository".to_string(), + )) +} + +pub fn send_email_if_possible(_subject: &str, _content: &str, _to: &str) { + tracing::warn!( + "send_email_if_possible is not implemented in Windmill's Open Source repository" + ); +} diff --git a/backend/windmill-api/src/variables.rs b/backend/windmill-api/src/variables.rs index e810f95750..7dc6a85b49 100644 --- a/backend/windmill-api/src/variables.rs +++ b/backend/windmill-api/src/variables.rs @@ -20,7 +20,7 @@ use axum::{ use hyper::StatusCode; use serde_json::Value; -use windmill_audit::audit_ee::{audit_log, AuditAuthorable}; +use windmill_audit::audit_oss::{audit_log, AuditAuthorable}; use windmill_audit::ActionKind; use windmill_common::{ db::UserDB, @@ -186,7 +186,7 @@ async fn get_variable( #[cfg(feature = "oauth2")] { Some( - crate::oauth2_ee::_refresh_token( + crate::oauth2_oss::_refresh_token( tx, &variable.path, &w_id, @@ -653,7 +653,7 @@ pub async fn get_value_internal<'c>( if variable.is_expired.unwrap_or(false) && variable.account.is_some() { #[cfg(feature = "oauth2")] { - crate::oauth2_ee::_refresh_token( + crate::oauth2_oss::_refresh_token( tx, &variable.path, &w_id, diff --git a/backend/windmill-api/src/websocket_triggers.rs b/backend/windmill-api/src/websocket_triggers.rs index 8bd165844c..8c263b1f62 100644 --- a/backend/windmill-api/src/websocket_triggers.rs +++ b/backend/windmill-api/src/websocket_triggers.rs @@ -20,7 +20,7 @@ use std::{collections::HashMap, fmt}; use tokio::net::TcpStream; use tokio_tungstenite::{connect_async, tungstenite::Message, MaybeTlsStream, WebSocketStream}; use uuid::Uuid; -use windmill_audit::{audit_ee::audit_log, ActionKind}; +use windmill_audit::{audit_oss::audit_log, ActionKind}; use windmill_common::{ db::UserDB, error::{self, to_anyhow, JsonResult}, diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index 75c9a8d034..b8e8a813f3 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -10,7 +10,7 @@ use std::collections::HashMap; use crate::ai::{AIConfig, AI_REQUEST_CACHE}; use crate::db::ApiAuthed; -use crate::users_ee::send_email_if_possible; +use crate::users_oss::send_email_if_possible; use crate::utils::get_instance_username_or_create_pending; use crate::BASE_URL; use crate::{ @@ -30,7 +30,7 @@ use chrono::Utc; use regex::Regex; use uuid::Uuid; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::db::UserDB; use windmill_common::s3_helpers::LargeFileStorage; @@ -58,7 +58,7 @@ use sqlx::{FromRow, Postgres, Transaction}; use windmill_common::oauth2::InstanceEvent; use windmill_common::utils::not_found_if_none; -use crate::teams_ee::{ +use crate::teams_oss::{ connect_teams, edit_teams_command, run_teams_message_test_job, workspaces_list_available_teams_channels, workspaces_list_available_teams_ids, }; @@ -145,7 +145,7 @@ pub fn workspaced_service() -> Router { #[cfg(all(feature = "stripe", feature = "enterprise"))] { - crate::stripe_ee::add_stripe_routes(router) + crate::stripe_oss::add_stripe_routes(router) } #[cfg(not(feature = "stripe"))] @@ -640,7 +640,7 @@ async fn edit_auto_invite( Path(w_id): Path, Json(ea): Json, ) -> Result { - crate::workspaces_ee::edit_auto_invite(authed, db, w_id, ea).await + crate::workspaces_oss::edit_auto_invite(authed, db, w_id, ea).await } async fn edit_webhook( diff --git a/backend/windmill-api/src/workspaces_export.rs b/backend/windmill-api/src/workspaces_export.rs index cd2be0f708..b3ad6dbdd7 100644 --- a/backend/windmill-api/src/workspaces_export.rs +++ b/backend/windmill-api/src/workspaces_export.rs @@ -622,7 +622,7 @@ pub(crate) async fn tarball_workspace( #[cfg(all(feature = "enterprise", feature = "kafka"))] { let kafka_triggers = sqlx::query_as!( - crate::kafka_triggers_ee::KafkaTrigger, + crate::kafka_triggers_oss::KafkaTrigger, "SELECT * FROM kafka_trigger WHERE workspace_id = $1", &w_id @@ -644,7 +644,7 @@ pub(crate) async fn tarball_workspace( #[cfg(all(feature = "enterprise", feature = "sqs_trigger"))] { let sqs_triggers = sqlx::query_as!( - crate::sqs_triggers_ee::SqsTrigger, + crate::sqs_triggers_oss::SqsTrigger, r#" SELECT aws_auth_resource_type AS "aws_auth_resource_type: _", @@ -684,7 +684,7 @@ pub(crate) async fn tarball_workspace( #[cfg(all(feature = "enterprise", feature = "gcp_trigger"))] { let gcp_triggers = sqlx::query_as!( - crate::gcp_triggers_ee::GcpTrigger, + crate::gcp_triggers_oss::GcpTrigger, r#" SELECT gcp_resource_path, @@ -726,7 +726,7 @@ pub(crate) async fn tarball_workspace( #[cfg(all(feature = "enterprise", feature = "nats"))] { let nats_triggers = sqlx::query_as!( - crate::nats_triggers_ee::NatsTrigger, + crate::nats_triggers_oss::NatsTrigger, "SELECT * FROM nats_trigger WHERE workspace_id = $1", &w_id diff --git a/backend/windmill-api/src/workspaces_extra.rs b/backend/windmill-api/src/workspaces_extra.rs index 07570df5c3..51a224d0e2 100644 --- a/backend/windmill-api/src/workspaces_extra.rs +++ b/backend/windmill-api/src/workspaces_extra.rs @@ -8,7 +8,7 @@ use axum::{ Json, }; -use windmill_audit::audit_ee::audit_log; +use windmill_audit::audit_oss::audit_log; use windmill_audit::ActionKind; use windmill_common::worker::CLOUD_HOSTED; diff --git a/backend/windmill-api/src/workspaces_oss.rs b/backend/windmill-api/src/workspaces_oss.rs new file mode 100644 index 0000000000..aa8799e233 --- /dev/null +++ b/backend/windmill-api/src/workspaces_oss.rs @@ -0,0 +1,15 @@ +use crate::{ + db::{ApiAuthed, DB}, + workspaces::EditAutoInvite, +}; + +pub async fn edit_auto_invite( + _authed: ApiAuthed, + _db: DB, + _w_id: String, + _ea: EditAutoInvite, +) -> windmill_common::error::Result { + Err(windmill_common::error::Error::internal_err( + "Not implemented on OSS".to_string(), + )) +} diff --git a/backend/windmill-audit/src/audit_oss.rs b/backend/windmill-audit/src/audit_oss.rs new file mode 100644 index 0000000000..027688f568 --- /dev/null +++ b/backend/windmill-audit/src/audit_oss.rs @@ -0,0 +1,74 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2022 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ +use std::collections::HashMap; +use windmill_common::{ + error::{Error, Result}, + utils::Pagination, +}; + +use crate::{ActionKind, AuditLog, ListAuditLogQuery}; +use sqlx::{Postgres, Transaction}; + +#[derive(Clone)] +pub struct AuditAuthor { + pub username: String, + pub email: String, + pub username_override: Option, +} + +impl AuditAuthorable for AuditAuthor { + fn email(&self) -> &str { + &self.email + } + + fn username(&self) -> &str { + &self.username + } + + fn username_override(&self) -> Option<&str> { + self.username_override.as_deref() + } +} + +pub trait AuditAuthorable { + fn username(&self) -> &str; + fn email(&self) -> &str; + fn username_override(&self) -> Option<&str>; +} + +#[tracing::instrument(level = "trace", skip_all)] +pub async fn audit_log<'c, E: sqlx::Executor<'c, Database = Postgres>>( + _db: E, + _author: &impl AuditAuthorable, + mut _operation: &str, + _action_kind: ActionKind, + _w_id: &str, + mut _resource: Option<&str>, + _parameters: Option>, +) -> Result<()> { + // Implementation is not open source as Audit logs is a Windmill Enterprise Edition feature + Ok(()) +} + +pub async fn list_audit( + _tx: Transaction<'_, Postgres>, + _w_id: String, + _pagination: Pagination, + _lq: ListAuditLogQuery, +) -> Result> { + // Implementation is not open source as Audit logs is a Windmill Enterprise Edition feature + return Ok(vec![]); +} + +pub async fn get_audit(tx: Transaction<'_, Postgres>, _id: i32, _w_id: &str) -> Result { + // Implementation is not open source as Audit logs is a Windmill Enterprise Edition feature + tx.commit().await?; + Err(Error::NotFound( + "Audit log not not available in Windmill Community edition".to_string(), + )) +} diff --git a/backend/windmill-audit/src/lib.rs b/backend/windmill-audit/src/lib.rs index 10894798fb..8a5155bd85 100644 --- a/backend/windmill-audit/src/lib.rs +++ b/backend/windmill-audit/src/lib.rs @@ -1,7 +1,8 @@ use serde::{Deserialize, Serialize}; use sqlx::FromRow; -pub mod audit_ee; +mod audit_ee; +pub mod audit_oss; #[derive(sqlx::Type, Serialize, Deserialize, Debug)] #[sqlx(type_name = "ACTION_KIND", rename_all = "lowercase")] diff --git a/backend/windmill-autoscaling/src/autoscaling_oss.rs b/backend/windmill-autoscaling/src/autoscaling_oss.rs new file mode 100644 index 0000000000..1c9defbede --- /dev/null +++ b/backend/windmill-autoscaling/src/autoscaling_oss.rs @@ -0,0 +1,6 @@ +use windmill_common::DB; + +pub async fn apply_all_autoscaling(_db: &DB) -> anyhow::Result<()> { + // Autoscaling is an ee feature + Ok(()) +} diff --git a/backend/windmill-autoscaling/src/lib.rs b/backend/windmill-autoscaling/src/lib.rs index 28b9319244..f488287b1d 100644 --- a/backend/windmill-autoscaling/src/lib.rs +++ b/backend/windmill-autoscaling/src/lib.rs @@ -1,2 +1,3 @@ mod autoscaling_ee; -pub use autoscaling_ee::*; +mod autoscaling_oss; +pub use autoscaling_oss::*; diff --git a/backend/windmill-common/src/ee.rs b/backend/windmill-common/src/ee.rs index 7acb430f1b..a7d5503a86 100644 --- a/backend/windmill-common/src/ee.rs +++ b/backend/windmill-common/src/ee.rs @@ -1,6 +1,6 @@ #[cfg(feature = "enterprise")] use crate::db::DB; -use crate::ee::LicensePlan::Community; +use crate::ee_oss::LicensePlan::{self, Community}; #[cfg(feature = "enterprise")] use crate::error; use serde::Deserialize; @@ -13,12 +13,6 @@ lazy_static::lazy_static! { pub static ref LICENSE_KEY: Arc> = Arc::new(RwLock::new("".to_string())); } -pub enum LicensePlan { - Community, - Pro, - Enterprise, -} - pub async fn get_license_plan() -> LicensePlan { // Implementation is not open source return Community; @@ -100,7 +94,11 @@ pub async fn worker_groups_alerts(_db: &DB) {} pub async fn jobs_waiting_alerts(_db: &DB) {} #[cfg(feature = "enterprise")] -pub async fn low_disk_alerts(_db: &DB, _server_mode: bool, _worker_mode: bool, _workers: Vec) { +pub async fn low_disk_alerts( + _db: &DB, + _server_mode: bool, + _worker_mode: bool, + _workers: Vec, +) { // Implementation is not open source } - diff --git a/backend/windmill-common/src/ee_oss.rs b/backend/windmill-common/src/ee_oss.rs new file mode 100644 index 0000000000..40d0377f80 --- /dev/null +++ b/backend/windmill-common/src/ee_oss.rs @@ -0,0 +1,110 @@ +#[cfg(feature = "enterprise")] +use crate::db::DB; +use crate::ee_oss::LicensePlan::Community; +#[cfg(feature = "enterprise")] +use crate::error; +use serde::Deserialize; +use std::sync::Arc; +use tokio::sync::RwLock; + +lazy_static::lazy_static! { + pub static ref LICENSE_KEY_VALID: Arc> = Arc::new(RwLock::new(true)); + pub static ref LICENSE_KEY_ID: Arc> = Arc::new(RwLock::new("".to_string())); + pub static ref LICENSE_KEY: Arc> = Arc::new(RwLock::new("".to_string())); +} + +pub enum LicensePlan { + Community, + Pro, + Enterprise, +} + +pub async fn get_license_plan() -> LicensePlan { + // Implementation is not open source + return Community; +} + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum CriticalErrorChannel { + Email { email: String }, + Slack { slack_channel: String }, + Teams { teams_channel: TeamsChannel }, +} + +#[derive(Deserialize)] +pub struct TeamsChannel { + pub team_id: String, + pub team_name: String, + pub channel_id: String, + pub channel_name: String, +} + +pub enum CriticalAlertKind { + #[cfg(feature = "enterprise")] + CriticalError, + #[cfg(feature = "enterprise")] + RecoveredCriticalError, +} + +#[cfg(feature = "enterprise")] +pub async fn send_critical_alert( + _error_message: String, + _db: &DB, + _kind: CriticalAlertKind, + _channels: Option>, +) { +} + +#[cfg(feature = "enterprise")] +pub async fn maybe_renew_license_key_on_start( + _http_client: &reqwest::Client, + _db: &crate::db::DB, + force_renew_now: bool, +) -> bool { + // Implementation is not open source + force_renew_now +} + +#[cfg(feature = "enterprise")] +pub enum RenewReason { + Manual, + Schedule, + OnStart, +} + +#[cfg(feature = "enterprise")] +pub async fn renew_license_key( + _http_client: &reqwest::Client, + _db: &crate::db::DB, + _key: Option, + _reason: RenewReason, +) -> String { + // Implementation is not open source + "".to_string() +} + +#[cfg(feature = "enterprise")] +pub async fn create_customer_portal_session( + _http_client: &reqwest::Client, + _key: Option, +) -> error::Result { + // Implementation is not open source + Ok("".to_string()) +} + +#[cfg(feature = "enterprise")] +pub async fn worker_groups_alerts(_db: &DB) {} + +#[cfg(feature = "enterprise")] +pub async fn jobs_waiting_alerts(_db: &DB) {} + +#[cfg(feature = "enterprise")] +pub async fn low_disk_alerts( + _db: &DB, + _server_mode: bool, + _worker_mode: bool, + _workers: Vec, +) { + // Implementation is not open source +} diff --git a/backend/windmill-common/src/email_oss.rs b/backend/windmill-common/src/email_oss.rs new file mode 100644 index 0000000000..42aebbeec3 --- /dev/null +++ b/backend/windmill-common/src/email_oss.rs @@ -0,0 +1,11 @@ +use crate::server::Smtp; + +pub async fn send_email( + _subject: &str, + _content: &str, + _to: Vec, + _smtp: Smtp, + _client_timeout: Option, +) -> crate::error::Result<()> { + Ok(()) +} diff --git a/backend/windmill-common/src/job_s3_helpers_oss.rs b/backend/windmill-common/src/job_s3_helpers_oss.rs new file mode 100644 index 0000000000..d5d6ac4052 --- /dev/null +++ b/backend/windmill-common/src/job_s3_helpers_oss.rs @@ -0,0 +1,34 @@ +use crate::s3_helpers::{ObjectStoreResource, StorageResourceType}; + +pub async fn get_s3_resource_internal<'c>( + _resource_type: StorageResourceType, + _s3_resource_value_raw: serde_json::Value, + _gen_token: TokenGenerator<'c>, + _db: &crate::DB, +) -> crate::error::Result { + todo!() +} + +pub enum TokenGenerator<'c> { + AsClient(&'c crate::client::AuthedClient), + AsServerInstance(), +} + +impl<'c> TokenGenerator<'c> { + pub async fn gen_token( + &self, + _audience: &str, + _db: Option<&crate::DB>, + ) -> anyhow::Result { + todo!() + } +} + +#[cfg(feature = "parquet")] +pub(crate) async fn generate_s3_aws_oidc_resource<'c>( + _clone: crate::s3_helpers::S3AwsOidcResource, + _token_generator: TokenGenerator<'c>, + _init_private_key: Option<&sqlx::Pool>, +) -> crate::error::Result { + todo!() +} diff --git a/backend/windmill-common/src/lib.rs b/backend/windmill-common/src/lib.rs index 6d92cd8f55..3825acf29f 100644 --- a/backend/windmill-common/src/lib.rs +++ b/backend/windmill-common/src/lib.rs @@ -19,7 +19,7 @@ use std::{ use tokio::sync::broadcast; -use ee::CriticalErrorChannel; +use ee_oss::CriticalErrorChannel; use error::Error; use scripts::ScriptLang; use sqlx::{Pool, Postgres}; @@ -32,8 +32,10 @@ pub mod bench; pub mod cache; pub mod client; pub mod db; -pub mod ee; -pub mod email_ee; +mod ee; +pub mod ee_oss; +mod email_ee; +pub mod email_oss; pub mod error; pub mod external_ip; pub mod flow_status; @@ -42,24 +44,31 @@ pub mod global_settings; pub mod indexer; pub mod job_metrics; #[cfg(feature = "parquet")] -pub mod job_s3_helpers_ee; +mod job_s3_helpers_ee; +#[cfg(feature = "parquet")] +pub mod job_s3_helpers_oss; #[cfg(all(feature = "enterprise", feature = "openidconnect"))] -pub mod oidc_ee; +mod oidc_ee; +#[cfg(all(feature = "enterprise", feature = "openidconnect"))] +pub mod oidc_oss; pub mod jobs; pub mod jwt; pub mod more_serde; pub mod oauth2; -pub mod otel_ee; +mod otel_ee; +pub mod otel_oss; pub mod queue; pub mod s3_helpers; pub mod schedule; pub mod schema; pub mod scripts; pub mod server; -pub mod stats_ee; -pub mod teams_ee; +mod stats_ee; +pub mod stats_oss; +mod teams_ee; +pub mod teams_oss; pub mod tracing_init; pub mod users; pub mod utils; diff --git a/backend/windmill-common/src/oidc_oss.rs b/backend/windmill-common/src/oidc_oss.rs new file mode 100644 index 0000000000..e7a157b04d --- /dev/null +++ b/backend/windmill-common/src/oidc_oss.rs @@ -0,0 +1,198 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2023 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ + +use serde::{Deserialize, Serialize}; +use tokio::sync::RwLock; +#[cfg(all(feature = "enterprise", feature = "openidconnect"))] +use { + crate::db::DB, + crate::{auth::IdToken as WindmillIdToken, error::Result}, + anyhow, + openidconnect::{ + core::{CoreJwsSigningAlgorithm, CoreRsaPrivateSigningKey}, + IssuerUrl, JsonWebKeyId, + }, + std::process::Command, +}; + +#[cfg(feature = "openidconnect")] +use openidconnect::AdditionalClaims; + +#[cfg(feature = "openidconnect")] +impl AdditionalClaims for JobClaim {} + +#[cfg(feature = "openidconnect")] +impl AdditionalClaims for WorkspaceClaim {} + +#[cfg(feature = "openidconnect")] +impl AdditionalClaims for InstanceClaim {} + +#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] +pub struct WorkspaceClaim { + pub workspace: String, +} + +#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] +pub struct InstanceClaim {} + +#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] +pub struct JobClaim { + pub job_id: String, + pub path: Option, + pub flow_path: Option, + pub groups: Vec, + pub username: String, + pub email: String, + pub workspace: String, +} + +lazy_static::lazy_static! { + static ref PRIVATE_KEY: RwLock> = RwLock::new(None); +} + +pub async fn generate_id_token( + db: Option<&DB>, + claim: T, + audience: &str, + identifier: String, + email: Option, +) -> Result { + use chrono::{Duration, Utc}; + use openidconnect::{ + core::{CoreGenderClaim, CoreJweContentEncryptionAlgorithm}, + Audience, EndUserEmail, IdToken, IdTokenClaims, StandardClaims, SubjectIdentifier, + }; + + let private_key = get_private_key(db).await?; + + let issue_url = format!("{}/api/oidc/", crate::BASE_URL.read().await.clone()); + let issue_time = Utc::now(); + let expiration = issue_time + Duration::try_hours(48).unwrap(); + let id_token = IdToken::< + T, + CoreGenderClaim, + CoreJweContentEncryptionAlgorithm, + CoreJwsSigningAlgorithm, + >::new( + IdTokenClaims::::new( + // Specify the issuer URL for the OpenID Connect Provider. + IssuerUrl::new(issue_url) + .map_err(|e| anyhow::anyhow!("Failed to generate IssueUrl: {}", e))?, + // The audience is usually a single entry with the client ID of the client for whom + // the ID token is intended. This is a required claim. + vec![Audience::new(audience.to_string())], + // The ID token expiration is usually much shorter than that of the access or refresh + // tokens issued to clients. + expiration, + // The issue time is usually the current time. + issue_time, + // Set the standard claims defined by the OpenID Connect Core spec. + StandardClaims::new( + // Stable subject identifiers are recommended in place of e-mail addresses or other + // potentially unstable identifiers. This is the only required claim. + SubjectIdentifier::new(identifier), + ) + // Optional: specify the user's e-mail address. This should only be provided if the + // client has been granted the 'profile' or 'email' scopes. + .set_email(email.map(|x| EndUserEmail::new(x))) + // Optional: specify whether the provider has verified the user's e-mail address. + .set_email_verified(Some(true)), + // OpenID Connect Providers may supply custom claims by providing a struct that + // implements the AdditionalClaims trait. This requires manually using the + // generic IdTokenClaims struct rather than the CoreIdTokenClaims type alias, + // however. + claim, + ), + // The private key used for signing the ID token. For confidential clients (those able + // to maintain a client secret), a CoreHmacKey can also be used, in conjunction + // with one of the CoreJwsSigningAlgorithm::HmacSha* signing algorithms. When using an + // HMAC-based signing algorithm, the UTF-8 representation of the client secret should + // be used as the HMAC key. + &CoreRsaPrivateSigningKey::from_pem( + &private_key, + Some(JsonWebKeyId::new("windmill".to_string())), + ) + .map_err(|e| anyhow::anyhow!("Invalid private key: {}", e))?, + // Uses the RS256 signature algorithm. This crate supports any RS*, PS*, or HS* + // signature algorithm. + CoreJwsSigningAlgorithm::RsaSsaPkcs1V15Sha256, + // When returning the ID token alongside an access token (e.g., in the Authorization Code + // flow), it is recommended to pass the access token here to set the `at_hash` claim + // automatically. + None, + // When returning the ID token alongside an authorization code (e.g., in the implicit + // flow), it is recommended to pass the authorization code here to set the `c_hash` claim + // automatically. + None, + ) + .map_err(|e| anyhow::anyhow!("Failed to generate token: {}", e))?; + + Ok(WindmillIdToken::new(id_token.to_string(), expiration)) +} + +#[cfg(all(feature = "enterprise", feature = "openidconnect"))] +pub async fn get_private_key(db: Option<&DB>) -> anyhow::Result { + if let Some(key) = PRIVATE_KEY.read().await.clone() { + return Ok(key); + } else if let Some(db) = db { + let key = sqlx::query_scalar!( + "SELECT value->>'private_key' FROM global_settings WHERE name = 'rsa_keys'", + ) + .fetch_optional(db) + .await? + .flatten(); + + let key = key.filter(|s| !s.is_empty()); + + if let Some(key) = key { + return Ok(key); + } else { + let keys = gen_pems(db).await?; + return Ok(keys.private_key); + } + } else { + return Err(anyhow::anyhow!("Private key not found and no db provided")); + } +} + +#[cfg(all(feature = "enterprise", feature = "openidconnect"))] +#[derive(Debug, Clone, serde::Serialize)] +struct Keys { + private_key: String, +} + +#[cfg(all(feature = "enterprise", feature = "openidconnect"))] +async fn gen_pems(db: &DB) -> anyhow::Result { + use anyhow::anyhow; + + let private_key_cmd = Command::new("openssl") + .arg("genrsa") + .arg("--traditional") + .arg("2048") + .output() + .expect("failed to execute process"); + + let private_key = String::from_utf8(private_key_cmd.stdout)?; + + tracing::debug!("Generated private key: {}", private_key); + + if private_key.is_empty() { + return Err(anyhow!("Failed to generate RSA key: key is empty")); + } + + let keys = Keys { private_key }; + + sqlx::query!( + r#"INSERT INTO global_settings (name, value) VALUES ('rsa_keys', $1)"#, + serde_json::to_value(&keys).unwrap() + ) + .execute(db) + .await?; + + Ok(keys) +} diff --git a/backend/windmill-common/src/otel_oss.rs b/backend/windmill-common/src/otel_oss.rs new file mode 100644 index 0000000000..f3ada162f6 --- /dev/null +++ b/backend/windmill-common/src/otel_oss.rs @@ -0,0 +1,58 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2022 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ + +use crate::{jobs::QueuedJob, utils::Mode}; +use uuid::Uuid; + +pub fn set_span_parent(_span: &tracing::Span, _rj: &Uuid) {} + +#[cfg(not(all(feature = "otel", feature = "enterprise")))] +pub(crate) type OtelProvider = Option<()>; + +#[cfg(all(feature = "otel", feature = "enterprise"))] +pub(crate) type OtelProvider = Option; + +#[cfg(not(feature = "otel"))] +pub fn otel_ctx() -> () {} + +#[cfg(feature = "otel")] +#[inline(always)] +pub fn otel_ctx() -> opentelemetry::Context { + opentelemetry::Context::current() +} + +#[cfg(not(feature = "otel"))] +impl FutureExt for T {} + +#[cfg(not(feature = "otel"))] +pub trait FutureExt: Sized { + fn with_context(self, _otel_cx: ()) -> Self { + self + } +} + +use tracing_subscriber::EnvFilter; + +pub(crate) fn init_logs_bridge(_mode: &Mode, _hostname: &str, _env: &str) -> Option { + None +} + +#[cfg(all(feature = "otel", feature = "enterprise"))] +pub(crate) fn init_otlp_tracer( + _mode: &Mode, + _hostname: &str, + _env: &str, +) -> Option { + None +} + +pub(crate) fn init_meter_provider(_mode: &Mode, _hostname: &str, _env: &str) -> OtelProvider { + None +} + +pub fn add_root_flow_job_to_otlp(_queued_job: &QueuedJob, _success: bool) {} diff --git a/backend/windmill-common/src/s3_helpers.rs b/backend/windmill-common/src/s3_helpers.rs index 7e7c48851e..171958f5cd 100644 --- a/backend/windmill-common/src/s3_helpers.rs +++ b/backend/windmill-common/src/s3_helpers.rs @@ -147,7 +147,7 @@ pub enum ObjectStoreReload { #[cfg(feature = "parquet")] pub async fn reload_object_store_setting(db: &crate::DB) -> ObjectStoreReload { use crate::{ - ee::{get_license_plan, LicensePlan}, + ee_oss::{get_license_plan, LicensePlan}, global_settings::{load_value_from_global_settings, OBJECT_STORE_CONFIG_SETTING}, s3_helpers::ObjectSettings, }; @@ -613,8 +613,8 @@ pub async fn build_object_store_from_settings( build_azure_blob_client(&azure_blob_resource).map(|x| ExpirableObjectStore::from(x)) } ObjectSettings::AwsOidc(ref s3_aws_oidc_settings) => { - let token_generator = crate::job_s3_helpers_ee::TokenGenerator::AsServerInstance(); - let res = crate::job_s3_helpers_ee::generate_s3_aws_oidc_resource( + let token_generator = crate::job_s3_helpers_oss::TokenGenerator::AsServerInstance(); + let res = crate::job_s3_helpers_oss::generate_s3_aws_oidc_resource( s3_aws_oidc_settings.clone(), token_generator, init_private_key, diff --git a/backend/windmill-common/src/stats_oss.rs b/backend/windmill-common/src/stats_oss.rs new file mode 100644 index 0000000000..5d2dc82b82 --- /dev/null +++ b/backend/windmill-common/src/stats_oss.rs @@ -0,0 +1,47 @@ +use sqlx::Postgres; + +use crate::{error::Result, scripts::ScriptLang, DB}; + +pub async fn get_disable_stats_setting(_db: &DB) -> bool { + // stats details are closed source + + false +} + +pub async fn schedule_stats(_db: &DB, _http_client: &reqwest::Client) -> () { + // stats details are closed source +} + +#[derive(Debug, sqlx::FromRow, serde::Serialize)] +struct JobsUsage { + language: Option, + total_duration: i64, + count: i64, +} + +pub enum SendStatsReason { + Manual, + Schedule, + OnStart, +} + +pub async fn send_stats( + _http_client: &reqwest::Client, + _db: &DB, + _reason: SendStatsReason, +) -> Result<()> { + // stats details are closed source + Ok(()) +} + +pub struct ActiveUserUsage { + pub author_count: Option, + pub operator_count: Option, +} + +pub async fn get_user_usage<'c, E: sqlx::Executor<'c, Database = Postgres>>( + _db: E, +) -> Result { + let usage = ActiveUserUsage { author_count: None, operator_count: None }; + Ok(usage) +} diff --git a/backend/windmill-common/src/teams_oss.rs b/backend/windmill-common/src/teams_oss.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/backend/windmill-common/src/tracing_init.rs b/backend/windmill-common/src/tracing_init.rs index 5ed5cec752..77194ac0a9 100644 --- a/backend/windmill-common/src/tracing_init.rs +++ b/backend/windmill-common/src/tracing_init.rs @@ -48,7 +48,7 @@ pub fn initialize_tracing( hostname: &str, mode: &Mode, environment: &str, -) -> (WorkerGuard, crate::otel_ee::OtelProvider) { +) -> (WorkerGuard, crate::otel_oss::OtelProvider) { let style = std::env::var("RUST_LOG_STYLE").unwrap_or_else(|_| "auto".into()); let rust_log_env = std::env::var("RUST_LOG"); @@ -70,16 +70,16 @@ pub fn initialize_tracing( LevelFilter::INFO }; - let meter_provider = crate::otel_ee::init_meter_provider(mode, hostname, environment); + let meter_provider = crate::otel_oss::init_meter_provider(mode, hostname, environment); #[cfg(all(feature = "otel", feature = "enterprise"))] - let opentelemetry = crate::otel_ee::init_otlp_tracer(mode, hostname, environment) + let opentelemetry = crate::otel_oss::init_otlp_tracer(mode, hostname, environment) .map(|x| tracing_opentelemetry::layer().with_tracer(x)); #[cfg(not(all(feature = "otel", feature = "enterprise")))] let opentelemetry: Option = None; - let logs_bridge = crate::otel_ee::init_logs_bridge(&mode, hostname, environment); + let logs_bridge = crate::otel_oss::init_logs_bridge(&mode, hostname, environment); use tracing_appender::rolling::{RollingFileAppender, Rotation}; diff --git a/backend/windmill-common/src/utils.rs b/backend/windmill-common/src/utils.rs index 3f1a1bd385..abd0840795 100644 --- a/backend/windmill-common/src/utils.rs +++ b/backend/windmill-common/src/utils.rs @@ -7,9 +7,9 @@ */ use crate::auth::is_devops_email; -use crate::ee::LICENSE_KEY_ID; +use crate::ee_oss::LICENSE_KEY_ID; #[cfg(feature = "enterprise")] -use crate::ee::{send_critical_alert, CriticalAlertKind}; +use crate::ee_oss::{send_critical_alert, CriticalAlertKind}; use crate::error::{to_anyhow, Error, Result}; use crate::global_settings::UNIQUE_ID_SETTING; use crate::DB; diff --git a/backend/windmill-git-sync/src/git_sync_oss.rs b/backend/windmill-git-sync/src/git_sync_oss.rs new file mode 100644 index 0000000000..cc245d3d0c --- /dev/null +++ b/backend/windmill-git-sync/src/git_sync_oss.rs @@ -0,0 +1,16 @@ +use windmill_common::error::Result; + +use crate::{DeployedObject, DB}; + +pub async fn handle_deployment_metadata<'c>( + _email: &str, + _created_by: &str, + _db: &DB, + _w_id: &str, + _obj: DeployedObject, + _deployment_message: Option, + _skip_db_insert: bool, +) -> Result<()> { + // Git sync is an enterprise feature and not part of the open-source version + return Ok(()); +} diff --git a/backend/windmill-git-sync/src/lib.rs b/backend/windmill-git-sync/src/lib.rs index f1e0ed6ee3..1f5ae622b6 100644 --- a/backend/windmill-git-sync/src/lib.rs +++ b/backend/windmill-git-sync/src/lib.rs @@ -10,9 +10,10 @@ use sqlx::{Pool, Postgres}; use windmill_common::scripts::ScriptHash; -pub mod git_sync_ee; +mod git_sync_ee; +pub mod git_sync_oss; -pub use git_sync_ee::handle_deployment_metadata; +pub use git_sync_oss::handle_deployment_metadata; pub type DB = Pool; #[derive(Clone, Debug)] diff --git a/backend/windmill-indexer/src/completed_runs_oss.rs b/backend/windmill-indexer/src/completed_runs_oss.rs new file mode 100644 index 0000000000..f5c6c98cf8 --- /dev/null +++ b/backend/windmill-indexer/src/completed_runs_oss.rs @@ -0,0 +1,22 @@ +use anyhow::anyhow; +use sqlx::{Pool, Postgres}; +use windmill_common::error::Error; + +#[derive(Clone)] +pub struct IndexReader; + +#[derive(Clone)] +pub struct IndexWriter; + +pub async fn init_index(_db: &Pool) -> Result<(IndexReader, IndexWriter), Error> { + Err(anyhow!("Cannot initialize index: not in EE").into()) +} + +pub async fn run_indexer( + _db: Pool, + mut _index_writer: IndexWriter, + mut _killpill_rx: tokio::sync::broadcast::Receiver<()>, +) -> Result<(), Error> { + tracing::error!("Cannot run indexer: not in EE"); + Err(anyhow!("Cannot run indexer: not in EE").into()) +} diff --git a/backend/windmill-indexer/src/indexer_oss.rs b/backend/windmill-indexer/src/indexer_oss.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/backend/windmill-indexer/src/indexer_oss.rs @@ -0,0 +1 @@ + diff --git a/backend/windmill-indexer/src/lib.rs b/backend/windmill-indexer/src/lib.rs index 59c6a627f7..c19e16818c 100644 --- a/backend/windmill-indexer/src/lib.rs +++ b/backend/windmill-indexer/src/lib.rs @@ -1,3 +1,6 @@ -pub mod completed_runs_ee; -pub mod indexer_ee; -pub mod service_logs_ee; +mod completed_runs_ee; +pub mod completed_runs_oss; +mod indexer_ee; +pub mod indexer_oss; +mod service_logs_ee; +pub mod service_logs_oss; diff --git a/backend/windmill-indexer/src/service_logs_oss.rs b/backend/windmill-indexer/src/service_logs_oss.rs new file mode 100644 index 0000000000..e04575d3f5 --- /dev/null +++ b/backend/windmill-indexer/src/service_logs_oss.rs @@ -0,0 +1,25 @@ +use anyhow::anyhow; +use sqlx::{Pool, Postgres}; +use windmill_common::error::Error; +use windmill_common::KillpillSender; +#[derive(Clone)] +pub struct ServiceLogIndexReader; + +#[derive(Clone)] +pub struct ServiceLogIndexWriter; + +pub async fn init_index( + _db: &Pool, + mut _killpill_tx: KillpillSender, +) -> Result<(ServiceLogIndexReader, ServiceLogIndexWriter), Error> { + Err(anyhow!("Cannot initialize index: not in EE").into()) +} + +pub async fn run_indexer( + _db: Pool, + mut _index_writer: ServiceLogIndexWriter, + mut _killpill_rx: tokio::sync::broadcast::Receiver<()>, +) -> Result<(), Error> { + tracing::error!("Cannot run indexer: not in EE"); + Err(anyhow!("Cannot run indexer: not in EE").into()) +} diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index de64071c42..7f7863c927 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -25,7 +25,7 @@ use sqlx::{types::Json, FromRow, Pool, Postgres, Transaction}; use tokio::{sync::RwLock, time::sleep}; use ulid::Ulid; use uuid::Uuid; -use windmill_audit::audit_ee::{audit_log, AuditAuthor}; +use windmill_audit::audit_oss::{audit_log, AuditAuthor}; use windmill_audit::ActionKind; #[cfg(feature = "benchmark")] @@ -71,7 +71,7 @@ use windmill_common::BASE_URL; use windmill_common::users::SUPERADMIN_SYNC_EMAIL; use crate::flow_status::{update_flow_status_in_progress, update_workflow_as_code_status}; -use crate::jobs_ee::update_concurrency_counter; +use crate::jobs_oss::update_concurrency_counter; use crate::schedule::{get_schedule_opt, push_scheduled_job}; use crate::tags::per_workspace_tag; diff --git a/backend/windmill-queue/src/jobs_oss.rs b/backend/windmill-queue/src/jobs_oss.rs new file mode 100644 index 0000000000..ea1f86b529 --- /dev/null +++ b/backend/windmill-queue/src/jobs_oss.rs @@ -0,0 +1,16 @@ +use chrono::{DateTime, Utc}; +use uuid::Uuid; +use windmill_common::DB; + +#[allow(dead_code)] +pub(crate) async fn update_concurrency_counter( + _db: &DB, + _job_id: &Uuid, + _job_concurrency_key: String, + _jobs_uuids_init_json_value: serde_json::Value, + _pulled_job_id: String, + _job_custom_concurrency_time_window_s: i32, + _limit: i32, +) -> anyhow::Result<(bool, Option>)> { + Ok((true, None)) +} diff --git a/backend/windmill-queue/src/lib.rs b/backend/windmill-queue/src/lib.rs index 2496bdf818..b7b17e6214 100644 --- a/backend/windmill-queue/src/lib.rs +++ b/backend/windmill-queue/src/lib.rs @@ -7,7 +7,8 @@ */ mod jobs; -pub mod jobs_ee; +mod jobs_ee; +pub mod jobs_oss; pub mod schedule; pub use jobs::*; pub mod flow_status; diff --git a/backend/windmill-queue/src/schedule.rs b/backend/windmill-queue/src/schedule.rs index bb7d5df906..294ece7509 100644 --- a/backend/windmill-queue/src/schedule.rs +++ b/backend/windmill-queue/src/schedule.rs @@ -13,7 +13,7 @@ use sqlx::{PgExecutor, Postgres, Transaction}; use std::collections::HashMap; use std::str::FromStr; use windmill_common::db::Authed; -use windmill_common::ee::LICENSE_KEY_VALID; +use windmill_common::ee_oss::LICENSE_KEY_VALID; use windmill_common::flows::Retry; use windmill_common::get_latest_flow_version_info_for_path; use windmill_common::jobs::JobPayload; diff --git a/backend/windmill-worker/src/common.rs b/backend/windmill-worker/src/common.rs index 9955256d13..45f03ee056 100644 --- a/backend/windmill-worker/src/common.rs +++ b/backend/windmill-worker/src/common.rs @@ -728,7 +728,7 @@ async fn get_workspace_s3_resource_path( storage: Option<&String>, ) -> windmill_common::error::Result> { use windmill_common::{ - job_s3_helpers_ee::get_s3_resource_internal, s3_helpers::StorageResourceType, + job_s3_helpers_oss::get_s3_resource_internal, s3_helpers::StorageResourceType, }; let raw_lfs_opt = if let Some(storage) = storage { @@ -786,7 +786,7 @@ async fn get_workspace_s3_resource_path( get_s3_resource_internal( rt, s3_resource_value_raw, - windmill_common::job_s3_helpers_ee::TokenGenerator::AsClient(client), + windmill_common::job_s3_helpers_oss::TokenGenerator::AsClient(client), db, ) .await @@ -1209,8 +1209,8 @@ pub async fn par_install_language_dependencies<'a>( } #[cfg(all(feature = "enterprise", feature = "parquet"))] let is_not_pro = !matches!( - windmill_common::ee::get_license_plan().await, - windmill_common::ee::LicensePlan::Pro + windmill_common::ee_oss::get_license_plan().await, + windmill_common::ee_oss::LicensePlan::Pro ); #[cfg(all(feature = "enterprise", feature = "parquet"))] if is_not_pro && matches!(install_fn, InstallStrategy::AllAtOnce(_)) { diff --git a/backend/windmill-worker/src/handle_child.rs b/backend/windmill-worker/src/handle_child.rs index 3eb9e95dc9..498e0b3c0d 100644 --- a/backend/windmill-worker/src/handle_child.rs +++ b/backend/windmill-worker/src/handle_child.rs @@ -53,7 +53,7 @@ use futures::{ use crate::common::{resolve_job_timeout, OccupancyMetrics}; use crate::job_logger::{append_job_logs, append_with_limit}; -use crate::job_logger_ee::process_streaming_log_lines; +use crate::job_logger_oss::process_streaming_log_lines; use crate::worker_utils::{ping_job_status, update_worker_ping_from_job}; use crate::{MAX_RESULT_SIZE, MAX_WAIT_FOR_SIGINT, MAX_WAIT_FOR_SIGTERM}; diff --git a/backend/windmill-worker/src/job_logger.rs b/backend/windmill-worker/src/job_logger.rs index f4abd1d0c2..626dfbce44 100644 --- a/backend/windmill-worker/src/job_logger.rs +++ b/backend/windmill-worker/src/job_logger.rs @@ -13,10 +13,10 @@ use std::sync::Arc; use uuid::Uuid; #[cfg(not(all(feature = "enterprise", feature = "parquet")))] -use crate::job_logger_ee::default_disk_log_storage; +use crate::job_logger_oss::default_disk_log_storage; #[cfg(all(feature = "enterprise", feature = "parquet"))] -use crate::job_logger_ee::s3_storage; +use crate::job_logger_oss::s3_storage; pub enum CompactLogs { #[cfg(not(all(feature = "enterprise", feature = "parquet")))] diff --git a/backend/windmill-worker/src/job_logger_oss.rs b/backend/windmill-worker/src/job_logger_oss.rs new file mode 100644 index 0000000000..22772878ee --- /dev/null +++ b/backend/windmill-worker/src/job_logger_oss.rs @@ -0,0 +1,42 @@ +use std::io; +use std::sync::atomic::AtomicU32; +use std::sync::Arc; + +use uuid::Uuid; +use windmill_common::DB; + +use crate::job_logger::CompactLogs; + +#[cfg(all(feature = "enterprise", feature = "parquet"))] +pub(crate) async fn s3_storage( + _job_id: &Uuid, + _w_id: &str, + _db: &sqlx::Pool, + _logs: &str, + _total_size: Arc, + _worker_name: &str, +) { + tracing::info!("Logs length of {_job_id} has exceeded a threshold. Implementation to store excess on s3 in not OSS"); +} + +#[allow(dead_code)] +pub(crate) async fn default_disk_log_storage( + job_id: &Uuid, + _w_id: &str, + _db: &DB, + _logs: &str, + _total_size: Arc, + _compact_kind: CompactLogs, + _worker_name: &str, +) { + tracing::info!("Logs length of {job_id} has exceeded a threshold. Implementation to store excess on disk in not OSS"); +} + +pub(crate) fn process_streaming_log_lines( + r: Result, io::Error>, + _stderr: bool, + _job_id: &Uuid, + _w_id: &str, +) -> Option> { + r.transpose() +} diff --git a/backend/windmill-worker/src/lib.rs b/backend/windmill-worker/src/lib.rs index fa6eb10960..240d727a0a 100644 --- a/backend/windmill-worker/src/lib.rs +++ b/backend/windmill-worker/src/lib.rs @@ -28,6 +28,7 @@ mod graphql_executor; mod handle_child; pub mod job_logger; mod job_logger_ee; +mod job_logger_oss; mod js_eval; #[cfg(feature = "mysql")] mod mysql_executor; @@ -36,6 +37,7 @@ mod nu_executor; #[cfg(feature = "oracledb")] mod oracledb_executor; mod otel_ee; +mod otel_oss; mod pg_executor; #[cfg(feature = "php")] mod php_executor; diff --git a/backend/windmill-worker/src/otel_oss.rs b/backend/windmill-worker/src/otel_oss.rs new file mode 100644 index 0000000000..311ffd6355 --- /dev/null +++ b/backend/windmill-worker/src/otel_oss.rs @@ -0,0 +1,3 @@ +use windmill_queue::MiniPulledJob; + +pub fn add_root_flow_job_to_otlp(_queued_job: &MiniPulledJob, _success: bool) {} diff --git a/backend/windmill-worker/src/python_executor.rs b/backend/windmill-worker/src/python_executor.rs index 76ee967656..3a4898acc1 100644 --- a/backend/windmill-worker/src/python_executor.rs +++ b/backend/windmill-worker/src/python_executor.rs @@ -20,7 +20,7 @@ use tokio::{ }; use uuid::Uuid; #[cfg(all(feature = "enterprise", feature = "parquet", unix))] -use windmill_common::ee::{get_license_plan, LicensePlan}; +use windmill_common::ee_oss::{get_license_plan, LicensePlan}; use windmill_common::{ error::{ self, diff --git a/backend/windmill-worker/src/result_processor.rs b/backend/windmill-worker/src/result_processor.rs index 342c53a301..2fc9e32bb7 100644 --- a/backend/windmill-worker/src/result_processor.rs +++ b/backend/windmill-worker/src/result_processor.rs @@ -12,7 +12,7 @@ use std::{ }; use tracing::{field, Instrument}; #[cfg(not(feature = "otel"))] -use windmill_common::otel_ee::FutureExt; +use windmill_common::otel_oss::FutureExt; use uuid::Uuid; @@ -41,7 +41,7 @@ use windmill_queue::{add_completed_job, add_completed_job_error}; use crate::{ bash_executor::ANSI_ESCAPE_RE, common::{error_to_value, read_result, save_in_cache}, - otel_ee::add_root_flow_job_to_otlp, + otel_oss::add_root_flow_job_to_otlp, worker_flow::update_flow_status_after_job_completion, JobCompletedReceiver, JobCompletedSender, SameWorkerSender, SendResult, UpdateFlow, INIT_SCRIPT_TAG, @@ -76,7 +76,7 @@ async fn process_jc( } else { jc.job.id }; - windmill_common::otel_ee::set_span_parent(&span, &rj); + windmill_common::otel_oss::set_span_parent(&span, &rj); if let Some(lg) = jc.job.script_lang.as_ref() { span.record("language", lg.as_str()); @@ -276,7 +276,7 @@ pub fn start_background_processor( async fn send_job_completed(job_completed_tx: JobCompletedSender, jc: JobCompleted) { job_completed_tx .send_job(jc, true) - .with_context(windmill_common::otel_ee::otel_ctx()) + .with_context(windmill_common::otel_oss::otel_ctx()) .await .expect("send job completed") } @@ -312,7 +312,7 @@ pub async fn process_result( duration, }, ) - .with_context(windmill_common::otel_ee::otel_ctx()) + .with_context(windmill_common::otel_oss::otel_ctx()) .await; Ok(true) } @@ -374,7 +374,7 @@ pub async fn process_result( duration, }, ) - .with_context(windmill_common::otel_ee::otel_ctx()) + .with_context(windmill_common::otel_oss::otel_ctx()) .await; Ok(false) } diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index e15c24ef70..a9e6d9015d 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -27,7 +27,7 @@ use windmill_common::{ }; #[cfg(feature = "enterprise")] -use windmill_common::ee::LICENSE_KEY_VALID; +use windmill_common::ee_oss::LICENSE_KEY_VALID; use anyhow::Result; use const_format::concatcp; @@ -1526,7 +1526,7 @@ pub async fn run_worker( span.record("root_job", root_job.to_string().as_str()); } - windmill_common::otel_ee::set_span_parent(&span, &rj); + windmill_common::otel_oss::set_span_parent(&span, &rj); // span.context().span().add_event_with_timestamp("job created".to_string(), arc_job.created_at.into(), vec![]); match handle_queued_job( diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index 6c0b133828..e846ea35db 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -66,7 +66,7 @@ use windmill_queue::{ type DB = sqlx::Pool; -use windmill_audit::audit_ee::{audit_log, AuditAuthor}; +use windmill_audit::audit_oss::{audit_log, AuditAuthor}; use windmill_audit::ActionKind; use windmill_queue::{canceled_job_to_result, push};