Fix all AppBridge payloads, split to actions and events etc
Some checks failed
clippy / clippy (push) Has been cancelled
Some checks failed
clippy / clippy (push) Has been cancelled
This commit is contained in:
parent
3d916f1ff4
commit
27c039278c
13 changed files with 216 additions and 52 deletions
6
.env
6
.env
|
@ -1,10 +1,10 @@
|
||||||
## COMMON VARIABLES FOR ALL APPS
|
## COMMON VARIABLES FOR ALL APPS
|
||||||
REQUIRED_SALEOR_VERSION="^3.13"
|
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
|
# 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.29:3000"
|
APP_API_BASE_URL="http://10.100.110.60:3000"
|
||||||
APP_IFRAME_BASE_URL="http://10.100.110.29:3000"
|
APP_IFRAME_BASE_URL="http://10.100.110.60:3000"
|
||||||
APL="File"
|
APL="File"
|
||||||
APL_URL="./temp/apl.json"
|
APL_URL="apl.json"
|
||||||
LOG_LEVEL="DEBUG"
|
LOG_LEVEL="DEBUG"
|
||||||
|
|
||||||
## THESE VARIABLES ARE FOR SITEMAP-GENERATOR APP
|
## THESE VARIABLES ARE FOR SITEMAP-GENERATOR APP
|
||||||
|
|
9
apl.json
Normal file
9
apl.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"http://localhost:8000/graphql/": {
|
||||||
|
"domain": "http://10.100.110.60:3000",
|
||||||
|
"token": "NhJa5QG3J4UGbXQSiYF9L7HySMCKqA",
|
||||||
|
"saleorApiUrl": "http://localhost:8000/graphql/",
|
||||||
|
"appId": "saleor-app-template-ui",
|
||||||
|
"jwks": null
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,17 +41,7 @@ envy = { workspace = true }
|
||||||
cynic = { workspace = true, features = ["http-surf"], optional = true }
|
cynic = { workspace = true, features = ["http-surf"], optional = true }
|
||||||
surf = { workspace = true, optional = true }
|
surf = { workspace = true, optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_family = "unix")'.dependencies]
|
saleor-app-sdk = { workspace = true, optional = true }
|
||||||
saleor-app-sdk = { workspace = true, optional = true, features = [
|
|
||||||
"file_apl",
|
|
||||||
"redis_apl",
|
|
||||||
"tracing",
|
|
||||||
"middleware",
|
|
||||||
"webhook_utils",
|
|
||||||
] }
|
|
||||||
|
|
||||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
|
||||||
saleor-app-sdk = { workspace = true, optional = true, features = ["bridge"] }
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cynic-codegen = { workspace = true, optional = true }
|
cynic-codegen = { workspace = true, optional = true }
|
||||||
|
@ -79,6 +69,7 @@ ssr = [
|
||||||
"leptos/ssr",
|
"leptos/ssr",
|
||||||
"leptos_meta/ssr",
|
"leptos_meta/ssr",
|
||||||
"leptos_router/ssr",
|
"leptos_router/ssr",
|
||||||
|
"saleor-app-sdk/bridge",
|
||||||
]
|
]
|
||||||
hydrate = [
|
hydrate = [
|
||||||
"leptos/hydrate",
|
"leptos/hydrate",
|
||||||
|
|
|
@ -55,7 +55,11 @@ async fn main() -> Result<(), std::io::Error> {
|
||||||
let saleor_app = SaleorApp::new(&config).unwrap();
|
let saleor_app = SaleorApp::new(&config).unwrap();
|
||||||
|
|
||||||
let app_manifest = AppManifestBuilder::new(&config, cargo_info!())
|
let app_manifest = AppManifestBuilder::new(&config, cargo_info!())
|
||||||
.add_permission(AppPermission::ManageProducts)
|
.add_permissions(vec![
|
||||||
|
AppPermission::ManageProducts,
|
||||||
|
AppPermission::ManageOrders,
|
||||||
|
AppPermission::ManageProductTypesAndAttributes,
|
||||||
|
])
|
||||||
.add_extension(
|
.add_extension(
|
||||||
AppExtensionBuilder::new()
|
AppExtensionBuilder::new()
|
||||||
.set_url("/extensions/order_to_pdf")
|
.set_url("/extensions/order_to_pdf")
|
||||||
|
@ -69,7 +73,8 @@ async fn main() -> Result<(), std::io::Error> {
|
||||||
.set_target(AppExtensionTarget::Popup)
|
.set_target(AppExtensionTarget::Popup)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.build();
|
.build()
|
||||||
|
.expect("Manifest has invalid parameters");
|
||||||
|
|
||||||
let app_state = AppState {
|
let app_state = AppState {
|
||||||
manifest: app_manifest,
|
manifest: app_manifest,
|
||||||
|
@ -89,11 +94,11 @@ async fn main() -> Result<(), std::io::Error> {
|
||||||
.fallback(file_and_error_handler)
|
.fallback(file_and_error_handler)
|
||||||
.route(
|
.route(
|
||||||
"/api/webhooks",
|
"/api/webhooks",
|
||||||
post(webhooks).route_layer(middleware::from_fn(webhook_signature_verifier)),
|
post(webhooks)//.route_layer(middleware::from_fn(webhook_signature_verifier)),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/register",
|
"/api/register",
|
||||||
post(register).route_layer(middleware::from_fn(webhook_signature_verifier)),
|
post(register)//.route_layer(middleware::from_fn(webhook_signature_verifier)),
|
||||||
)
|
)
|
||||||
.route("/api/manifest", get(manifest))
|
.route("/api/manifest", get(manifest))
|
||||||
.with_state(app_state.clone());
|
.with_state(app_state.clone());
|
||||||
|
|
|
@ -5,9 +5,9 @@ use axum::{
|
||||||
http::{HeaderMap, StatusCode},
|
http::{HeaderMap, StatusCode},
|
||||||
};
|
};
|
||||||
use saleor_app_sdk::{AuthData, AuthToken};
|
use saleor_app_sdk::{AuthData, AuthToken};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
use crate::{app::AppState, error_template::AxumError};
|
use crate::{app::AppState, error_template::{self, AxumError}};
|
||||||
|
|
||||||
|
|
||||||
pub async fn register(
|
pub async fn register(
|
||||||
|
@ -34,7 +34,10 @@ pub async fn register(
|
||||||
app_id: state.manifest.id,
|
app_id: state.manifest.id,
|
||||||
saleor_api_url: saleor_api_url.clone(),
|
saleor_api_url: saleor_api_url.clone(),
|
||||||
};
|
};
|
||||||
app.apl.set(auth_data).await?;
|
if let Err(e) = app.apl.set(auth_data).await{
|
||||||
|
error!("{:?}",e);
|
||||||
|
return Err(error_template::AxumError::Anyhow(e))
|
||||||
|
};
|
||||||
|
|
||||||
info!("registered app for{:?}", &saleor_api_url);
|
info!("registered app for{:?}", &saleor_api_url);
|
||||||
Ok(StatusCode::OK)
|
Ok(StatusCode::OK)
|
||||||
|
|
|
@ -1,7 +1,46 @@
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
use leptos_dom::logging::{console_error, console_log};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Pdf() -> impl IntoView {
|
pub fn Pdf() -> impl IntoView {
|
||||||
|
let bridge = create_effect(|_| {
|
||||||
|
use saleor_app_sdk::bridge::AppBridge;
|
||||||
|
use saleor_app_sdk::{
|
||||||
|
bridge::action::{Action, PayloadRequestPermissions},
|
||||||
|
manifest::AppPermission,
|
||||||
|
};
|
||||||
|
match AppBridge::new(true) {
|
||||||
|
Ok(mut app_bridge) => {
|
||||||
|
console_log("App Bridge connected");
|
||||||
|
let cb_handle = app_bridge
|
||||||
|
.listen_to_events(|event| match event {
|
||||||
|
Ok(event) => console_log(&format!("order_to_pdf: {:?}", event)),
|
||||||
|
Err(e) => console_error(&format!("order_to_pdf: {:?}", e)),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
//TODO: imagine leaking memory on purpose xd
|
||||||
|
cb_handle.forget();
|
||||||
|
_ = app_bridge.dispatch_event(Action::RequestPermissions(
|
||||||
|
PayloadRequestPermissions {
|
||||||
|
permissions: vec![AppPermission::ManageOrders],
|
||||||
|
redirect_path: "".to_owned(),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Err(e) => console_error(&format!("{:?}", e)),
|
||||||
|
}; // let mut bridge = bridge.unwrap();
|
||||||
|
|
||||||
|
// match bridge.dispatch_event(Event::Handshake(PayloadHanshake::default())) {
|
||||||
|
// Ok(ev) => {
|
||||||
|
// console_log(&format! {"{:?}",ev});
|
||||||
|
// }
|
||||||
|
// Err(e) => {
|
||||||
|
// console_log(&format! {"{:?}",e});
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// async fn temp(){}
|
||||||
|
// temp()
|
||||||
|
});
|
||||||
view! {
|
view! {
|
||||||
<h1>Yello!</h1>
|
<h1>Yello!</h1>
|
||||||
<p class="italic text-lg">r#"Loading AppBridge, please wait..."#</p>
|
<p class="italic text-lg">r#"Loading AppBridge, please wait..."#</p>
|
||||||
|
|
|
@ -76,7 +76,9 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.add_permission(AppPermission::ManageProducts)
|
.add_permission(AppPermission::ManageProducts)
|
||||||
.build();
|
.build()
|
||||||
|
.expect("Manifest has invalid parameters");
|
||||||
|
|
||||||
let app_state = AppState {
|
let app_state = AppState {
|
||||||
manifest: app_manifest,
|
manifest: app_manifest,
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
|
|
45
sdk/src/bridge/action.rs
Normal file
45
sdk/src/bridge/action.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::manifest::AppPermission;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[serde(tag = "type", content = "payload")]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub enum Action {
|
||||||
|
Redirect(PayloadRedirect),
|
||||||
|
RequestPermissions(PayloadRequestPermissions),
|
||||||
|
NotifyReady(String),
|
||||||
|
Notification(PayloadNotification),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PayloadRequestPermissions {
|
||||||
|
pub permissions: Vec<AppPermission>,
|
||||||
|
pub redirect_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PayloadNotification {
|
||||||
|
pub status: Option<NotificationStatus>,
|
||||||
|
pub title: Option<String>,
|
||||||
|
pub text: Option<String>,
|
||||||
|
pub api_message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum NotificationStatus {
|
||||||
|
Info,
|
||||||
|
Success,
|
||||||
|
Warning,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PayloadRedirect {
|
||||||
|
pub to: String,
|
||||||
|
pub new_context: Option<bool>,
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::locales::LocaleCode;
|
use crate::{locales::LocaleCode, manifest::AppPermission};
|
||||||
|
|
||||||
use super::ThemeType;
|
use super::ThemeType;
|
||||||
// use bus::{Bus, BusReader};
|
// use bus::{Bus, BusReader};
|
||||||
|
@ -72,14 +72,38 @@ pub enum Event {
|
||||||
Theme(PayloadTheme),
|
Theme(PayloadTheme),
|
||||||
LocaleChanged(PayloadLocaleChanged),
|
LocaleChanged(PayloadLocaleChanged),
|
||||||
TokenRefreshed(PayloadTokenRefreshed),
|
TokenRefreshed(PayloadTokenRefreshed),
|
||||||
NotifyReady(String),
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PayloadRequestPermissions {
|
||||||
|
pub permissions: Vec<AppPermission>,
|
||||||
|
pub redirect_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PayloadNotification {
|
||||||
|
pub status: Option<NotificationStatus>,
|
||||||
|
pub title: Option<String>,
|
||||||
|
pub text: Option<String>,
|
||||||
|
pub api_message: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum NotificationStatus {
|
||||||
|
Info,
|
||||||
|
Success,
|
||||||
|
Warning,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PayloadHanshake {
|
pub struct PayloadHanshake {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
pub version: String,
|
pub version: f32,
|
||||||
pub saleor_version: Option<String>,
|
pub saleor_version: Option<String>,
|
||||||
pub dashboard_version: Option<String>,
|
pub dashboard_version: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -87,23 +111,24 @@ pub struct PayloadHanshake {
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PayloadResponse {
|
pub struct PayloadResponse {
|
||||||
pub action_id: String,
|
pub action_id: Option<String>,
|
||||||
pub ok: bool,
|
pub ok: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PayloadRedirect {
|
pub struct PayloadRedirect {
|
||||||
pub path: String,
|
pub to: String,
|
||||||
|
pub new_context: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PayloadTheme {
|
pub struct PayloadTheme {
|
||||||
pub theme: ThemeType,
|
pub theme: ThemeType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PayloadLocaleChanged {
|
pub struct PayloadLocaleChanged {
|
||||||
pub locale: LocaleCode,
|
pub locale: LocaleCode,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
pub mod action;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use action::Action;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use strum_macros::{EnumString, IntoStaticStr};
|
use strum_macros::{EnumString, IntoStaticStr};
|
||||||
use wasm_bindgen::{closure::Closure, JsCast, JsValue};
|
use wasm_bindgen::{closure::Closure, JsCast, JsValue};
|
||||||
|
@ -9,7 +11,7 @@ use wasm_bindgen::{closure::Closure, JsCast, JsValue};
|
||||||
use crate::{locales::LocaleCode, manifest::AppPermission};
|
use crate::{locales::LocaleCode, manifest::AppPermission};
|
||||||
|
|
||||||
use self::event::Event;
|
use self::event::Event;
|
||||||
use web_sys::console;
|
use web_sys::{console, js_sys::JSON};
|
||||||
|
|
||||||
pub struct AppBridge {
|
pub struct AppBridge {
|
||||||
pub state: AppBridgeState,
|
pub state: AppBridgeState,
|
||||||
|
@ -19,7 +21,7 @@ pub struct AppBridge {
|
||||||
* Should automatically emit Actions.NotifyReady.
|
* Should automatically emit Actions.NotifyReady.
|
||||||
* If app loading time is longer, this can be disabled and sent manually.
|
* If app loading time is longer, this can be disabled and sent manually.
|
||||||
*/
|
*/
|
||||||
auto_notify_ready: Option<bool>,
|
auto_notify_ready: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
@ -120,7 +122,7 @@ impl Default for ThemeType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppBridge {
|
impl AppBridge {
|
||||||
pub fn new(auto_notify_ready: Option<bool>) -> Result<Self, AppBridgeError> {
|
pub fn new(auto_notify_ready: bool) -> Result<Self, AppBridgeError> {
|
||||||
// debug!("creating app bridge");
|
// debug!("creating app bridge");
|
||||||
console::log_1(&"creating app bridge".into());
|
console::log_1(&"creating app bridge".into());
|
||||||
if web_sys::Window::is_type_of(&JsValue::from_str("undefined")) {
|
if web_sys::Window::is_type_of(&JsValue::from_str("undefined")) {
|
||||||
|
@ -148,39 +150,61 @@ impl AppBridge {
|
||||||
},
|
},
|
||||||
referer_origin: referrer,
|
referer_origin: referrer,
|
||||||
};
|
};
|
||||||
if bridge.auto_notify_ready.unwrap_or(false) {
|
if bridge.auto_notify_ready {
|
||||||
bridge.notify_ready()?;
|
bridge.notify_ready()?;
|
||||||
}
|
}
|
||||||
Ok(bridge)
|
Ok(bridge)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen_to_events(&mut self) -> Result<&mut Self, AppBridgeError> {
|
/*
|
||||||
|
* make sure to keep the returned closure handle safe, once it deallocs events will no longer
|
||||||
|
* trigger
|
||||||
|
*/
|
||||||
|
pub fn listen_to_events(
|
||||||
|
&mut self,
|
||||||
|
mut on_event: impl FnMut(Result<Event, serde_wasm_bindgen::Error>) + 'static,
|
||||||
|
) -> Result<Closure<dyn FnMut(JsValue)>, AppBridgeError> {
|
||||||
let window = web_sys::window().ok_or(AppBridgeError::WindowIsUndefined)?;
|
let window = web_sys::window().ok_or(AppBridgeError::WindowIsUndefined)?;
|
||||||
let cb = Closure::wrap(Box::new(|e: JsValue| {
|
let cb = Closure::wrap(Box::new(move |e: JsValue| {
|
||||||
let event_data: Result<SaleorIframeEvent, _> = serde_wasm_bindgen::from_value(e);
|
web_sys::console::log_1(
|
||||||
web_sys::console::log_1(&format!("{:?}", &event_data).into());
|
&format!(
|
||||||
// debug!("{:?}", &event_data);
|
"sdk::bridge::listen_to_events: {:?}",
|
||||||
}) as Box<dyn FnMut(_)>);
|
&JSON::stringify(&web_sys::js_sys::Reflect::get(&e, &"data".into()).unwrap())
|
||||||
|
.unwrap()
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
let event_data: Result<Event, _> = serde_wasm_bindgen::from_value(
|
||||||
|
web_sys::js_sys::Reflect::get(&e, &"data".into())
|
||||||
|
.expect("Closure should've received object with .data property, but didn't, saleor plz fix?"),
|
||||||
|
);
|
||||||
|
// web_sys::console::log_1(&format!("{:?}", &event_data).into());
|
||||||
|
on_event(event_data);
|
||||||
|
}) as Box<dyn FnMut(JsValue)>);
|
||||||
|
|
||||||
window
|
window
|
||||||
.add_event_listener_with_callback("message", &cb.as_ref().unchecked_ref())
|
.add_event_listener_with_callback("message", &cb.as_ref().unchecked_ref())
|
||||||
.map_err(|e| AppBridgeError::JsValue(e))?;
|
.map_err(|e| AppBridgeError::JsValue(e))?;
|
||||||
Ok(self)
|
Ok(cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_event(&mut self, event: Event) -> Result<Event, AppBridgeError> {
|
pub fn dispatch_event(&mut self, action: Action) -> Result<(), AppBridgeError> {
|
||||||
let window = web_sys::window().ok_or(AppBridgeError::WindowIsUndefined)?;
|
let window = web_sys::window().ok_or(AppBridgeError::WindowIsUndefined)?;
|
||||||
let parent = match window.parent() {
|
let parent = match window.parent() {
|
||||||
Ok(p) => p.ok_or(AppBridgeError::WindowParentIsUndefined)?,
|
Ok(p) => p.ok_or(AppBridgeError::WindowParentIsUndefined)?,
|
||||||
Err(e) => return Err(AppBridgeError::JsValue(e)),
|
Err(e) => return Err(AppBridgeError::JsValue(e)),
|
||||||
};
|
};
|
||||||
let message = JsValue::from_str(&serde_json::to_string(&event)?);
|
// let message = JsValue::from(&event);
|
||||||
|
let message = serde_wasm_bindgen::to_value(&action)?;
|
||||||
|
web_sys::console::log_1(&message);
|
||||||
parent
|
parent
|
||||||
.post_message(&message, "*")
|
.post_message(&message, "*")
|
||||||
.map_err(|e| AppBridgeError::JsValue(e))?;
|
.map_err(|e| AppBridgeError::JsValue(e))?;
|
||||||
todo!()
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn notify_ready(&mut self) -> Result<&mut Self, AppBridgeError> {
|
pub fn notify_ready(&mut self) -> Result<&mut Self, AppBridgeError> {
|
||||||
self.dispatch_event(Event::NotifyReady("{}".to_owned()))?;
|
self.dispatch_event(Action::NotifyReady("{}".to_owned()))?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,6 +225,6 @@ pub enum AppBridgeError {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct SaleorIframeEvent {
|
pub struct SaleorIframeEvent {
|
||||||
origin: String,
|
pub origin: String,
|
||||||
data: Event,
|
pub data: Event,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub mod extension;
|
pub mod extension;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{config::Config, webhooks::WebhookManifest};
|
use crate::{config::Config, webhooks::WebhookManifest};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
pub enum AppPermission {
|
pub enum AppPermission {
|
||||||
ManageUsers,
|
ManageUsers,
|
||||||
|
@ -213,9 +214,26 @@ impl AppManifestBuilder {
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn build(self) -> AppManifest {
|
pub fn build(self) -> Result<AppManifest, AppManifestBuilderError> {
|
||||||
self.manifest
|
if let Some(ext) = self
|
||||||
|
.manifest
|
||||||
|
.extensions
|
||||||
|
.as_ref()
|
||||||
|
.map(|exts| exts.iter().flat_map(|e| &e.permissions).collect::<Vec<_>>())
|
||||||
|
{
|
||||||
|
match ext.iter().all(|e| self.manifest.permissions.contains(e)) {
|
||||||
|
true => Ok(self.manifest),
|
||||||
|
false => Err(AppManifestBuilderError::MismatchedPermissions),
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(self.manifest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum AppManifestBuilderError {
|
||||||
|
#[error("manifest.permissions doesn't list all permissions needed in manifest.extensions.permissions")]
|
||||||
|
MismatchedPermissions,
|
||||||
}
|
}
|
||||||
pub struct CargoInfo {
|
pub struct CargoInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
@ -86,14 +86,15 @@ async fn main() -> anyhow::Result<()> {
|
||||||
AppPermission::ManageCheckouts,
|
AppPermission::ManageCheckouts,
|
||||||
AppPermission::HandleCheckouts,
|
AppPermission::HandleCheckouts,
|
||||||
])
|
])
|
||||||
.build();
|
.build()
|
||||||
|
.expect("Manifest has invalid parameters");
|
||||||
|
|
||||||
let app_state = AppState {
|
let app_state = AppState {
|
||||||
active_payment_methods: get_active_payment_methods_from_env()?,
|
active_payment_methods: get_active_payment_methods_from_env()?,
|
||||||
manifest: app_manifest,
|
manifest: app_manifest,
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
saleor_app: Arc::new(Mutex::new(saleor_app)),
|
saleor_app: Arc::new(Mutex::new(saleor_app)),
|
||||||
cod_extra_price_as_product_slug: std::env::var("COD_EXTRA_PRICE_AS_PRODUCT_SLUG").ok()
|
cod_extra_price_as_product_slug: std::env::var("COD_EXTRA_PRICE_AS_PRODUCT_SLUG").ok(),
|
||||||
};
|
};
|
||||||
let app = create_routes(app_state);
|
let app = create_routes(app_state);
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,9 @@ async fn create_app(config: &Config, sitemap_config: SitemapConfig) -> Router {
|
||||||
])
|
])
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.build();
|
.build()
|
||||||
|
.expect("Manifest has invalid parameters");
|
||||||
|
|
||||||
debug!("Created AppManifest...");
|
debug!("Created AppManifest...");
|
||||||
|
|
||||||
let (sender, receiver) = tokio::sync::mpsc::channel(100);
|
let (sender, receiver) = tokio::sync::mpsc::channel(100);
|
||||||
|
|
Loading…
Reference in a new issue