diff --git a/apps/frontend/src/components/ui/HCaptcha.vue b/apps/frontend/src/components/ui/HCaptcha.vue index 3421afa0..bacc2516 100644 --- a/apps/frontend/src/components/ui/HCaptcha.vue +++ b/apps/frontend/src/components/ui/HCaptcha.vue @@ -12,17 +12,21 @@ function hCaptchaReady() { } onMounted(() => { - window.hCaptchaReady = hCaptchaReady; + if (window.hcaptcha) { + hCaptchaReady(); + } else { + window.hCaptchaReady = hCaptchaReady; - useHead({ - script: [ - { - src: "https://js.hcaptcha.com/1/api.js?render=explicit&onload=hCaptchaReady", - async: true, - defer: true, - }, - ], - }); + useHead({ + script: [ + { + src: "https://js.hcaptcha.com/1/api.js?render=explicit&onload=hCaptchaReady", + async: true, + defer: true, + }, + ], + }); + } }); defineExpose({ diff --git a/apps/frontend/src/components/ui/servers/BackupCreateModal.vue b/apps/frontend/src/components/ui/servers/BackupCreateModal.vue index e0b67486..fc475325 100644 --- a/apps/frontend/src/components/ui/servers/BackupCreateModal.vue +++ b/apps/frontend/src/components/ui/servers/BackupCreateModal.vue @@ -17,6 +17,9 @@ Backup #{{ newBackupAmount }} +
+ You're creating backups too fast. Please wait a moment before trying again. +
@@ -36,10 +39,9 @@ + + +
+ + + + + diff --git a/apps/frontend/src/types/servers.ts b/apps/frontend/src/types/servers.ts index 4b19c0b1..626fc1a0 100644 --- a/apps/frontend/src/types/servers.ts +++ b/apps/frontend/src/types/servers.ts @@ -167,6 +167,9 @@ export interface WSAuthExpiringEvent { export interface WSPowerStateEvent { event: "power-state"; state: ServerState; + // if state "crashed" + oom_killed?: boolean; + exit_code?: number; } export interface WSAuthIncorrectEvent { diff --git a/apps/labrinth/.env b/apps/labrinth/.env index 893f80b9..af01d17a 100644 --- a/apps/labrinth/.env +++ b/apps/labrinth/.env @@ -86,8 +86,9 @@ SITE_VERIFY_EMAIL_PATH=none SITE_RESET_PASSWORD_PATH=none SITE_BILLING_PATH=none -BEEHIIV_PUBLICATION_ID=none -BEEHIIV_API_KEY=none +SENDY_URL=none +SENDY_LIST_ID=none +SENDY_API_KEY=none ANALYTICS_ALLOWED_ORIGINS='["http://127.0.0.1:3000", "http://localhost:3000", "https://modrinth.com", "https://www.modrinth.com", "*"]' diff --git a/apps/labrinth/src/lib.rs b/apps/labrinth/src/lib.rs index 091b0998..d2108913 100644 --- a/apps/labrinth/src/lib.rs +++ b/apps/labrinth/src/lib.rs @@ -460,8 +460,9 @@ pub fn check_env_vars() -> bool { failed |= check_var::("SITE_RESET_PASSWORD_PATH"); failed |= check_var::("SITE_BILLING_PATH"); - failed |= check_var::("BEEHIIV_PUBLICATION_ID"); - failed |= check_var::("BEEHIIV_API_KEY"); + failed |= check_var::("SENDY_URL"); + failed |= check_var::("SENDY_LIST_ID"); + failed |= check_var::("SENDY_API_KEY"); if parse_strings_from_var("ANALYTICS_ALLOWED_ORIGINS").is_none() { warn!( diff --git a/apps/labrinth/src/routes/internal/flows.rs b/apps/labrinth/src/routes/internal/flows.rs index 7cc03b43..c5825aaa 100644 --- a/apps/labrinth/src/routes/internal/flows.rs +++ b/apps/labrinth/src/routes/internal/flows.rs @@ -1430,23 +1430,23 @@ pub async fn delete_auth_provider( Ok(HttpResponse::NoContent().finish()) } -pub async fn sign_up_beehiiv(email: &str) -> Result<(), AuthenticationError> { - let id = dotenvy::var("BEEHIIV_PUBLICATION_ID")?; - let api_key = dotenvy::var("BEEHIIV_API_KEY")?; +pub async fn sign_up_sendy(email: &str) -> Result<(), AuthenticationError> { + let url = dotenvy::var("SENDY_URL")?; + let id = dotenvy::var("SENDY_LIST_ID")?; + let api_key = dotenvy::var("SENDY_API_KEY")?; let site_url = dotenvy::var("SITE_URL")?; + let mut form = HashMap::new(); + + form.insert("api_key", &*api_key); + form.insert("email", email); + form.insert("list", &*id); + form.insert("referrer", &*site_url); + let client = reqwest::Client::new(); client - .post(format!( - "https://api.beehiiv.com/v2/publications/{id}/subscriptions" - )) - .header(AUTHORIZATION, format!("Bearer {}", api_key)) - .json(&serde_json::json!({ - "email": email, - "utm_source": "modrinth", - "utm_medium": "account_creation", - "referring_site": site_url, - })) + .post(format!("{url}/subscribe")) + .form(&form) .send() .await? .error_for_status()? @@ -1578,7 +1578,7 @@ pub async fn create_account_with_password( )?; if new_account.sign_up_newsletter.unwrap_or(false) { - sign_up_beehiiv(&new_account.email).await?; + sign_up_sendy(&new_account.email).await?; } transaction.commit().await?; @@ -1678,26 +1678,26 @@ async fn validate_2fa_code( .map_err(|_| AuthenticationError::InvalidCredentials)?, ) .map_err(|_| AuthenticationError::InvalidCredentials)?; - let token = totp - .generate_current() - .map_err(|_| AuthenticationError::InvalidCredentials)?; const TOTP_NAMESPACE: &str = "used_totp"; let mut conn = redis.connect().await?; // Check if TOTP has already been used if conn - .get(TOTP_NAMESPACE, &format!("{}-{}", token, user_id.0)) + .get(TOTP_NAMESPACE, &format!("{}-{}", input, user_id.0)) .await? .is_some() { return Err(AuthenticationError::InvalidCredentials); } - if input == token { + if totp + .check_current(input.as_str()) + .map_err(|_| AuthenticationError::InvalidCredentials)? + { conn.set( TOTP_NAMESPACE, - &format!("{}-{}", token, user_id.0), + &format!("{}-{}", input, user_id.0), "", Some(60), ) @@ -2453,7 +2453,7 @@ pub async fn subscribe_newsletter( .1; if let Some(email) = user.email { - sign_up_beehiiv(&email).await?; + sign_up_sendy(&email).await?; Ok(HttpResponse::NoContent().finish()) } else {