fix build

This commit is contained in:
Ruben Fiszel
2024-02-17 13:54:54 +01:00
parent 7805c35d27
commit db04e995ed
4 changed files with 14 additions and 278 deletions
+2 -2
View File
@@ -59,7 +59,7 @@ if [ ! -d "${EE_CODE_DIR}" ]; then
fi
if [ "$REVERT" == "YES" ]; then
for ee_file in $(find ${EE_CODE_DIR} -name "*.rs"); do
for ee_file in $(find ${EE_CODE_DIR} -name "*ee.rs"); do
ce_file="${ee_file/${EE_CODE_DIR}/.}"
ce_file="${root_dirpath}/backend/${ce_file}"
git restore --staged ${ce_file} || true
@@ -67,7 +67,7 @@ if [ "$REVERT" == "YES" ]; then
done
else
# This replaces all files in current repo with alternative EE files in windmill-ee-private
for ee_file in $(find "${EE_CODE_DIR}" -name "*.rs"); do
for ee_file in $(find "${EE_CODE_DIR}" -name "*ee.rs"); do
ce_file="${ee_file/${EE_CODE_DIR}/.}"
ce_file="${root_dirpath}/backend/${ce_file}"
if [[ -f "${ce_file}" ]]; then
+1
View File
@@ -71,6 +71,7 @@ mod scim_ee;
mod scripts;
mod settings;
mod static_assets;
mod stripe_ee;
mod tracing_init;
mod users;
mod utils;
+7
View File
@@ -0,0 +1,7 @@
#[cfg(feature = "stripe")]
use axum::Router;
#[cfg(feature = "stripe")]
pub fn add_stripe_routes(router: Router) -> Router {
return router;
}
+4 -276
View File
@@ -6,9 +6,6 @@
* LICENSE-AGPL for a copy of the license.
*/
#[cfg(feature = "stripe")]
use std::str::FromStr;
use crate::db::ApiAuthed;
use crate::BASE_URL;
use crate::{
@@ -20,8 +17,7 @@ use crate::{
utils::require_super_admin,
webhook_util::WebhookShared,
};
#[cfg(feature = "stripe")]
use axum::response::Redirect;
use axum::{
body::StreamBody,
extract::{Extension, Path, Query},
@@ -31,11 +27,9 @@ use axum::{
Json, Router,
};
use chrono::Utc;
#[cfg(feature = "stripe")]
use chrono::{Datelike, TimeZone, Timelike};
use regex::Regex;
#[cfg(feature = "stripe")]
use stripe::CustomerId;
use uuid::Uuid;
use windmill_audit::audit_ee::audit_log;
use windmill_audit::ActionKind;
@@ -109,16 +103,7 @@ pub fn workspaced_service() -> Router {
#[cfg(feature = "stripe")]
{
if STRIPE_KEY.is_none() {
return router;
} else {
tracing::info!("stripe enabled");
return router
.route("/premium_info", get(premium_info))
.route("/checkout", get(stripe_checkout))
.route("/billing_portal", get(stripe_portal));
}
crate::stripe_ee::add_stripe_routes(router)
}
#[cfg(not(feature = "stripe"))]
@@ -141,11 +126,6 @@ pub fn global_service() -> Router {
)
}
#[cfg(feature = "enterprise")]
lazy_static::lazy_static! {
pub static ref STRIPE_KEY: Option<String> = std::env::var("STRIPE_KEY").ok();
}
#[derive(FromRow, Serialize)]
struct Workspace {
id: String,
@@ -335,258 +315,6 @@ async fn is_premium(
Ok(Json(row))
}
#[derive(Serialize)]
pub struct PremiumWorkspaceInfo {
pub premium: bool,
pub usage: Option<i32>,
pub seats: Option<i32>,
}
#[cfg(feature = "stripe")]
async fn premium_info(
authed: ApiAuthed,
Extension(db): Extension<DB>,
Path(w_id): Path<String>,
) -> JsonResult<PremiumWorkspaceInfo> {
require_admin(authed.is_admin, &authed.username)?;
let mut tx = db.begin().await?;
let row = sqlx::query!(
r#"SELECT premium, usage.usage as "usage?", workspace_settings.customer_id, workspace_settings.plan FROM workspace LEFT JOIN workspace_settings ON workspace_settings.workspace_id = $1 LEFT JOIN usage ON usage.id = $1 AND month_ = EXTRACT(YEAR FROM current_date) * 12 + EXTRACT(MONTH FROM current_date) AND usage.is_workspace IS true WHERE workspace.id = $1"#,
&w_id
)
.fetch_one(&mut *tx)
.await?;
tx.commit().await?;
let result = PremiumWorkspaceInfo { premium: row.premium, usage: row.usage, seats: None };
#[cfg(feature = "enterprise")]
let mut result = result;
#[cfg(feature = "enterprise")]
if row.premium && row.plan == Some("team".to_string()) {
let customer_id = row.customer_id.ok_or(Error::InternalErr(format!(
"no customer id for workspace {}",
w_id
)))?;
let client = stripe::Client::new(
STRIPE_KEY
.clone()
.ok_or(Error::InternalErr(format!("stripe key not set")))?,
);
let customer_id = CustomerId::from_str(&customer_id).map_err(to_anyhow)?;
let subscriptions = stripe::Subscription::list(
&client,
&stripe::ListSubscriptions {
customer: Some(customer_id.clone()),
limit: Some(1),
..Default::default()
},
)
.await
.map_err(to_anyhow)?;
if subscriptions.data.len() > 1 {
return Err(Error::InternalErr(format!("multiple subscriptions for customer {}, please contact us at ccontact@windmill.dev", customer_id)));
}
let subscription = subscriptions.data.get(0).ok_or_else(|| {
Error::InternalErr(format!("no subscription for customer {}", customer_id))
})?;
result.seats = subscription
.items
.data
.iter()
.filter_map(|item| {
item.price
.clone()
.map(|p| {
p.metadata.map(|m| {
m.get("plan")
.filter(|plan| plan == &"team")
.map(|_| item.quantity.map(|x| x as i32))
})
})
.flatten()
.flatten()
.flatten()
})
.collect::<Vec<_>>()
.get(0)
.copied();
}
Ok(Json(result))
}
#[cfg(feature = "stripe")]
#[derive(Deserialize)]
struct PlanQuery {
plan: String,
seats: Option<i32>,
}
#[cfg(feature = "stripe")]
async fn stripe_checkout(
authed: ApiAuthed,
Path(w_id): Path<String>,
Query(plan): Query<PlanQuery>,
Extension(db): Extension<DB>,
) -> Result<Redirect> {
// #[cfg(feature = "enterprise")]
{
require_admin(authed.is_admin, &authed.username)?;
let client = stripe::Client::new(
STRIPE_KEY
.clone()
.ok_or(Error::InternalErr(format!("stripe key not set")))?,
);
let base_url = BASE_URL.read().await.clone();
let success_rd = format!("{}/workspace_settings/checkout?success=true", base_url);
let failure_rd = format!("{}/workspace_settings/checkout?success=false", base_url);
let checkout_session = {
let mut params = stripe::CreateCheckoutSession::new(&success_rd);
params.mode = Some(stripe::CheckoutSessionMode::Subscription);
params.cancel_url = Some(&failure_rd);
params.line_items = match plan.plan.as_str() {
"team" => Some(vec![stripe::CreateCheckoutSessionLineItems {
quantity: Some(plan.seats.unwrap_or(1) as u64),
price: Some("price_1NCNOgGU3NdFi9eLuG4fZuEP".to_string()),
adjustable_quantity: Some(
stripe::CreateCheckoutSessionLineItemsAdjustableQuantity {
enabled: true,
minimum: Some(1),
..Default::default()
},
),
..Default::default()
}]),
_ => Err(Error::BadRequest("invalid plan".to_string()))?,
};
params.client_reference_id = Some(&w_id);
let customer_id = sqlx::query_scalar!(
"SELECT customer_id FROM workspace_settings WHERE workspace_id = $1",
&w_id
)
.fetch_one(&db)
.await?;
match customer_id {
Some(customer_id) => {
params.customer = Some(CustomerId::from_str(&customer_id).map_err(to_anyhow)?)
}
_ => params.customer_email = Some(&authed.email),
}
let now = Utc::now();
params.subscription_data = Some(stripe::CreateCheckoutSessionSubscriptionData {
metadata: {
let mut map = std::collections::HashMap::new();
map.insert("workspace_id".to_string(), w_id.clone());
Some(map)
},
billing_cycle_anchor: if now.day() == 1 && now.hour() < 12 {
// no need to prorate so close to the billing cycle renew date
None
} else {
// first of the next month (and possibly next year) at noon UTC
let date = if now.month() == 12 {
Utc.with_ymd_and_hms(now.year() + 1, 1, 1, 12, 0, 0)
.single()
.unwrap()
} else {
Utc.with_ymd_and_hms(now.year(), now.month() + 1, 1, 12, 0, 0)
.single()
.unwrap()
};
Some(date.timestamp())
},
..Default::default()
});
stripe::CheckoutSession::create(&client, params)
.await
.map_err(to_anyhow)?
};
let uri = checkout_session
.url
.ok_or_else(|| Error::InternalErr(format!("stripe checkout redirect issue")))?;
Ok(Redirect::to(&uri))
}
}
#[cfg(feature = "stripe")]
async fn stripe_portal(
authed: ApiAuthed,
Path(w_id): Path<String>,
Extension(db): Extension<DB>,
) -> Result<Redirect> {
require_admin(authed.is_admin, &authed.username)?;
let customer_id = sqlx::query_scalar!(
"SELECT customer_id FROM workspace_settings WHERE workspace_id = $1",
w_id
)
.fetch_one(&db)
.await?
.ok_or_else(|| Error::InternalErr(format!("no customer id for workspace {}", w_id)))?;
let client = stripe::Client::new(
STRIPE_KEY
.clone()
.ok_or(Error::InternalErr(format!("stripe key not set")))?,
);
let success_rd = format!(
"{}/workspace_settings?tab=premium",
BASE_URL.read().await.clone()
);
let portal_session = {
let customer_id = CustomerId::from_str(&customer_id).unwrap();
let mut params = stripe::CreateBillingPortalSession::new(customer_id);
params.return_url = Some(&success_rd);
stripe::BillingPortalSession::create(&client, params)
.await
.map_err(to_anyhow)?
};
Ok(Redirect::to(&portal_session.url))
}
// async fn stripe_usage(
// authed: ApiAuthed,
// Path(w_id): Path<String>,
// Extension(db): Extension<DB>,
// Extension(base_url): Extension<Arc<BaseUrl>>,
// ) -> Result<Redirect> {
// require_admin(authed.is_admin, &authed.username)?;
// let customer_id = sqlx::query_scalar!(
// "SELECT customer_id FROM workspace_settings WHERE workspace_id = $1",
// w_id
// )
// .fetch_one(&db)
// .await?
// .ok_or_else(|| Error::InternalErr(format!("no customer id for workspace {}", w_id)))?;
// let client = stripe::Client::new(std::env::var("STRIPE_KEY").expect("STRIPE_KEY"));
// let success_rd = format!("{}/workspace_settings?tab=premium", base_url.0);
// let portal_session = {
// let customer_id = CustomerId::from_str(&customer_id).unwrap();
// let subscriptions = stripe::Subscription::list(
// &client,
// stripe::ListSubscriptions { customer: Some(customer_id), ..Default::default() },
// )
// .await
// .map_err(to_anyhow)?
// .data[0];
// let getUsage =
// stripe::SubscriptionItem::list(
// &client,
// stripe::ListSubscriptionItems {
// subscription: subscription.id,
// ..Default::default()
// },
// )
// .await
// .map_err(to_anyhow)
// };
// let mut params = stripe::ListSubscriptionItems::new(customer_id);
// params.return_url = Some(&success_rd);
// stripe::BillingPortalSession::create(&client, params)
// .await
// .map_err(to_anyhow)?
// };
// }
async fn exists_workspace(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,