From df27d18043e92147136d75fa346172f40216c3bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Djk=C3=A1=C5=A5o?= Date: Wed, 3 Apr 2024 19:47:23 +0200 Subject: [PATCH] clippy refactor, payment gateway payment flow revertion --- .env | 7 +- .env.example | 5 +- Dockerfile | 10 +- README.md | 1 + app-template/src/app.rs | 12 +- app-template/src/main.rs | 20 +- app-template/src/routes/mod.rs | 2 +- app-template/src/routes/webhooks.rs | 7 +- docker-gateway.env | 11 +- docker-sitemap.env | 3 +- sdk/src/config.rs | 1 + sdk/src/manifest.rs | 4 +- sdk/src/webhooks/mod.rs | 6 +- sdk/src/webhooks/utils.rs | 1 + simple-payment-gateway/src/app.rs | 99 +++---- simple-payment-gateway/src/main.rs | 51 ++-- .../src/queries/event_transactions.rs | 22 +- simple-payment-gateway/src/routes/mod.rs | 2 +- simple-payment-gateway/src/routes/webhooks.rs | 243 +++++++++--------- sitemap-generator/src/app.rs | 12 +- sitemap-generator/src/main.rs | 17 +- sitemap-generator/src/routes/mod.rs | 2 +- sitemap-generator/src/routes/register.rs | 182 ++++++------- sitemap-generator/src/routes/webhooks.rs | 137 +++++----- 24 files changed, 413 insertions(+), 444 deletions(-) diff --git a/.env b/.env index 90ad006..7838790 100644 --- a/.env +++ b/.env @@ -2,6 +2,7 @@ REQUIRED_SALEOR_VERSION="^3.13" # only sets port, the host is always 0.0.0.0 (listens to everything). Set this to docker-compose service name APP_API_BASE_URL="http://10.100.110.234:3000" +APP_IFRAME_BASE_URL="http://app-name.site.com" APL="Redis" APL_URL="redis://localhost:6380/2" LOG_LEVEL="DEBUG" @@ -20,9 +21,9 @@ SITEMAP_PAGES_TEMPLATE="https://example.com/{page.slug}" SITEMAP_INDEX_HOSTNAME="https://example.com" ## THESE VARIABLES ARE FOR SIMPLE-PAYMENT-GATEWAY APP -#To see all possible options, check simple-payment-gateway/src/app:GatewayTypes -ACTIVE_GATEWAYS="cod,cash,transfer" +#To see all possible options, check simple-payment-gateway/src/app:PaymentMethods +ACTIVE_PAYMENT_METHODS="cod,cash,transfer" # only SK,EN available :). Determines what language the gateway names will be in storefront -LOCALE="SK" +LOCALE="Sk" # uses https://crates.io/crates/iso_currency CURRENCIES="EUR" diff --git a/.env.example b/.env.example index a00edf7..3d298d3 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,7 @@ REQUIRED_SALEOR_VERSION="^3.13" # only sets port, the host is always 0.0.0.0 (listens to everything). Set this to docker-compose service name APP_API_BASE_URL="http://0.0.0.0:3000" +APP_IFRAME_BASE_URL="http://app-name.site.com" APL="Redis" APL_URL="redis://localhost:6379/1" LOG_LEVEL="DEBUG" @@ -22,7 +23,7 @@ SITEMAP_INDEX_HOSTNAME="https://example.com" ## THESE VARIABLES ARE FOR SIMPLE-PAYMENT-GATEWAY APP #To see all possible options, check simple-payment-gateway/src/app:GatewayTypes ACTIVE_GATEWAYS="cod,cash,transfer" -# only SK,EN available :). Determines what language the gateway names will be in storefront -LOCALE="SK" +# only Sk,En available :). Determines what language the gateway names will be in storefront +LOCALE="Sk" # uses https://crates.io/crates/iso_currency CURRENCIES="EUR" diff --git a/Dockerfile b/Dockerfile index 99c8977..9e3eb4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,8 +17,11 @@ RUN cargo chef cook --release --recipe-path=recipe.json COPY . . RUN cargo build --release + FROM debian:bookworm-slim as chef-sitemap-generator -COPY --from=builder /apps/target/release/sitemap-generator /sitemap-generator +WORKDIR /app +COPY --from=builder /apps/target/release/sitemap-generator . +COPY ./sitemap-generator/public ./public RUN apt-get update -y && \ apt-get install -y pkg-config libssl-dev curl RUN mkdir /sitemaps @@ -31,8 +34,11 @@ LABEL org.opencontainers.image.title="djkato/saleor-sitemap-generator"\ org.opencontainers.image.authors="Djkáťo "\ org.opencontainers.image.licenses="PolyForm-Noncommercial-1.0.0" + FROM debian:bookworm-slim as chef-simple-payment-gateway -COPY --from=builder /apps/target/release/simple-payment-gateway /simple-payment-gateway +WORKDIR /app +COPY --from=builder /apps/target/release/simple-payment-gateway . +COPY ./simple-payment-gateway/public ./public RUN apt-get update -y && \ apt-get install -y pkg-config libssl-dev curl CMD [ "./simple-payment-gateway" ] diff --git a/README.md b/README.md index 7fdf013..52fe09a 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ and set all necessary env variables in `app-simple-gateway.env` according to the To use, you need to have [Rust environment prepared](https://rustup.rs/). Every folder represents a different workspace. To add a new lib, do `cargo new --lib` or `cargo new ` for binary apps. It should appear as a new member under root `Cargo.toml` +To run apps propery, use `cargo run -c ` # Unofficial Saleor App SDK diff --git a/app-template/src/app.rs b/app-template/src/app.rs index d21cec6..136f7d6 100644 --- a/app-template/src/app.rs +++ b/app-template/src/app.rs @@ -33,22 +33,18 @@ where } } -pub fn trace_to_std(config: &Config) { +pub fn trace_to_std(config: &Config) -> anyhow::Result<()> { let filter = EnvFilter::builder() .with_default_directive(LevelFilter::DEBUG.into()) - .from_env() - .unwrap() - .add_directive( - format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level) - .parse() - .unwrap(), - ); + .from_env()? + .add_directive(format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level).parse()?); tracing_subscriber::fmt() .with_max_level(config.log_level) .with_env_filter(filter) .with_target(true) .compact() .init(); + Ok(()) } #[derive(Debug, Clone)] diff --git a/app-template/src/main.rs b/app-template/src/main.rs index 4d8e064..e6cef1d 100644 --- a/app-template/src/main.rs +++ b/app-template/src/main.rs @@ -1,3 +1,11 @@ +#![allow( + non_upper_case_globals, + clippy::large_enum_variant, + clippy::upper_case_acronyms +)] +#![feature(let_chains)] +#![deny(clippy::unwrap_used, clippy::expect_used)] + mod app; mod queries; mod routes; @@ -5,8 +13,8 @@ mod routes; use saleor_app_sdk::{ cargo_info, config::Config, - manifest::{AppManifest, AppPermission}, - webhooks::{AsyncWebhookEventType, WebhookManifest}, + manifest::{AppManifestBuilder, AppPermission}, + webhooks::{AsyncWebhookEventType, WebhookManifestBuilder}, SaleorApp, }; use std::sync::Arc; @@ -20,13 +28,13 @@ use crate::{ #[tokio::main] async fn main() -> anyhow::Result<()> { let config = Config::load()?; - trace_to_std(&config); + trace_to_std(&config)?; let saleor_app = SaleorApp::new(&config)?; - let app_manifest = AppManifest::new(&config, cargo_info!()) + let app_manifest = AppManifestBuilder::new(&config, cargo_info!()) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query( r#" subscription QueryProductsChanged { @@ -85,7 +93,7 @@ async fn main() -> anyhow::Result<()> { .unwrap_or(&"3000"), ) .await?; - tracing::debug!("listening on {}", listener.local_addr().unwrap()); + tracing::debug!("listening on {}", listener.local_addr()?); match axum::serve(listener, app).await { Ok(o) => Ok(o), Err(e) => anyhow::bail!(e), diff --git a/app-template/src/routes/mod.rs b/app-template/src/routes/mod.rs index 5124453..ba7840b 100644 --- a/app-template/src/routes/mod.rs +++ b/app-template/src/routes/mod.rs @@ -22,7 +22,7 @@ pub fn create_routes(state: AppState) -> Router { (StatusCode::NOT_FOUND, "Not found") } let service = handle_404.into_service(); - let serve_dir = ServeDir::new("saleor-app-template/public").not_found_service(service); + let serve_dir = ServeDir::new("./public").not_found_service(service); Router::new() .layer(middleware::from_fn(webhook_signature_verifier)) diff --git a/app-template/src/routes/webhooks.rs b/app-template/src/routes/webhooks.rs index 695d759..424144d 100644 --- a/app-template/src/routes/webhooks.rs +++ b/app-template/src/routes/webhooks.rs @@ -37,16 +37,15 @@ pub async fn webhooks( .get(SALEOR_API_URL_HEADER) .context("missing saleor api url header")?; let event_type = get_webhook_event_type(&headers)?; - match event_type { - EitherWebhookType::Async(a) => match a { + if let EitherWebhookType::Async(a) = event_type { + match a { AsyncWebhookEventType::ProductUpdated | AsyncWebhookEventType::ProductCreated | AsyncWebhookEventType::ProductDeleted => { update_product(product, url.to_str()?, state).await? } _ => (), - }, - _ => (), + } } info!("got webhooks!"); diff --git a/docker-gateway.env b/docker-gateway.env index be1202c..90bda12 100644 --- a/docker-gateway.env +++ b/docker-gateway.env @@ -1,8 +1,7 @@ ## COMMON VARIABLES FOR ALL APPS REQUIRED_SALEOR_VERSION="^3.13" -APP_API_BASE_URL="http://0.0.0.0:3001" -MANIFEST_URL="http://0.0.0.0:3001" -CONFIG_URL="http://0.0.0.0:3001" +APP_API_BASE_URL="http://app-payment-gateway:3000" +APP_IFRAME_BASE_URL="http://app-payment-gateway.site.com" APL="Redis" APL_URL="redis://redis-apl:6379/1" LOG_LEVEL="DEBUG" @@ -23,5 +22,7 @@ SITEMAP_INDEX_HOSTNAME="https://example.com" ## THESE VARIABLES ARE FOR SIMPLE-PAYMENT-GATEWAY APP #To see all possible options, check simple-payment-gateway/src/app:GatewayTypes ACTIVE_GATEWAYS="cod,cash,transfer" -# only SK,EN available :). Determines what language the gateway names will be in storefront -LOCALE="SK" +# only Sk,En available :). Determines what language the gateway names will be in storefront +LOCALE="Sk" +# uses https://crates.io/crates/iso_currency +CURRENCIES="EUR" diff --git a/docker-sitemap.env b/docker-sitemap.env index 5c0a857..cb50251 100644 --- a/docker-sitemap.env +++ b/docker-sitemap.env @@ -1,6 +1,7 @@ ## COMMON VARIABLES FOR ALL APPS REQUIRED_SALEOR_VERSION="^3.13" -APP_API_BASE_URL="http://0.0.0.0:3002" +APP_API_BASE_URL="http://0.0.0.0:3000" +APP_IFRAME_BASE_URL="http://app-payment-gateway.site.com" APL="Redis" APL_URL="redis://redis-apl:6379/1" LOG_LEVEL="DEBUG" diff --git a/sdk/src/config.rs b/sdk/src/config.rs index 00ed45a..d5b6b63 100644 --- a/sdk/src/config.rs +++ b/sdk/src/config.rs @@ -24,6 +24,7 @@ pub struct Config { #[serde(default = "version_default")] pub required_saleor_version: String, pub app_api_base_url: String, + pub app_iframe_base_url: String, pub apl: AplType, pub apl_url: String, #[serde(with = "LocalTracingLevel")] diff --git a/sdk/src/manifest.rs b/sdk/src/manifest.rs index ee4725b..986e8b7 100644 --- a/sdk/src/manifest.rs +++ b/sdk/src/manifest.rs @@ -214,7 +214,7 @@ macro_rules! cargo_info { } pub use cargo_info; -impl AppManifest { +impl AppManifestBuilder { /** * Builder for AppManifest * @@ -227,7 +227,7 @@ impl AppManifest { * To set webhooks and permissions use the add_webhook() and add_permissions() * */ - pub fn new(config: &Config, info: CargoInfo) -> AppManifestBuilder { + pub fn new(config: &Config, info: CargoInfo) -> Self { AppManifestBuilder { manifest: AppManifest { id: info.name.clone(), diff --git a/sdk/src/webhooks/mod.rs b/sdk/src/webhooks/mod.rs index fc868cc..725c7b0 100644 --- a/sdk/src/webhooks/mod.rs +++ b/sdk/src/webhooks/mod.rs @@ -269,15 +269,15 @@ impl WebhookManifestBuilder { } } -impl WebhookManifest { +impl WebhookManifestBuilder { /** * Creates defaults of name( webhook) and target url(/api/webhooks) from config and env. */ - pub fn new(config: &Config) -> WebhookManifestBuilder { + pub fn new(config: &Config) -> Self { WebhookManifestBuilder { webhook_manifest: WebhookManifest { target_url: format!("{}/api/webhooks", config.app_api_base_url), - name: env!("CARGO_PKG_NAME").to_owned() + " webhook", + name: "webhook".to_owned(), is_active: Some(true), ..Default::default() }, diff --git a/sdk/src/webhooks/utils.rs b/sdk/src/webhooks/utils.rs index b189106..cde3dd1 100644 --- a/sdk/src/webhooks/utils.rs +++ b/sdk/src/webhooks/utils.rs @@ -4,6 +4,7 @@ use crate::headers::SALEOR_EVENT_HEADER; use super::{AsyncWebhookEventType, SyncWebhookEventType}; +#[derive(Debug)] pub enum EitherWebhookType { Sync(SyncWebhookEventType), Async(AsyncWebhookEventType), diff --git a/simple-payment-gateway/src/app.rs b/simple-payment-gateway/src/app.rs index 5957d60..511b305 100644 --- a/simple-payment-gateway/src/app.rs +++ b/simple-payment-gateway/src/app.rs @@ -5,14 +5,11 @@ use axum::{ use enum_iterator::{all, Sequence}; use iso_currency::Currency; use std::{str::FromStr, sync::Arc}; -use tracing::level_filters::LevelFilter; +use tracing::{debug, level_filters::LevelFilter}; use tracing_subscriber::EnvFilter; -use saleor_app_sdk::{ - config::Config, locales::LocaleCode, manifest::AppManifest, - webhooks::sync_response::PaymentGateway, SaleorApp, -}; -use serde::Serialize; +use saleor_app_sdk::{config::Config, locales::LocaleCode, manifest::AppManifest, SaleorApp}; +use serde::{Deserialize, Serialize}; // Make our own error that wraps `anyhow::Error`. pub struct AppError(anyhow::Error); @@ -38,27 +35,23 @@ where } } -pub fn trace_to_std(config: &Config) { +pub fn trace_to_std(config: &Config) -> anyhow::Result<()> { let filter = EnvFilter::builder() .with_default_directive(LevelFilter::DEBUG.into()) - .from_env() - .unwrap() - .add_directive( - format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level) - .parse() - .unwrap(), - ); + .from_env()? + .add_directive(format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level).parse()?); tracing_subscriber::fmt() .with_max_level(config.log_level) .with_env_filter(filter) .with_target(true) .compact() .init(); + Ok(()) } -#[derive(Debug, Clone, Sequence, Serialize)] +#[derive(Debug, Clone, Sequence, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] -pub enum GatewayType { +pub enum PaymentMethodType { Accreditation, Cash, /** @@ -75,16 +68,16 @@ pub struct AppState { pub saleor_app: Arc>, pub config: Config, pub manifest: AppManifest, - pub active_gateways: Vec, + pub active_payment_methods: Vec, } -pub fn get_active_gateways_from_env() -> anyhow::Result> { +pub fn get_active_payment_methods_from_env() -> anyhow::Result> { _ = dotenvy::dotenv(); //eg: "accreditation,cod,other,transfer" - let env_types = std::env::var("ACTIVE_GATEWAYS")?; + let env_methods = std::env::var("ACTIVE_PAYMENT_METHODS")?; let locale = std::env::var("LOCALE")?; - let locale = LocaleCode::from_str(&locale)?; let currencies = std::env::var("CURRENCIES")?; + let locale = LocaleCode::from_str(&locale)?; let currencies = currencies.split(',').collect::>(); let currencies = currencies .iter() @@ -92,44 +85,52 @@ pub fn get_active_gateways_from_env() -> anyhow::Result> { .collect::, _>>() .map_err(|e| anyhow::anyhow!(format!("{:?}", e)))?; - let str_types: Vec<_> = env_types.split(',').collect(); - let gateway_types = str_types + let str_types: Vec<_> = env_methods.split(',').collect(); + let payment_methods = str_types .iter() - .zip(all::()) + .flat_map(|s| all::().map(move |g| (s, g))) .filter_map(|(s, g)| match format!("{:?}", g).to_lowercase() == *s { true => Some(g), false => None, }) - .map(|g| ActiveGateway { - gateway_type: g.clone(), - gateway: PaymentGateway { - currencies: currencies.clone(), - id: format!("{:?}", &g).to_lowercase(), - config: vec![], - name: match (g, &locale) { - (GatewayType::COD, LocaleCode::Sk) => "Dobierka".to_owned(), - (GatewayType::Cash, LocaleCode::Sk) => "Hotovosť".to_owned(), - (GatewayType::Transfer, LocaleCode::Sk) => "Bankový prevod".to_owned(), - (GatewayType::Inkaso, LocaleCode::Sk) => "Inkaso".to_owned(), - (GatewayType::Accreditation, LocaleCode::Sk) => "Vzajomný zápočet".to_owned(), - (GatewayType::Other, LocaleCode::Sk) => "Iné".to_owned(), - (GatewayType::COD, LocaleCode::En) => "Cash on delivery".to_owned(), - (GatewayType::Cash, LocaleCode::En) => "Cash".to_owned(), - (GatewayType::Transfer, LocaleCode::En) => "Bank transfer".to_owned(), - (GatewayType::Inkaso, LocaleCode::En) => "Encashment".to_owned(), - (GatewayType::Accreditation, LocaleCode::En) => "Mutual credit".to_owned(), - (GatewayType::Other, LocaleCode::En) => "Other".to_owned(), - (g, l) => unimplemented!("Gateway {:?} in locale {:?} not implemented", g, l), - }, + .map(|g| ActivePaymentMethod { + typ: g.clone(), + name: match (g, &locale) { + (PaymentMethodType::COD, LocaleCode::Sk) => "Dobierka".to_owned(), + (PaymentMethodType::Cash, LocaleCode::Sk) => "Hotovosť".to_owned(), + (PaymentMethodType::Transfer, LocaleCode::Sk) => "Bankový prevod".to_owned(), + (PaymentMethodType::Inkaso, LocaleCode::Sk) => "Inkaso".to_owned(), + (PaymentMethodType::Accreditation, LocaleCode::Sk) => "Vzajomný zápočet".to_owned(), + (PaymentMethodType::Other, LocaleCode::Sk) => "Iné".to_owned(), + (PaymentMethodType::COD, LocaleCode::En) => "Cash on delivery".to_owned(), + (PaymentMethodType::Cash, LocaleCode::En) => "Cash".to_owned(), + (PaymentMethodType::Transfer, LocaleCode::En) => "Bank transfer".to_owned(), + (PaymentMethodType::Inkaso, LocaleCode::En) => "Encashment".to_owned(), + (PaymentMethodType::Accreditation, LocaleCode::En) => "Mutual credit".to_owned(), + (PaymentMethodType::Other, LocaleCode::En) => "Other".to_owned(), + (g, l) => unimplemented!("Gateway {:?} in locale {:?} not implemented", g, l), }, }) .collect::>(); - - Ok(gateway_types) + debug!( + "active gateway types:{:?}\ncurrencies:{:?}\nlocale:{:?}", + &payment_methods, ¤cies, &locale + ); + Ok(payment_methods) } #[derive(Debug, Clone, Serialize)] -pub struct ActiveGateway { - pub gateway_type: GatewayType, - pub gateway: PaymentGateway, +pub struct ActivePaymentMethod { + pub typ: PaymentMethodType, + pub name: String, +} + +#[derive(Serialize)] +pub struct PaymentGatewayInitializeSessionData { + pub payment_methods: Vec, +} + +#[derive(Deserialize, Serialize)] +pub struct TransactionInitializeSessionData { + pub payment_method: PaymentMethodType, } diff --git a/simple-payment-gateway/src/main.rs b/simple-payment-gateway/src/main.rs index b38d323..2eb3720 100644 --- a/simple-payment-gateway/src/main.rs +++ b/simple-payment-gateway/src/main.rs @@ -1,4 +1,8 @@ -#![allow(non_upper_case_globals)] +#![allow( + non_upper_case_globals, + clippy::large_enum_variant, + clippy::upper_case_acronyms +)] #![feature(let_chains)] #![deny(clippy::unwrap_used, clippy::expect_used)] mod app; @@ -8,20 +12,19 @@ mod routes; use saleor_app_sdk::{ cargo_info, config::Config, - manifest::{AppManifest, AppPermission}, - webhooks::{SyncWebhookEventType, WebhookManifest}, + manifest::{AppManifestBuilder, AppPermission}, + webhooks::{SyncWebhookEventType, WebhookManifestBuilder}, SaleorApp, }; use std::sync::Arc; use tokio::sync::Mutex; use crate::{ - app::{get_active_gateways_from_env, trace_to_std, AppState}, + app::{get_active_payment_methods_from_env, trace_to_std, AppState}, queries::event_transactions::{ - sub_list_payment_gateways, sub_payment_gateway_initialize_session, - sub_transaction_cancelation_requested, sub_transaction_charge_requested, - sub_transaction_initialize_session, sub_transaction_process_session, - sub_transaction_refund_requested, + sub_payment_gateway_initialize_session, sub_transaction_cancelation_requested, + sub_transaction_charge_requested, sub_transaction_initialize_session, + sub_transaction_process_session, sub_transaction_refund_requested, }, routes::create_routes, }; @@ -29,53 +32,53 @@ use crate::{ #[tokio::main] async fn main() -> anyhow::Result<()> { let config = Config::load()?; - trace_to_std(&config); + trace_to_std(&config)?; let saleor_app = SaleorApp::new(&config)?; - let app_manifest = AppManifest::new(&config, cargo_info!()) + let app_manifest = AppManifestBuilder::new(&config, cargo_info!()) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query(sub_transaction_process_session) .add_sync_event(SyncWebhookEventType::TransactionProcessSession) .build(), ) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query(sub_transaction_charge_requested) .add_sync_event(SyncWebhookEventType::TransactionChargeRequested) .build(), ) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query(sub_transaction_refund_requested) .add_sync_event(SyncWebhookEventType::TransactionRefundRequested) .build(), ) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query(sub_transaction_initialize_session) .add_sync_event(SyncWebhookEventType::TransactionInitializeSession) .build(), ) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query(sub_payment_gateway_initialize_session) .add_sync_event(SyncWebhookEventType::PaymentGatewayInitializeSession) .build(), ) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query(sub_transaction_cancelation_requested) .add_sync_event(SyncWebhookEventType::TransactionCancelationRequested) .build(), ) - .add_webhook( - WebhookManifest::new(&config) - .set_query(sub_list_payment_gateways) - .add_sync_event(SyncWebhookEventType::PaymentListGateways) - .build(), - ) + // .add_webhook( + // WebhookManifestBuilder::new(&config) + // .set_query(sub_list_payment_gateways) + // .add_sync_event(SyncWebhookEventType::PaymentListGateways) + // .build(), + // ) .add_permissions(vec![ AppPermission::HandlePayments, AppPermission::ManageOrders, @@ -85,7 +88,7 @@ async fn main() -> anyhow::Result<()> { .build(); let app_state = AppState { - active_gateways: get_active_gateways_from_env()?, + active_payment_methods: get_active_payment_methods_from_env()?, manifest: app_manifest, config: config.clone(), saleor_app: Arc::new(Mutex::new(saleor_app)), @@ -102,7 +105,7 @@ async fn main() -> anyhow::Result<()> { .unwrap_or(&"3000"), ) .await?; - tracing::debug!("listening on {}", listener.local_addr().unwrap()); + tracing::debug!("listening on {}", listener.local_addr()?); match axum::serve(listener, app).await { Ok(o) => Ok(o), Err(e) => anyhow::bail!(e), diff --git a/simple-payment-gateway/src/queries/event_transactions.rs b/simple-payment-gateway/src/queries/event_transactions.rs index 750c10e..b5869c2 100644 --- a/simple-payment-gateway/src/queries/event_transactions.rs +++ b/simple-payment-gateway/src/queries/event_transactions.rs @@ -55,17 +55,17 @@ fragment OrderDetails on Order { } "#; -pub const sub_list_payment_gateways: &str = r#" -subscription ListPaymentGateways { - event { - ... on PaymentListGateways { - checkout { - id - } - } - } -} -"#; +// pub const sub_list_payment_gateways: &str = r#" +// subscription ListPaymentGateways { +// event { +// ... on PaymentListGateways { +// checkout { +// id +// } +// } +// } +// } +// "#; pub const sub_payment_gateway_initialize_session: &str = concatcp!( r#" diff --git a/simple-payment-gateway/src/routes/mod.rs b/simple-payment-gateway/src/routes/mod.rs index 0af534a..ba7840b 100644 --- a/simple-payment-gateway/src/routes/mod.rs +++ b/simple-payment-gateway/src/routes/mod.rs @@ -22,7 +22,7 @@ pub fn create_routes(state: AppState) -> Router { (StatusCode::NOT_FOUND, "Not found") } let service = handle_404.into_service(); - let serve_dir = ServeDir::new("simple-payment-gateway/public").not_found_service(service); + let serve_dir = ServeDir::new("./public").not_found_service(service); Router::new() .layer(middleware::from_fn(webhook_signature_verifier)) diff --git a/simple-payment-gateway/src/routes/webhooks.rs b/simple-payment-gateway/src/routes/webhooks.rs index 42555e7..aa9f321 100644 --- a/simple-payment-gateway/src/routes/webhooks.rs +++ b/simple-payment-gateway/src/routes/webhooks.rs @@ -7,23 +7,23 @@ use saleor_app_sdk::{ webhooks::{ sync_response::{ CancelationRequestedResult, ChargeRequestedResult, - PaymentGatewayInitializeSessionResponse, PaymentListGatewaysResponse, - RefundRequestedResult, TransactionCancelationRequestedResponse, - TransactionChargeRequestedResponse, TransactionInitializeSessionResponse, - TransactionProcessSessionResponse, TransactionRefundRequestedResponse, - TransactionSessionResult, + PaymentGatewayInitializeSessionResponse, RefundRequestedResult, + TransactionCancelationRequestedResponse, TransactionChargeRequestedResponse, + TransactionInitializeSessionResponse, TransactionProcessSessionResponse, + TransactionRefundRequestedResponse, TransactionSessionResult, }, utils::{get_webhook_event_type, EitherWebhookType}, SyncWebhookEventType, }, }; -use serde::Serialize; use serde_json::Value; use std::str::FromStr; use tracing::{debug, error, info}; use crate::{ - app::{ActiveGateway, AppError, AppState, GatewayType}, + app::{ + AppError, AppState, PaymentGatewayInitializeSessionData, TransactionInitializeSessionData, + }, queries::{ event_transactions::{ TransactionCancelationRequested2, TransactionChargeRequested2, @@ -43,7 +43,6 @@ pub async fn webhooks( ) -> Result, AppError> { debug!("/api/webhooks"); debug!("req: {:?}", body); - debug!("headers: {:?}", headers); let saleor_api_url = headers .get(SALEOR_API_URL_HEADER) @@ -51,57 +50,96 @@ pub async fn webhooks( .to_str()? .to_owned(); let event_type = get_webhook_event_type(&headers)?; + debug!("event: {:?}", event_type); let res: Json = match event_type { EitherWebhookType::Sync(a) => match a { - SyncWebhookEventType::PaymentListGateways => { - let gateways = state - .active_gateways - .iter() - .cloned() - .map(|g| g.gateway) - .collect::>(); - Json::from(serde_json::to_value(PaymentListGatewaysResponse(gateways))?) - } - - SyncWebhookEventType::TransactionCancelationRequested => { - let data = serde_json::from_str::(&body)?; + // SyncWebhookEventType::PaymentListGateways => { + // let gateways = state + // .active_gateways + // .iter() + // .cloned() + // .map(|g| g.gateway) + // .collect::>(); + // Json::from(serde_json::to_value(PaymentListGatewaysResponse(gateways))?) + // } + SyncWebhookEventType::PaymentGatewayInitializeSession => { + let data = serde_json::to_value(PaymentGatewayInitializeSessionData { + payment_methods: state.active_payment_methods, + })?; Json::from(serde_json::to_value( - TransactionCancelationRequestedResponse { - time: None, - psp_reference: "".to_owned(), - external_url: None, - message: None, - amount: data - .action - .amount - .and_then(|a| Decimal::from_str(&a.0).ok()), - result: Some(CancelationRequestedResult::CancelSuccess), - }, + PaymentGatewayInitializeSessionResponse:: { data: Some(data) }, )?) } - SyncWebhookEventType::PaymentGatewayInitializeSession => Json::from( - serde_json::to_value(PaymentGatewayInitializeSessionResponse:: { data: None })?, - ), - SyncWebhookEventType::TransactionProcessSession => { - let data = serde_json::from_str::(&body)?; - Json::from(serde_json::to_value(TransactionProcessSessionResponse::< - u8, - > { - data: None, - time: None, - psp_reference: None, - external_url: None, - message: None, - amount: Decimal::from_str(&data.action.amount.0)?, - result: match data.action.action_type { - TransactionFlowStrategyEnum::Charge => { - TransactionSessionResult::ChargeSuccess - } - TransactionFlowStrategyEnum::Authorization => { - TransactionSessionResult::AuthorizationSuccess - } + SyncWebhookEventType::TransactionInitializeSession => { + let session_data = serde_json::from_str::(&body)?; + let payment_method: TransactionInitializeSessionData = serde_json::from_str( + &session_data + .data + .context("Missing data field on TransactionInitializeSession2 body")? + .0, + )?; + debug!( + "Transaction session initialised with '{:?}' payment method.", + &payment_method.payment_method + ); + let str_payment_method = serde_json::to_string(&payment_method)?; + + let app = state.saleor_app.lock().await; + let auth_data = app.apl.get(&saleor_api_url).await?; + + let operation = TransactionUpdate::build(TransactionUpdateVariables { + id: &session_data.transaction.id, + transaction: Some(TransactionUpdateInput { + message: Some(&str_payment_method), + ..Default::default() + }), + }); + let mut res = surf::post(&saleor_api_url) + .header("authorization-bearer", auth_data.token) + .run_graphql(operation) + .await; + + let mut webhook_result = WebhookResult::Failiure; + if let Ok(r) = &mut res + && let Some(data) = &mut r.data + && let Some(q_res) = &mut data.transaction_update + { + if !q_res.errors.is_empty() { + q_res + .errors + .iter() + .for_each(|e| error!("failed update transaction, {:?}", e)); + } else if q_res.transaction.is_some() { + webhook_result = WebhookResult::Success; + } + } + + Json::from(serde_json::to_value( + TransactionInitializeSessionResponse:: { + data: None, + time: None, + psp_reference: None, + external_url: None, + message: None, + amount: Decimal::from_str(&session_data.action.amount.0)?, + result: match (session_data.action.action_type, webhook_result) { + (TransactionFlowStrategyEnum::Charge, WebhookResult::Success) => { + TransactionSessionResult::ChargeSuccess + } + ( + TransactionFlowStrategyEnum::Authorization, + WebhookResult::Success, + ) => TransactionSessionResult::AuthorizationSuccess, + (TransactionFlowStrategyEnum::Charge, WebhookResult::Failiure) => { + TransactionSessionResult::ChargeFailiure + } + ( + TransactionFlowStrategyEnum::Authorization, + WebhookResult::Failiure, + ) => TransactionSessionResult::AuthorizationFailure, + }, }, - })?) + )?) } SyncWebhookEventType::TransactionChargeRequested => { let data = serde_json::from_str::(&body)?; @@ -131,91 +169,54 @@ pub async fn webhooks( result: Some(RefundRequestedResult::RefundSuccess), })?) } - SyncWebhookEventType::TransactionInitializeSession => { - let data = serde_json::from_str::(&body)?; - let app = state.saleor_app.lock().await; - let auth_data = app.apl.get(&saleor_api_url).await?; - let operation = TransactionUpdate::build(TransactionUpdateVariables { - id: &data.transaction.id, - transaction: Some(TransactionUpdateInput { - message: Some(""), - ..Default::default() - }), - }); - let mut res = surf::post(&saleor_api_url) - .header("authorization-bearer", auth_data.token) - .run_graphql(operation) - .await; - - let mut webhook_result = WebhookResult::Failiure; - if let Ok(r) = &mut res - && let Some(data) = &mut r.data - && let Some(q_res) = &mut data.transaction_update - { - if !q_res.errors.is_empty() { - q_res - .errors - .iter() - .for_each(|e| error!("failed update transaction, {:?}", e)); - } else if let Some(tr) = &mut q_res.transaction { - tr.message = serde_json::to_string(&PaymentMethod { - payment_method: GatewayType::COD, - })?; - webhook_result = WebhookResult::Success; - } - } + SyncWebhookEventType::TransactionCancelationRequested => { + let data = serde_json::from_str::(&body)?; Json::from(serde_json::to_value( - TransactionInitializeSessionResponse:: { - data: None, + TransactionCancelationRequestedResponse { time: None, - psp_reference: None, + psp_reference: "".to_owned(), external_url: None, message: None, - amount: Decimal::from_str(&data.action.amount.0)?, - result: match (data.action.action_type, webhook_result) { - (TransactionFlowStrategyEnum::Charge, WebhookResult::Success) => { - TransactionSessionResult::ChargeSuccess - } - ( - TransactionFlowStrategyEnum::Authorization, - WebhookResult::Success, - ) => TransactionSessionResult::AuthorizationSuccess, - (TransactionFlowStrategyEnum::Charge, WebhookResult::Failiure) => { - TransactionSessionResult::ChargeFailiure - } - ( - TransactionFlowStrategyEnum::Authorization, - WebhookResult::Failiure, - ) => TransactionSessionResult::AuthorizationFailure, - }, + amount: data + .action + .amount + .and_then(|a| Decimal::from_str(&a.0).ok()), + result: Some(CancelationRequestedResult::CancelSuccess), }, )?) } + SyncWebhookEventType::TransactionProcessSession => { + let data = serde_json::from_str::(&body)?; + Json::from(serde_json::to_value(TransactionProcessSessionResponse::< + u8, + > { + data: None, + time: None, + psp_reference: None, + external_url: None, + message: None, + amount: Decimal::from_str(&data.action.amount.0)?, + result: match data.action.action_type { + TransactionFlowStrategyEnum::Charge => { + TransactionSessionResult::ChargeSuccess + } + TransactionFlowStrategyEnum::Authorization => { + TransactionSessionResult::AuthorizationSuccess + } + }, + })?) + } _ => Json::from(Value::from_str("")?), }, _ => Json::from(Value::from_str("")?), }; - + debug!("{:?}", res.to_string()); info!("got webhooks!"); Ok(res) } -#[derive(Serialize, Clone, Debug)] -pub struct JsonResponse { - data: JsonResponseData, -} - -#[derive(Serialize, Clone, Debug)] -pub struct JsonResponseData { - current_gateway: ActiveGateway, -} enum WebhookResult { Success, Failiure, } - -#[derive(Serialize, Clone, Debug)] -struct PaymentMethod { - payment_method: GatewayType, -} diff --git a/sitemap-generator/src/app.rs b/sitemap-generator/src/app.rs index 4570be8..0ec2212 100644 --- a/sitemap-generator/src/app.rs +++ b/sitemap-generator/src/app.rs @@ -36,22 +36,18 @@ where } } -pub fn trace_to_std(config: &Config) { +pub fn trace_to_std(config: &Config) -> anyhow::Result<()> { let filter = EnvFilter::builder() .with_default_directive(LevelFilter::DEBUG.into()) - .from_env() - .unwrap() - .add_directive( - format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level) - .parse() - .unwrap(), - ); + .from_env()? + .add_directive(format!("{}={}", env!("CARGO_PKG_NAME"), config.log_level).parse()?); tracing_subscriber::fmt() .with_max_level(config.log_level) .with_env_filter(filter) .with_target(true) .compact() .init(); + Ok(()) } /** diff --git a/sitemap-generator/src/main.rs b/sitemap-generator/src/main.rs index 4c88b34..96c3085 100644 --- a/sitemap-generator/src/main.rs +++ b/sitemap-generator/src/main.rs @@ -1,3 +1,8 @@ +#![allow( + non_upper_case_globals, + clippy::large_enum_variant, + clippy::upper_case_acronyms +)] #![feature(let_chains)] #![deny(clippy::unwrap_used, clippy::expect_used)] mod app; @@ -6,8 +11,8 @@ mod routes; use saleor_app_sdk::{ config::Config, - manifest::{cargo_info, AppManifest, AppPermission}, - webhooks::{AsyncWebhookEventType, WebhookManifest}, + manifest::{cargo_info, AppManifestBuilder, AppPermission}, + webhooks::{AsyncWebhookEventType, WebhookManifestBuilder}, SaleorApp, }; use std::sync::Arc; @@ -23,7 +28,7 @@ use crate::{ #[tokio::main] async fn main() -> anyhow::Result<()> { let config = Config::load()?; - trace_to_std(&config); + trace_to_std(&config)?; let sitemap_config = SitemapConfig::load()?; debug!("Creating configs..."); @@ -31,13 +36,13 @@ async fn main() -> anyhow::Result<()> { debug!("Creating saleor App..."); - let app_manifest = AppManifest::new(&config, cargo_info!()) + let app_manifest = AppManifestBuilder::new(&config, cargo_info!()) .add_permissions(vec![ AppPermission::ManageProducts, AppPermission::ManagePages, ]) .add_webhook( - WebhookManifest::new(&config) + WebhookManifestBuilder::new(&config) .set_query(EVENTS_QUERY) .add_async_events(vec![ AsyncWebhookEventType::ProductCreated, @@ -98,7 +103,7 @@ async fn main() -> anyhow::Result<()> { .unwrap_or(&"3000"), ) .await?; - info!("listening on {}", listener.local_addr().unwrap()); + info!("listening on {}", listener.local_addr()?); match axum::serve(listener, app).await { Ok(o) => Ok(o), Err(e) => anyhow::bail!(e), diff --git a/sitemap-generator/src/routes/mod.rs b/sitemap-generator/src/routes/mod.rs index 5c251e7..de9c3bd 100644 --- a/sitemap-generator/src/routes/mod.rs +++ b/sitemap-generator/src/routes/mod.rs @@ -23,7 +23,7 @@ pub fn create_routes(state: AppState) -> Router { } let service = handle_404.into_service(); //TODO : Fix this relative path issue in workspaces - let serve_dir = ServeDir::new("./sitemap-generator/public").not_found_service(service); + let serve_dir = ServeDir::new("./public").not_found_service(service); //TODO Query for everything using the app auth token //TODO "Failed fetching initial products: More than one channel exists, please spocify which diff --git a/sitemap-generator/src/routes/register.rs b/sitemap-generator/src/routes/register.rs index 9db31e0..f5b317a 100644 --- a/sitemap-generator/src/routes/register.rs +++ b/sitemap-generator/src/routes/register.rs @@ -198,10 +198,7 @@ pub async fn regenerate(state: AppState, saleor_api_url: String) -> anyhow::Resu category: match xml_data.iter().find(|all| { x.relations .iter() - .find(|rel| { - all.id == **rel && all.data_type == XmlDataType::Category - }) - .is_some() + .any(|rel| all.id == *rel && all.data_type == XmlDataType::Category) }) { Some(c) => Some(event_subjects_updated::Category { slug: c.slug.clone(), @@ -286,34 +283,27 @@ async fn get_all_pages( ); //Keep fetching next page let mut next_cursor = pages.page_info.end_cursor.clone(); - loop { - if let Some(cursor) = &mut next_cursor { - let res = surf::post(saleor_api_url) - .header("authorization-bearer", token) - .run_graphql(GetPagesNext::build(GetPagesNextVariables { after: cursor })) - .await; - if let Ok(query) = &res - && let Some(data) = &query.data - && let Some(pages) = &data.pages - { - all_pages.append( - &mut pages - .edges - .iter() - .map(|p| p.node.clone()) - .collect::>(), - ); - debug!("fetched next pages, eg.:{:?}", &pages.edges.first()); - if !pages.page_info.has_next_page { - break; - } - next_cursor.clone_from(&pages.page_info.end_cursor); - } else { - error!("Failed fetching initial pages! {:?}", &res); - anyhow::bail!("Failed fetching initial pages! {:?}", res); - } + while let Some(cursor) = &mut next_cursor { + let res = surf::post(saleor_api_url) + .header("authorization-bearer", token) + .run_graphql(GetPagesNext::build(GetPagesNextVariables { after: cursor })) + .await; + if let Ok(query) = &res + && let Some(data) = &query.data + && let Some(pages) = &data.pages + { + all_pages.append( + &mut pages + .edges + .iter() + .map(|p| p.node.clone()) + .collect::>(), + ); + debug!("fetched next pages, eg.:{:?}", &pages.edges.first()); + next_cursor.clone_from(&pages.page_info.end_cursor); } else { - break; + error!("Failed fetching next pages! {:?}", &res); + anyhow::bail!("Failed fetching next pages! {:?}", res); } } } else { @@ -349,44 +339,37 @@ async fn get_all_categories(saleor_api_url: &str, token: &str) -> anyhow::Result ); //Keep fetching next page let mut next_cursor = categories.page_info.end_cursor.clone(); - loop { - if let Some(cursor) = &mut next_cursor { - let res = surf::post(saleor_api_url) - .header("authorization-bearer", token) - .run_graphql(GetCategoriesNext::build(GetCategoriesNextVariables { - after: Some(cursor), - })) - .await; - if let Ok(query) = &res - && let Some(data) = &query.data - && let Some(categories) = &data.categories - { - all_categories.append( - &mut categories - .edges - .iter() - .map(|p| p.node.clone()) - .collect::>(), - ); - debug!( - "fetched first categories, eg.:{:?}", - &categories.edges.first() - ); - if !categories.page_info.has_next_page { - break; - } - next_cursor.clone_from(&categories.page_info.end_cursor); - } else { - error!("Failed fetching initial pages! {:?}", &res); - anyhow::bail!("Failed fetching initial pages! {:?}", res); - } + while let Some(cursor) = &mut next_cursor { + let res = surf::post(saleor_api_url) + .header("authorization-bearer", token) + .run_graphql(GetCategoriesNext::build(GetCategoriesNextVariables { + after: Some(cursor), + })) + .await; + if let Ok(query) = &res + && let Some(data) = &query.data + && let Some(categories) = &data.categories + { + all_categories.append( + &mut categories + .edges + .iter() + .map(|p| p.node.clone()) + .collect::>(), + ); + debug!( + "fetched first categories, eg.:{:?}", + &categories.edges.first() + ); + next_cursor.clone_from(&categories.page_info.end_cursor); } else { - break; + error!("Failed fetching next categories! {:?}", &res); + anyhow::bail!("Failed fetching next categories! {:?}", res); } } } else { - error!("Failed fetching initial pages! {:?}", &res); - anyhow::bail!("Failed fetching initial pages! {:?}", res); + error!("Failed fetching initial Categories! {:?}", &res); + anyhow::bail!("Failed fetching initial Categories! {:?}", res); }; info!("All categories collected"); Ok(all_categories) @@ -418,39 +401,32 @@ async fn get_all_collections(saleor_api_url: &str, token: &str) -> anyhow::Resul //Keep fetching next page let mut next_cursor = collections.page_info.end_cursor.clone(); - loop { - if let Some(cursor) = &mut next_cursor { - let res = surf::post(saleor_api_url) - .header("authorization-bearer", token) - .run_graphql(GetCollectionsNext::build(GetCollectionsNextVariables { - after: Some(cursor), - })) - .await; - if let Ok(query) = &res - && let Some(data) = &query.data - && let Some(collections) = &data.collections - { - all_collections.append( - &mut collections - .edges - .iter() - .map(|p| p.node.clone()) - .collect::>(), - ); - debug!( - "fetched next collections, eg.:{:?}", - &collections.edges.first() - ); - if !collections.page_info.has_next_page { - break; - } - next_cursor.clone_from(&collections.page_info.end_cursor); - } else { - error!("Failed fetching initial collecnios! {:?}", &res); - anyhow::bail!("Failed fetching initial collections! {:?}", res); - } + while let Some(cursor) = &mut next_cursor { + let res = surf::post(saleor_api_url) + .header("authorization-bearer", token) + .run_graphql(GetCollectionsNext::build(GetCollectionsNextVariables { + after: Some(cursor), + })) + .await; + if let Ok(query) = &res + && let Some(data) = &query.data + && let Some(collections) = &data.collections + { + all_collections.append( + &mut collections + .edges + .iter() + .map(|p| p.node.clone()) + .collect::>(), + ); + debug!( + "fetched next collections, eg.:{:?}", + &collections.edges.first() + ); + next_cursor.clone_from(&collections.page_info.end_cursor); } else { - break; + error!("Failed fetching next collecnios! {:?}", &res); + anyhow::bail!("Failed fetching next collections! {:?}", res); } } } else { @@ -498,7 +474,7 @@ async fn get_all_products( debug!("fetched first products, eg: {:?}", products.edges.first()); let mut next_cursor = products.page_info.end_cursor.clone(); loop { - if let Some(cursor) = &mut next_cursor { + while let Some(cursor) = &mut next_cursor { let res = surf::post(saleor_api_url) .header("authorization-bearer", token) .run_graphql(GetCategoryProductsNext::build( @@ -526,22 +502,14 @@ async fn get_all_products( .collect::>(), ); debug!("fetched next products, eg: {:?}", products.edges.first()); - if !products.page_info.has_next_page { - break; - } next_cursor.clone_from(&products.page_info.end_cursor); } else { error!("Failed fetching initial products! {:?}", &res); anyhow::bail!("Failed fetching initial products! {:?}", res); } - } else { - break; } } - } else { - error!("Failed fetching initial products! {:?}", &res); - anyhow::bail!("Failed fetching initial products! {:?}", res); - }; + } info!("All products collected..."); Ok(all_categorised_products) } diff --git a/sitemap-generator/src/routes/webhooks.rs b/sitemap-generator/src/routes/webhooks.rs index 5c2ff2d..2fa2946 100644 --- a/sitemap-generator/src/routes/webhooks.rs +++ b/sitemap-generator/src/routes/webhooks.rs @@ -13,12 +13,7 @@ use saleor_app_sdk::{ AsyncWebhookEventType, }, }; -use sitemap_rs::{ - sitemap::Sitemap, - sitemap_index::SitemapIndex, - url::{Url}, - url_set::UrlSet, -}; +use sitemap_rs::{sitemap::Sitemap, sitemap_index::SitemapIndex, url::Url, url_set::UrlSet}; use tinytemplate::TinyTemplate; use tokio::spawn; use tracing::{debug, error, info}; @@ -26,8 +21,8 @@ use tracing::{debug, error, info}; use crate::{ app::{AppError, AppState, XmlData, XmlDataType}, queries::event_subjects_updated::{ - Category, Category2, CategoryUpdated, Collection, CollectionUpdated, Page, - PageUpdated, Product, ProductUpdated, + Category, Category2, CategoryUpdated, Collection, CollectionUpdated, Page, PageUpdated, + Product, ProductUpdated, }, }; @@ -46,8 +41,8 @@ pub async fn webhooks( .to_str()? .to_owned(); let event_type = get_webhook_event_type(&headers)?; - match event_type { - EitherWebhookType::Async(a) => match a { + if let EitherWebhookType::Async(a) = event_type { + match a { AsyncWebhookEventType::ProductUpdated | AsyncWebhookEventType::ProductCreated | AsyncWebhookEventType::ProductDeleted => { @@ -90,8 +85,7 @@ pub async fn webhooks( } _ => (), - }, - _ => (), + } } info!("webhook proccessed"); @@ -185,10 +179,7 @@ async fn update_sitemap_product( xml_cat.last_modified = chrono::offset::Utc::now().fixed_offset(); // If the category exists but product isn't in relation to it yet, // add it - if !xml_cat - .relations - .iter().any(|c| *c == product.id) - { + if !xml_cat.relations.iter().any(|c| *c == product.id) { xml_cat.relations.push(product.id.clone()); } //if cat isn't in xml data, add it @@ -216,10 +207,7 @@ async fn update_sitemap_product( category: match xml_data.iter().find(|all| { x.relations .iter() - .find(|rel| { - all.id == **rel && all.data_type == XmlDataType::Category - }) - .is_some() + .any(|rel| all.id == *rel && all.data_type == XmlDataType::Category) }) { Some(c) => Some(Category { slug: c.slug.clone(), @@ -322,49 +310,38 @@ async fn update_sitemap_category( let mut tt = TinyTemplate::new(); if is_category_in_product_url && x.data_type == XmlDataType::Product { tt.add_template("product_url", &state.sitemap_config.product_template)?; - let context; //If current xml products category is this changed category, just use that instead //of searching for it again - match x.relations.iter().find(|c| *c == &category.id) { - Some(_) => { - context = ProductUpdated { - product: Some(Product { - id: x.id.clone(), - slug: x.slug.clone(), - category: Some(Category { - slug: category.slug.clone(), - id: category.id.clone(), + let context = ProductUpdated { + product: match x.relations.iter().find(|c| *c == &category.id) { + Some(_) => Some(Product { + id: x.id.clone(), + slug: x.slug.clone(), + category: Some(Category { + slug: category.slug.clone(), + id: category.id.clone(), + }), + }), + None => Some(Product { + id: x.id.clone(), + slug: x.slug.clone(), + category: match xml_data.iter().find(|all| { + x.relations.iter().any(|rel| { + all.id == *rel && all.data_type == XmlDataType::Category + }) + }) { + Some(c) => Some(Category { + slug: c.slug.clone(), + id: c.id.clone(), }), - }), - }; - } - None => { - context = ProductUpdated { - product: Some(Product { - id: x.id.clone(), - slug: x.slug.clone(), - category: match xml_data.iter().find(|all| { - x.relations - .iter() - .find(|rel| { - all.id == **rel - && all.data_type == XmlDataType::Category - }) - .is_some() - }) { - Some(c) => Some(Category { - slug: c.slug.clone(), - id: c.id.clone(), - }), - None => Some(Category { - slug: "unknown".to_owned(), - id: cynic::Id::new("unknown".to_owned()), - }), - }, - }), - }; - } - } + None => Some(Category { + slug: "unknown".to_owned(), + id: cynic::Id::new("unknown".to_owned()), + }), + }, + }), + }, + }; product_urls.push( Url::builder(tt.render("product_url", &context)?) .last_modified(x.last_modified) @@ -564,8 +541,7 @@ pub async fn write_xml( let mut sitemaps: Vec = vec![]; for urls in sliced_urls { for url in urls.iter().cloned() { - let mut sitemap_urls: Vec = vec![]; - sitemap_urls.push(url); + let sitemap_urls = vec![url]; sitemaps.push(UrlSet::new(sitemap_urls)?); } } @@ -616,22 +592,25 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> { let sitemaps: Vec = paths .into_iter() - .map(|p| { - Sitemap::new( - format!( - "{}/{}", - state.sitemap_config.index_hostname, - p.file_name() - .expect("file dissapeared or broke during sitemap-index construction") - .to_string_lossy() - ), - p.metadata().map_or(None, |meta| { - meta.modified().map_or(None, |modified| { - let dt_utc: DateTime = modified.into(); - Some(dt_utc.fixed_offset()) - }) - }), - ) + .filter_map(|p| { + if let Some(file_name) = p.file_name() { + Some(Sitemap::new( + format!( + "{}/{}", + state.sitemap_config.index_hostname, + file_name.to_string_lossy() + ), + p.metadata().map_or(None, |meta| { + meta.modified().map_or(None, |modified| { + let dt_utc: DateTime = modified.into(); + Some(dt_utc.fixed_offset()) + }) + }), + )) + } else { + error!("file dissapeared or broke during sitemap-index construction"); + None + } }) .collect::>(); let sitemap_index = SitemapIndex::new(sitemaps)?; @@ -646,7 +625,7 @@ async fn update_sitemap_index(state: &AppState) -> anyhow::Result<()> { let mut buf = Vec::::new(); sitemap_index.write(&mut buf)?; - file.write_all(&mut buf).await?; + file.write_all(&buf).await?; Ok(()) }