This commit is contained in:
JMARyA 2024-09-12 11:48:09 +02:00
parent 37475460e2
commit 02966c0605
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
9 changed files with 340 additions and 13 deletions

255
Cargo.lock generated
View file

@ -294,6 +294,7 @@ dependencies = [
"mdq",
"mongod",
"mongodb",
"reqwest",
"rocket",
"rocket_cors",
"serde",
@ -387,6 +388,16 @@ dependencies = [
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
@ -665,6 +676,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
@ -965,6 +991,19 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
@ -1333,6 +1372,23 @@ dependencies = [
"version_check",
]
[[package]]
name = "native-tls"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -1383,6 +1439,50 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "openssl"
version = "0.10.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "openssl-probe"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "overload"
version = "0.1.1"
@ -1462,6 +1562,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -1623,6 +1729,46 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "reqwest"
version = "0.11.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
dependencies = [
"base64 0.21.7",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http 0.2.12",
"http-body",
"hyper",
"hyper-tls",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-native-tls",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winreg",
]
[[package]]
name = "resolv-conf"
version = "0.7.0"
@ -1846,6 +1992,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
@ -1868,6 +2023,29 @@ dependencies = [
"untrusted",
]
[[package]]
name = "security-framework"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.6.0",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "semver"
version = "0.9.0"
@ -1940,6 +2118,18 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_with"
version = "1.14.0"
@ -2150,6 +2340,33 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sync_wrapper"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "take_mut"
version = "0.2.2"
@ -2280,6 +2497,16 @@ dependencies = [
"syn 2.0.77",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.24.1"
@ -2606,6 +2833,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.5"
@ -2663,6 +2896,18 @@ dependencies = [
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.93"
@ -2692,6 +2937,16 @@ version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
[[package]]
name = "web-sys"
version = "0.3.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki-roots"
version = "0.25.4"

View file

@ -20,3 +20,4 @@ uuid = { version = "1.8.0", features = ["v4"] }
mongod = { git = "https://git.hydrar.de/jmarya/mongod" }
env_logger = "0.11.5"
walkdir = "2.5.0"
reqwest = { version = "0.11", features = ["json"] }

View file

@ -1 +1,13 @@
# Only these tokens are authorized to make requests
allowed_tokens = ["password"]
# Webhook Notifications
[webhook]
# Item Variants inventory goes below the minimum
item_below_minimum = "https://example.com"
# Transaction gets added
transaction_added = "https://example.com"
# Transaction gets consumed
transaction_consumed = "https://example.com"

View file

@ -1,3 +1,9 @@
# Webhooks
Certain events can trigger webhooks. This allows you to independently build your automation pipeline.
#todo
Webhooks are configured in the `config.toml` file under `[webhook]`.
## Webhook Events
These events can trigger a webhook:
- Add a transaction
- Consume a transaction
- Item Variant amount goes below specified minimum

View file

@ -4,12 +4,15 @@ use serde::Deserialize;
pub struct Config {
/// Allowed tokens for access
pub allowed_tokens: Vec<String>,
/// Webhook Config
pub webhook: Option<Webhook>,
}
impl Default for Config {
fn default() -> Self {
Self {
allowed_tokens: Vec::new(),
webhook: None,
}
}
}
@ -21,3 +24,17 @@ pub fn get_config() -> Config {
Config::default()
}
#[derive(Debug, Clone, Deserialize)]
pub struct Webhook {
pub item_below_minimum: Option<String>,
pub transaction_added: Option<String>,
pub transaction_consumed: Option<String>,
}
impl Webhook {
pub async fn send(url: &str, data: &serde_json::Value) {
let client = reqwest::Client::new();
client.post(url).json(data).send().await.unwrap();
}
}

View file

@ -1,10 +1,12 @@
use mongod::{Model, ToAPI};
use rocket::serde::json::Json;
use rocket::{get, post, State};
use serde::Deserialize;
use serde_json::json;
use crate::check_auth;
use crate::config::Config;
use crate::config::{Config, Webhook};
use crate::item::Item;
use crate::routes::Token;
use crate::variant::Variant;
use crate::{
@ -26,7 +28,7 @@ pub struct DemandForm {
pub async fn demand_route(f: Json<DemandForm>, t: Token, c: &State<Config>) -> FallibleApiResponse {
check_auth!(t, c);
Variant::demand(
let transaction = Variant::demand(
&f.uuid,
f.price
.clone()
@ -37,6 +39,33 @@ pub async fn demand_route(f: Json<DemandForm>, t: Token, c: &State<Config>) -> F
.await
.ok_or_else(|| api_error("Demand failed"))?;
if let Some(hook) = &c.webhook {
if let Some(url) = &hook.transaction_consumed {
Webhook::send(url, &transaction.api().await).await;
}
if let Some(url) = &hook.item_below_minimum {
let variant = Item::get(&transaction.item)
.await
.unwrap()
.variant(&transaction.variant)
.unwrap();
let min_res = variant.is_below_min().await;
if min_res.0 {
Webhook::send(
url,
&json!({
"item": transaction.item,
"variant": transaction.variant,
"minimum": variant.min,
"current_amount": variant.min.unwrap() - min_res.1
}),
)
.await;
}
}
}
Ok(json!({"ok": 1}))
}

View file

@ -1,10 +1,11 @@
use mongod::ToAPI;
use rocket::serde::json::Json;
use rocket::{get, post, State};
use serde::Deserialize;
use serde_json::json;
use crate::check_auth;
use crate::config::Config;
use crate::config::{Config, Webhook};
use crate::routes::Token;
use crate::{
db::ItemDB,
@ -38,7 +39,7 @@ pub async fn supply_route(
.variant(&form.variant)
.ok_or_else(variant_does_not_exist_error)?;
let transaction_id = variant
let transaction = variant
.supply(
form.price
.clone()
@ -49,7 +50,13 @@ pub async fn supply_route(
)
.await;
Ok(json!({"uuid": transaction_id}))
if let Some(hook) = &c.webhook {
if let Some(url) = &hook.transaction_added {
Webhook::send(url, &transaction.api().await).await;
}
}
Ok(json!({"uuid": transaction._id}))
}
/// Returns a list of Transaction UUIDs for the Item Variant

View file

@ -77,7 +77,7 @@ impl Transaction {
}
/// Consumes the Item with `price` and `destination`
pub async fn consume(self, price: Price, destination: &str) {
pub async fn consume(self, price: Price, destination: &str) -> Self {
self.change()
.consumed(Some(Consumed {
destination: destination.to_string(),
@ -86,7 +86,7 @@ impl Transaction {
}))
.update()
.await
.unwrap();
.unwrap()
}
pub async fn is_expired(&self) -> bool {

View file

@ -125,11 +125,11 @@ impl Variant {
ret
}
pub async fn demand(uuid: &str, price: Price, destination: &str) -> Option<()> {
pub async fn demand(uuid: &str, price: Price, destination: &str) -> Option<Transaction> {
// check if transaction exists
let mut t = Transaction::get(uuid).await?;
t.consume(price, destination).await;
Some(())
t = t.consume(price, destination).await;
Some(t)
}
/// Records a supply transaction in the database.
@ -147,12 +147,12 @@ impl Variant {
price: Price,
origin: Option<&str>,
location: Option<&str>,
) -> String {
) -> Transaction {
let t = Transaction::new(&self.item, &self.variant, price, origin, location).await;
t.insert().await.unwrap();
t._id
t
}
pub async fn get_all_transactions(&self) -> Vec<Transaction> {