Replace all oss files content

This commit is contained in:
Diego Imbert
2025-05-30 15:58:19 +02:00
parent db00def1b9
commit ea4017d59f
38 changed files with 44 additions and 1541 deletions
+1 -8
View File
@@ -1,8 +1 @@
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
}
pub use crate::ee::*;
+1 -52
View File
@@ -1,52 +1 @@
/*
* 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<tokio::task::JoinHandle<()>>,
Option<windmill_worker::JobCompletedSender>,
) {
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<String>,
pub tags: Vec<String>,
pub exp: Option<usize>,
}
pub struct AgentCache {}
impl AgentCache {
pub fn new() -> Self {
AgentCache {}
}
}
pub use crate::agent_workers_ee::*;
+1 -5
View File
@@ -1,5 +1 @@
use axum::Router;
pub fn global_unauthed_service() -> Router {
Router::new()
}
pub use crate::apps_ee::*;
+1 -32
View File
@@ -1,32 +1 @@
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<Arc<RwLock<ExternalJwks>>>,
) -> 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<Arc<RwLock<Self>>> {
// Implementation is not open source
None
}
}
pub use crate::ee::*;
+1 -147
View File
@@ -1,147 +1 @@
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<String>,
#[serde(deserialize_with = "empty_as_none")]
audience: Option<String>,
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<String>,
pub delivery_config: Option<SqlxJson<PushConfig>>,
}
#[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<String>,
_base_endpoint: &mut Option<String>,
_subscription_mode: SubscriptionMode,
_create_update_config: Option<CreateUpdateConfig>,
_trigger_mode: bool,
_is_flow: bool,
) -> WindmillResult<CreateUpdateConfig> {
Ok(CreateUpdateConfig::default())
}
pub async fn process_google_push_request(
_headers: HeaderMap,
_request: Request,
) -> Result<(String, HashMap<String, Box<RawValue>>), 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<SqlxJson<PushConfig>>,
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<chrono::Utc>,
pub extra_perms: Option<serde_json::Value>,
pub error: Option<String>,
pub server_id: Option<String>,
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
pub enabled: bool,
}
impl TriggerJobArgs<String> for GcpTrigger {
fn v1_payload_fn(payload: String) -> HashMap<String, Box<RawValue>> {
HashMap::from([("payload".to_string(), to_raw_value(&payload))])
}
fn trigger_kind() -> TriggerKind {
TriggerKind::Gcp
}
}
pub use crate::gcp_triggers_ee::*;
+1 -9
View File
@@ -1,9 +1 @@
use axum::routing::Router;
pub fn workspaced_service() -> Router {
Router::new()
}
pub fn global_service() -> Router {
Router::new()
}
pub use crate::git_sync_ee::*;
+1 -9
View File
@@ -1,9 +1 @@
use axum::Router;
pub fn workspaced_service() -> Router {
Router::new()
}
pub fn global_service() -> Router {
Router::new()
}
pub use crate::indexer_ee::*;
+1 -121
View File
@@ -1,121 +1 @@
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<String>,
}
#[derive(Deserialize)]
pub struct DownloadFileQuery {
#[allow(dead_code)]
pub file_key: String,
#[allow(dead_code)]
pub storage: Option<String>,
#[allow(dead_code)]
pub s3_resource_path: Option<String>,
}
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<UserDB>,
_token: &str,
_w_id: &str,
_storage: Option<String>,
) -> windmill_common::error::Result<(Option<bool>, Option<ObjectStoreResource>)> {
// implementation is not open source
Ok((None, None))
}
pub fn get_random_file_name(_file_extension: Option<String>) -> String {
unimplemented!("Not implemented in Windmill's Open Source repository")
}
pub async fn get_s3_resource<'c>(
_authed: &ApiAuthed,
_db: &DB,
_user_db: Option<UserDB>,
_token: &str,
_w_id: &str,
_resource_path: &str,
_resource_type: Option<StorageResourceType>,
_job_id: Option<Uuid>,
) -> error::Result<ObjectStoreResource> {
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<dyn ObjectStore>,
_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<dyn ObjectStore>,
_file_key: &str,
_stream: impl Stream<Item = Result<Bytes, std::io::Error>> + 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<UserDB>,
_token: &str,
_w_id: &str,
_query: DownloadFileQuery,
) -> error::Result<Response> {
Err(error::Error::internal_err(
"Not implemented in Windmill's Open Source repository".to_string(),
))
}
pub use crate::job_helpers_ee::*;
+1 -42
View File
@@ -1,42 +1 @@
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<String>,
pub script_path: String,
pub is_flow: bool,
pub edited_by: String,
pub email: String,
pub edited_at: chrono::DateTime<chrono::Utc>,
#[serde(skip_serializing_if = "Option::is_none")]
pub server_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
pub extra_perms: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
pub enabled: bool,
}
pub use crate::kafka_triggers_ee::*;
+1 -43
View File
@@ -1,43 +1 @@
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<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stream_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub consumer_name: Option<String>,
pub use_jetstream: bool,
pub script_path: String,
pub is_flow: bool,
pub edited_by: String,
pub email: String,
pub edited_at: chrono::DateTime<chrono::Utc>,
#[serde(skip_serializing_if = "Option::is_none")]
pub server_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
pub extra_perms: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
pub enabled: bool,
}
pub use crate::nats_triggers_ee::*;
+1 -184
View File
@@ -1,184 +1 @@
/*
* 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<String>,
_extra_params: Option<HashMap<String, String>>,
_extra_params_callback: Option<HashMap<String, String>>,
_allowed_domains: Option<Vec<String>>,
_userinfo_url: Option<String>,
}
#[cfg(feature = "oauth2")]
pub type BasicClientsMap = HashMap<String, ClientWithScopes>;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OAuthConfig {
auth_url: String,
token_url: String,
userinfo_url: Option<String>,
scopes: Option<Vec<String>>,
extra_params: Option<HashMap<String, String>>,
extra_params_callback: Option<HashMap<String, String>>,
req_body_auth: Option<bool>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OAuthClient {
id: String,
secret: String,
allowed_domains: Option<Vec<String>>,
connect_config: Option<OAuthConfig>,
login_config: Option<OAuthConfig>,
}
#[cfg(feature = "oauth2")]
#[derive(Debug)]
pub struct AllClients {
pub logins: BasicClientsMap,
pub connects: BasicClientsMap,
pub slack: Option<OClient>,
}
#[cfg(feature = "oauth2")]
pub async fn build_oauth_clients(
_base_url: &str,
_oauths_from_config: Option<HashMap<String, OAuthClient>>,
_db: &DB,
) -> anyhow::Result<AllClients> {
// 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<u64>,
refresh_token: Option<RefreshToken>,
#[serde(deserialize_with = "helpers::deserialize_space_delimited_vec")]
#[serde(serialize_with = "helpers::serialize_space_delimited_vec")]
#[serde(default)]
scope: Option<Vec<Scope>>,
}
#[derive(Serialize)]
struct Logins {
oauth: Vec<String>,
saml: Option<String>,
}
async fn list_logins() -> error::JsonResult<Logins> {
// Implementation is not open source
return Ok(Json(Logins { oauth: vec![], saml: None }));
}
#[cfg(feature = "oauth2")]
async fn list_connects() -> error::JsonResult<Vec<String>> {
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<Vec<String>> {
// 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<String> {
// 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<S: AsRef<[u8]>>(secret: S) -> anyhow::Result<SlackVerifier> {
HmacSha256::new_from_slice(secret.as_ref())
.map(|mac| SlackVerifier { _mac: mac })
.map_err(|_| anyhow::anyhow!("invalid secret"))
}
}
pub use crate::oauth2_ee::*;
+1 -17
View File
@@ -1,17 +1 @@
/*
* 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()
}
pub use crate::oidc_ee::*;
+1 -25
View File
@@ -1,25 +1 @@
/*
* 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<ServiceProviderExt> {
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()
}
pub use crate::saml_ee::*;
+1 -23
View File
@@ -1,23 +1 @@
/*
* 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<B>(_request: Request<B>, _next: Next) -> Response {
//Not implemented in open-source version
todo!()
}
pub use crate::scim_ee::*;
+1 -20
View File
@@ -1,20 +1 @@
use crate::{auth::AuthCache, db::DB};
use std::{net::SocketAddr, sync::Arc};
use windmill_common::db::UserDB;
pub struct SmtpServer {
pub auth_cache: Arc<AuthCache>,
pub db: DB,
pub user_db: UserDB,
pub base_internal_url: String,
}
impl SmtpServer {
pub async fn start_listener_thread(self: Arc<Self>, _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"))
}
}
pub use crate::smtp_server_ee::*;
+1 -33
View File
@@ -1,33 +1 @@
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<Vec<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<chrono::Utc>,
pub extra_perms: Option<serde_json::Value>,
pub error: Option<String>,
pub server_id: Option<String>,
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
pub enabled: bool,
}
pub use crate::sqs_triggers_ee::*;
+1 -5
View File
@@ -1,5 +1 @@
use axum::Router;
pub fn add_stripe_routes(router: Router) -> Router {
return router;
}
pub use crate::stripe_ee::*;
@@ -1,7 +1 @@
use hyper::StatusCode;
use windmill_common::error::Error;
pub async fn request_teams_approval() -> Result<StatusCode, Error> {
Err(Error::InternalErr("enterprise feature only".to_string()))
}
pub use crate::teams_approvals_ee::*;
+1 -39
View File
@@ -1,39 +1 @@
use http::status::StatusCode;
#[cfg(feature = "enterprise")]
use axum::Router;
use windmill_common::error::Error;
pub async fn edit_teams_command() -> Result<StatusCode, Error> {
return Err(Error::BadRequest(
"Teams only available on enterprise".to_string(),
));
}
pub async fn workspaces_list_available_teams_ids() -> Result<StatusCode, Error> {
return Err(Error::BadRequest(
"Teams only available on enterprise".to_string(),
));
}
pub async fn connect_teams() -> Result<StatusCode, Error> {
return Err(Error::BadRequest(
"Teams only available on enterprise".to_string(),
));
}
pub async fn run_teams_message_test_job() -> Result<StatusCode, Error> {
return Err(Error::BadRequest(
"Teams only available on enterprise".to_string(),
));
}
pub async fn workspaces_list_available_teams_channels() -> Result<StatusCode, Error> {
return Err(Error::BadRequest(
"Teams only available on enterprise".to_string(),
));
}
#[cfg(feature = "enterprise")]
pub fn teams_service() -> Router {
Router::new()
}
pub use crate::teams_ee::*;
+1 -41
View File
@@ -1,41 +1 @@
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<Argon2<'_>>,
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<Argon2<'_>>,
_authed: ApiAuthed,
_user_email: &str,
_ep: EditPassword,
) -> Result<String> {
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"
);
}
pub use crate::users_ee::*;
+1 -15
View File
@@ -1,15 +1 @@
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<String> {
Err(windmill_common::error::Error::internal_err(
"Not implemented on OSS".to_string(),
))
}
pub use crate::workspaces_ee::*;
+1 -74
View File
@@ -1,74 +1 @@
/*
* 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<String>,
}
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<HashMap<&str, &str>>,
) -> 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<Vec<AuditLog>> {
// 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<AuditLog> {
// 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(),
))
}
pub use crate::audit_ee::*;
@@ -1,6 +1 @@
use windmill_common::DB;
pub async fn apply_all_autoscaling(_db: &DB) -> anyhow::Result<()> {
// Autoscaling is an ee feature
Ok(())
}
pub use crate::autoscaling_ee::*;
+7 -1
View File
@@ -1,6 +1,6 @@
#[cfg(feature = "enterprise")]
use crate::db::DB;
use crate::ee_oss::LicensePlan::{self, Community};
use crate::ee::LicensePlan::Community;
#[cfg(feature = "enterprise")]
use crate::error;
use serde::Deserialize;
@@ -13,6 +13,12 @@ lazy_static::lazy_static! {
pub static ref LICENSE_KEY: Arc<RwLock<String>> = 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;
+1 -110
View File
@@ -1,110 +1 @@
#[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<RwLock<bool>> = Arc::new(RwLock::new(true));
pub static ref LICENSE_KEY_ID: Arc<RwLock<String>> = Arc::new(RwLock::new("".to_string()));
pub static ref LICENSE_KEY: Arc<RwLock<String>> = 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<Vec<CriticalErrorChannel>>,
) {
}
#[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<String>,
_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<String>,
) -> error::Result<String> {
// 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<String>,
) {
// Implementation is not open source
}
pub use crate::ee::*;
+1 -11
View File
@@ -1,11 +1 @@
use crate::server::Smtp;
pub async fn send_email(
_subject: &str,
_content: &str,
_to: Vec<String>,
_smtp: Smtp,
_client_timeout: Option<tokio::time::Duration>,
) -> crate::error::Result<()> {
Ok(())
}
pub use crate::email_ee::*;
@@ -1,34 +1 @@
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<ObjectStoreResource> {
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<String> {
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<sqlx::Postgres>>,
) -> crate::error::Result<ObjectStoreResource> {
todo!()
}
pub use crate::job_s3_helpers_ee::*;
+1 -198
View File
@@ -1,198 +1 @@
/*
* 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<String>,
pub flow_path: Option<String>,
pub groups: Vec<String>,
pub username: String,
pub email: String,
pub workspace: String,
}
lazy_static::lazy_static! {
static ref PRIVATE_KEY: RwLock<Option<String>> = RwLock::new(None);
}
pub async fn generate_id_token<T: AdditionalClaims>(
db: Option<&DB>,
claim: T,
audience: &str,
identifier: String,
email: Option<String>,
) -> Result<WindmillIdToken> {
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::<T, CoreGenderClaim>::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<String> {
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<Keys> {
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)
}
pub use crate::oidc_ee::*;
+1 -58
View File
@@ -1,58 +1 @@
/*
* 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<opentelemetry_sdk::metrics::SdkMeterProvider>;
#[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<T: Sized> 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<EnvFilter> {
None
}
#[cfg(all(feature = "otel", feature = "enterprise"))]
pub(crate) fn init_otlp_tracer(
_mode: &Mode,
_hostname: &str,
_env: &str,
) -> Option<opentelemetry_sdk::trace::Tracer> {
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) {}
pub use crate::otel_ee::*;
+1 -47
View File
@@ -1,47 +1 @@
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<ScriptLang>,
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<i32>,
pub operator_count: Option<i32>,
}
pub async fn get_user_usage<'c, E: sqlx::Executor<'c, Database = Postgres>>(
_db: E,
) -> Result<ActiveUserUsage> {
let usage = ActiveUserUsage { author_count: None, operator_count: None };
Ok(usage)
}
pub use crate::stats_ee::*;
+1
View File
@@ -0,0 +1 @@
pub use crate::teams_ee::*;
+1 -16
View File
@@ -1,16 +1 @@
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<String>,
_skip_db_insert: bool,
) -> Result<()> {
// Git sync is an enterprise feature and not part of the open-source version
return Ok(());
}
pub use crate::git_sync_ee::*;
@@ -1,22 +1 @@
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<Postgres>) -> Result<(IndexReader, IndexWriter), Error> {
Err(anyhow!("Cannot initialize index: not in EE").into())
}
pub async fn run_indexer(
_db: Pool<Postgres>,
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())
}
pub use crate::completed_runs_ee::*;
+1 -1
View File
@@ -1 +1 @@
pub use crate::indexer_ee::*;
@@ -1,25 +1 @@
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<Postgres>,
mut _killpill_tx: KillpillSender,
) -> Result<(ServiceLogIndexReader, ServiceLogIndexWriter), Error> {
Err(anyhow!("Cannot initialize index: not in EE").into())
}
pub async fn run_indexer(
_db: Pool<Postgres>,
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())
}
pub use crate::service_logs_ee::*;
+1 -16
View File
@@ -1,16 +1 @@
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<DateTime<Utc>>)> {
Ok((true, None))
}
pub use crate::jobs_ee::*;
+1 -42
View File
@@ -1,42 +1 @@
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<sqlx::Postgres>,
_logs: &str,
_total_size: Arc<AtomicU32>,
_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<AtomicU32>,
_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<Option<String>, io::Error>,
_stderr: bool,
_job_id: &Uuid,
_w_id: &str,
) -> Option<Result<String, io::Error>> {
r.transpose()
}
pub use crate::job_logger_ee::*;
+1 -3
View File
@@ -1,3 +1 @@
use windmill_queue::MiniPulledJob;
pub fn add_root_flow_job_to_otlp(_queued_job: &MiniPulledJob, _success: bool) {}
pub use crate::otel_ee::*;