From 424499d4002280803010869e1a21a42a7a81fbed Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Fri, 17 Nov 2023 11:22:04 +0100 Subject: [PATCH 1/9] package updates and code cosmetics --- Cargo.lock | 216 +++++++++++++++++++++-------------- Cargo.toml | 2 +- ffplayout-engine/Cargo.toml | 2 +- ffplayout-engine/src/main.rs | 2 +- lib/src/utils/mod.rs | 2 +- 5 files changed, 136 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2d69f9d..6b905d75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,21 +458,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] +[[package]] +name = "async-channel" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" +dependencies = [ + "concurrent-queue", + "event-listener 3.1.0", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-executor" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" dependencies = [ - "async-lock", + "async-lock 2.8.0", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite", + "futures-lite 1.13.0", "slab", ] @@ -482,12 +495,12 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-io", - "async-lock", + "async-lock 2.8.0", "blocking", - "futures-lite", + "futures-lite 1.13.0", "once_cell", ] @@ -497,11 +510,11 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite", + "futures-lite 1.13.0", "log", "parking", "polling", @@ -517,7 +530,18 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb2ab2aa8a746e221ab826c73f48bc6ba41be6763f0855cb249eb6d154cf1d7" +dependencies = [ + "event-listener 3.1.0", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -527,15 +551,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ "async-attributes", - "async-channel", + "async-channel 1.9.0", "async-global-executor", "async-io", - "async-lock", + "async-lock 2.8.0", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite", + "futures-lite 1.13.0", "gloo-timers", "kv-log-macro", "log", @@ -660,16 +684,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.1.0", + "async-lock 3.1.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite", + "futures-lite 2.0.1", "piper", "tracing", ] @@ -769,7 +793,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" dependencies = [ - "hashbrown 0.14.2", + "hashbrown", "stacker", ] @@ -781,9 +805,9 @@ checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" [[package]] name = "clap" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -791,9 +815,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -1011,7 +1035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.2", + "hashbrown", "lock_api", "once_cell", "parking_lot_core", @@ -1110,9 +1134,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys", @@ -1135,6 +1159,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +dependencies = [ + "event-listener 3.1.0", + "pin-project-lite", +] + [[package]] name = "faccess" version = "0.2.4" @@ -1163,14 +1208,14 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "ffplayout" -version = "0.20.0" +version = "0.20.1" dependencies = [ "chrono", "clap", "crossbeam-channel", "ffplayout-lib", "futures", - "itertools", + "itertools 0.12.0", "notify", "notify-debouncer-full", "rand", @@ -1185,7 +1230,7 @@ dependencies = [ [[package]] name = "ffplayout-api" -version = "0.20.0" +version = "0.20.1" dependencies = [ "actix-files", "actix-multipart", @@ -1224,7 +1269,7 @@ dependencies = [ [[package]] name = "ffplayout-lib" -version = "0.20.0" +version = "0.20.1" dependencies = [ "chrono", "crossbeam-channel", @@ -1413,6 +1458,16 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.29" @@ -1501,9 +1556,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1511,19 +1566,13 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap", "slab", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.2" @@ -1540,7 +1589,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.2", + "hashbrown", ] [[package]] @@ -1593,9 +1642,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -1708,16 +1757,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.1.0" @@ -1725,7 +1764,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown", ] [[package]] @@ -1783,6 +1822,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -2593,13 +2641,13 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.2.0" +version = "7.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" dependencies = [ "libc", "rtoolbox", - "winapi", + "windows-sys", ] [[package]] @@ -2624,12 +2672,12 @@ dependencies = [ [[package]] name = "rtoolbox" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" +checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" dependencies = [ "libc", - "winapi", + "windows-sys", ] [[package]] @@ -2663,9 +2711,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" dependencies = [ "bitflags 2.4.1", "errno", @@ -2676,9 +2724,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.8" +version = "0.21.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", "ring", @@ -2688,9 +2736,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64", ] @@ -2810,7 +2858,7 @@ version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ - "indexmap 2.1.0", + "indexmap", "itoa", "ryu", "serde", @@ -2887,9 +2935,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core", @@ -2930,9 +2978,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" @@ -2985,7 +3033,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" dependencies = [ - "itertools", + "itertools 0.11.0", "nom", "unicode_categories", ] @@ -3017,7 +3065,7 @@ dependencies = [ "crossbeam-queue", "dotenvy", "either", - "event-listener", + "event-listener 2.5.3", "futures-channel", "futures-core", "futures-intrusive", @@ -3025,7 +3073,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.1.0", + "indexmap", "log", "memchr", "once_cell", @@ -3298,7 +3346,7 @@ dependencies = [ "cfg-if", "fastrand 2.0.1", "redox_syscall 0.4.1", - "rustix 0.38.21", + "rustix 0.38.24", "windows-sys", ] @@ -3313,7 +3361,7 @@ dependencies = [ [[package]] name = "tests" -version = "0.20.0" +version = "0.20.1" dependencies = [ "chrono", "crossbeam-channel", @@ -3416,9 +3464,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -3435,9 +3483,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", @@ -3864,18 +3912,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" dependencies = [ "proc-macro2", "quote", @@ -3884,9 +3932,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" [[package]] name = "zeromq" diff --git a/Cargo.toml b/Cargo.toml index 588555df..6c579d06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ default-members = ["ffplayout-api", "ffplayout-engine", "tests"] resolver = "2" [workspace.package] -version = "0.20.0" +version = "0.20.1" license = "GPL-3.0" repository = "https://github.com/ffplayout/ffplayout" authors = ["Jonathan Baecker "] diff --git a/ffplayout-engine/Cargo.toml b/ffplayout-engine/Cargo.toml index c5533c37..75089335 100644 --- a/ffplayout-engine/Cargo.toml +++ b/ffplayout-engine/Cargo.toml @@ -16,7 +16,7 @@ chrono = { version = "0.4", default-features = false, features = ["clock", "std" clap = { version = "4.3", features = ["derive"] } crossbeam-channel = "0.5" futures = "0.3" -itertools = "0.11" +itertools = "0.12" notify = "6.0" notify-debouncer-full = { version = "*", default-features = false } rand = "0.8" diff --git a/ffplayout-engine/src/main.rs b/ffplayout-engine/src/main.rs index b0265d79..fcbea1bf 100644 --- a/ffplayout-engine/src/main.rs +++ b/ffplayout-engine/src/main.rs @@ -126,7 +126,7 @@ fn main() { let config_clone1 = config.clone(); let config_clone2 = config.clone(); - if ![2, 4, 6, 8].contains(&config.processing.audio_channels) { + if !matches!(config.processing.audio_channels, 2 | 4 | 6 | 8) { error!( "Encoding {} channel(s) is not allowed. Only 2, 4, 6 and 8 channels are supported!", config.processing.audio_channels diff --git a/lib/src/utils/mod.rs b/lib/src/utils/mod.rs index 12a747c3..17f7c8c0 100644 --- a/lib/src/utils/mod.rs +++ b/lib/src/utils/mod.rs @@ -373,7 +373,7 @@ pub fn modified_time(path: &str) -> Option { /// Convert a formatted time string to seconds. pub fn time_to_sec(time_str: &str) -> f64 { - if ["now", "", "none"].contains(&time_str) || !time_str.contains(':') { + if matches!(time_str, "now" | "" | "none") || !time_str.contains(':') { return get_sec(); } From 3f222975c16580deeeedaa2e0721e4a312e7c8fb Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Fri, 17 Nov 2023 16:31:27 +0100 Subject: [PATCH 2/9] call system status only when app is not hidden --- ffplayout-frontend | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffplayout-frontend b/ffplayout-frontend index 03200acf..559f4b0d 160000 --- a/ffplayout-frontend +++ b/ffplayout-frontend @@ -1 +1 @@ -Subproject commit 03200acf1b426dc8b64dc702ab907e4184efd667 +Subproject commit 559f4b0d78d2a3364e1968061755fba1a495eb83 From 197a6450f487674171c019dfb51247d7f57aeb3a Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Sat, 18 Nov 2023 22:08:17 +0100 Subject: [PATCH 3/9] remove class --- ffplayout-frontend | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffplayout-frontend b/ffplayout-frontend index 559f4b0d..71aaff16 160000 --- a/ffplayout-frontend +++ b/ffplayout-frontend @@ -1 +1 @@ -Subproject commit 559f4b0d78d2a3364e1968061755fba1a495eb83 +Subproject commit 71aaff1657936fd8372e57e37ee14ae13d165742 From 81e32747897a498b223d7d5f4eb426c600e2d24a Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Sat, 18 Nov 2023 22:31:24 +0100 Subject: [PATCH 4/9] update jwt-decode, fix login --- ffplayout-frontend | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffplayout-frontend b/ffplayout-frontend index 71aaff16..36f0919a 160000 --- a/ffplayout-frontend +++ b/ffplayout-frontend @@ -1 +1 @@ -Subproject commit 71aaff1657936fd8372e57e37ee14ae13d165742 +Subproject commit 36f0919aebc68a57b79c7dbce0e97f4abd115465 From ea83160ba63bb8723de1f004f6449b37a1ea2593 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Mon, 20 Nov 2023 12:30:49 +0100 Subject: [PATCH 5/9] add silence detection for validation --- Cargo.lock | 29 ++++++++------ assets/ffplayout.yml | 3 ++ lib/Cargo.toml | 1 + lib/src/utils/config.rs | 2 + lib/src/utils/errors.rs | 27 +++++++++++++ lib/src/utils/json_validate.rs | 71 +++++++++++++++++++++++----------- lib/src/utils/mod.rs | 1 + 7 files changed, 99 insertions(+), 35 deletions(-) create mode 100644 lib/src/utils/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 6b905d75..f0d00193 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -477,15 +477,15 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" +checksum = "fc5ea910c42e5ab19012bab31f53cb4d63d54c3a27730f9a833a88efcf4bb52d" dependencies = [ - "async-lock 2.8.0", + "async-lock 3.1.1", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 1.13.0", + "futures-lite 2.0.1", "slab", ] @@ -535,9 +535,9 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb2ab2aa8a746e221ab826c73f48bc6ba41be6763f0855cb249eb6d154cf1d7" +checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" dependencies = [ "event-listener 3.1.0", "event-listener-strategy", @@ -689,7 +689,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ "async-channel 2.1.0", - "async-lock 3.1.0", + "async-lock 3.1.1", "async-task", "fastrand 2.0.1", "futures-io", @@ -1273,6 +1273,7 @@ version = "0.20.1" dependencies = [ "chrono", "crossbeam-channel", + "derive_more", "ffprobe", "file-rotate", "lettre", @@ -1464,7 +1465,11 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" dependencies = [ + "fastrand 2.0.1", "futures-core", + "futures-io", + "memchr", + "parking", "pin-project-lite", ] @@ -2711,9 +2716,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.24" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -3346,7 +3351,7 @@ dependencies = [ "cfg-if", "fastrand 2.0.1", "redox_syscall 0.4.1", - "rustix 0.38.24", + "rustix 0.38.25", "windows-sys", ] @@ -3650,9 +3655,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ "getrandom", ] diff --git a/assets/ffplayout.yml b/assets/ffplayout.yml index 7e12c263..b6bcc087 100644 --- a/assets/ffplayout.yml +++ b/assets/ffplayout.yml @@ -35,6 +35,8 @@ logging: false will set log timestamps to UTC. Path to /var/log/ only if you run this program as daemon. 'level' can be DEBUG, INFO, WARNING, ERROR. 'ffmpeg_level' can be info, warning, error. + 'detect_silence' logs an error message if the audio line is silent for 15 + seconds during the validation process. log_to_file: true backup_count: 7 local_time: true @@ -43,6 +45,7 @@ logging: level: DEBUG ffmpeg_level: error ingest_level: warning + detect_silence: false processing: help_text: Default processing for all clips, to have them unique. Mode can be playlist diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 2b76ca5a..79f55660 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -11,6 +11,7 @@ edition.workspace = true [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock", "serde", "std"] } crossbeam-channel = "0.5" +derive_more = "0.99" ffprobe = "0.3" file-rotate = "0.7" lettre = { version = "0.11", features = ["builder", "rustls-tls", "smtp-transport"], default-features = false } diff --git a/lib/src/utils/config.rs b/lib/src/utils/config.rs index 0b2bbbc5..2beb101c 100644 --- a/lib/src/utils/config.rs +++ b/lib/src/utils/config.rs @@ -222,6 +222,8 @@ pub struct Logging { pub level: LevelFilter, pub ffmpeg_level: String, pub ingest_level: Option, + #[serde(default)] + pub detect_silence: bool, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/lib/src/utils/errors.rs b/lib/src/utils/errors.rs new file mode 100644 index 00000000..1f797c51 --- /dev/null +++ b/lib/src/utils/errors.rs @@ -0,0 +1,27 @@ +use std::io; + +use derive_more::Display; + +#[derive(Debug, Display)] +pub enum ProcError { + #[display(fmt = "Failed to spawn ffmpeg/ffprobe. {}", _0)] + CommandSpawn(io::Error), + #[display(fmt = "Failed to read data from ffmpeg/ffprobe. {}", _0)] + IO(io::Error), + #[display(fmt = "{}", _0)] + Custom(String), + #[display(fmt = "Regex compile error {}", _0)] + Regex(String), +} + +impl From for ProcError { + fn from(err: std::io::Error) -> Self { + Self::CommandSpawn(err) + } +} + +impl From for ProcError { + fn from(err: regex::Error) -> Self { + Self::Regex(err.to_string()) + } +} diff --git a/lib/src/utils/json_validate.rs b/lib/src/utils/json_validate.rs index 803a24bd..d48ae943 100644 --- a/lib/src/utils/json_validate.rs +++ b/lib/src/utils/json_validate.rs @@ -1,5 +1,5 @@ use std::{ - io::{BufRead, BufReader, Error, ErrorKind}, + io::{BufRead, BufReader}, process::{Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, @@ -7,11 +7,13 @@ use std::{ }, }; +use regex::Regex; use simplelog::*; +use crate::filter::FilterType::Audio; use crate::utils::{ - loop_image, sec_to_time, seek_and_length, valid_source, vec_strings, JsonPlaylist, Media, - OutputMode::Null, PlayoutConfig, FFMPEG_IGNORE_ERRORS, IMAGE_FORMAT, + errors::ProcError, loop_image, sec_to_time, seek_and_length, valid_source, vec_strings, + JsonPlaylist, Media, OutputMode::Null, PlayoutConfig, FFMPEG_IGNORE_ERRORS, IMAGE_FORMAT, }; /// check if ffmpeg can read the file and apply filter to it. @@ -20,23 +22,26 @@ fn check_media( pos: usize, begin: f64, config: &PlayoutConfig, -) -> Result<(), Error> { - let mut enc_cmd = vec_strings!["-hide_banner", "-nostats", "-v", "level+error"]; +) -> Result<(), ProcError> { + let mut enc_cmd = vec_strings!["-hide_banner", "-nostats", "-v", "level+info"]; let mut error_list = vec![]; let mut config = config.clone(); config.out.mode = Null; + let mut process_length = 0.1; + + if config.logging.detect_silence { + process_length = 15.0; + } + node.add_probe(); if node.probe.clone().and_then(|p| p.format).is_none() { - return Err(Error::new( - ErrorKind::Other, - format!( - "No Metadata at position {pos} {}, from file \"{}\"", - sec_to_time(begin), - node.source - ), - )); + return Err(ProcError::Custom(format!( + "No Metadata at position {pos} {}, from file \"{}\"", + sec_to_time(begin), + node.source + ))); } // take care, that no seek and length command is added. @@ -60,24 +65,30 @@ fn check_media( let mut filter = node.filter.unwrap_or_default(); if filter.cmd().len() > 1 { - filter.cmd()[1] = filter.cmd()[1].replace("realtime=speed=1", "null") + let re_clean = Regex::new(r"volume=[0-9.]+")?; + + filter.audio_chain = re_clean + .replace_all(&filter.audio_chain, "anull") + .to_string(); } + filter.add_filter("silencedetect=n=-30dB", 0, Audio); + enc_cmd.append(&mut node.cmd.unwrap_or_default()); enc_cmd.append(&mut filter.cmd()); enc_cmd.append(&mut filter.map()); - enc_cmd.append(&mut vec_strings!["-t", "0.1", "-f", "null", "-"]); + enc_cmd.append(&mut vec_strings!["-t", process_length, "-f", "null", "-"]); - let mut enc_proc = match Command::new("ffmpeg") - .args(enc_cmd.clone()) + let mut enc_proc = Command::new("ffmpeg") + .args(enc_cmd) .stderr(Stdio::piped()) - .spawn() - { - Err(e) => return Err(e), - Ok(proc) => proc, - }; + .spawn()?; let enc_err = BufReader::new(enc_proc.stderr.take().unwrap()); + let mut silence_start = 0.0; + let mut silence_end = 0.0; + let re_start = Regex::new(r"silence_start: ([0-9]+:)?([0-9.]+)")?; + let re_end = Regex::new(r"silence_end: ([0-9]+:)?([0-9.]+)")?; for line in enc_err.lines() { let line = line?; @@ -91,11 +102,25 @@ fn check_media( error_list.push(log_line); } } + + if config.logging.detect_silence { + if let Some(start) = re_start.captures(&line).and_then(|c| c.get(2)) { + silence_start = start.as_str().parse::().unwrap_or_default(); + } + + if let Some(end) = re_end.captures(&line).and_then(|c| c.get(2)) { + silence_end = end.as_str().parse::().unwrap_or_default() + 0.5; + } + } + } + + if silence_end - silence_start > process_length { + error_list.push("Audio is totally silent!".to_string()); } if !error_list.is_empty() { error!( - "[Validator] ffmpeg error on position {pos} - {}: {}:\n{}", + "[Validator] ffmpeg error on position {pos} - {}: {}: {}", sec_to_time(begin), node.source, error_list.join("\n") diff --git a/lib/src/utils/mod.rs b/lib/src/utils/mod.rs index 17f7c8c0..9c933ad2 100644 --- a/lib/src/utils/mod.rs +++ b/lib/src/utils/mod.rs @@ -23,6 +23,7 @@ use simplelog::*; pub mod config; pub mod controller; +pub mod errors; pub mod folder; pub mod generator; pub mod import; From 85619c0633fddc3c0446b2804b39cf6becfa5ce8 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Tue, 21 Nov 2023 10:39:43 +0100 Subject: [PATCH 6/9] seek in on validation --- ffplayout-engine/src/main.rs | 43 ++++++++++++------------------- ffplayout-engine/src/utils/mod.rs | 26 ++++++------------- lib/src/utils/errors.rs | 20 ++++++++++++++ lib/src/utils/json_validate.rs | 17 +++++++++--- 4 files changed, 59 insertions(+), 47 deletions(-) diff --git a/ffplayout-engine/src/main.rs b/ffplayout-engine/src/main.rs index fcbea1bf..b93eb50b 100644 --- a/ffplayout-engine/src/main.rs +++ b/ffplayout-engine/src/main.rs @@ -19,9 +19,9 @@ use ffplayout::{ }; use ffplayout_lib::utils::{ - folder::fill_filler_list, generate_playlist, get_date, import::import_file, init_logging, - is_remote, send_mail, test_tcp_port, validate_ffmpeg, validate_playlist, JsonPlaylist, - OutputMode::*, PlayerControl, PlayoutStatus, ProcessControl, + errors::ProcError, folder::fill_filler_list, generate_playlist, get_date, import::import_file, + init_logging, is_remote, send_mail, test_tcp_port, validate_ffmpeg, validate_playlist, + JsonPlaylist, OutputMode::*, PlayerControl, PlayoutStatus, ProcessControl, }; #[cfg(debug_assertions)] @@ -44,7 +44,7 @@ struct StatusData { /// we save the time difference, so we stay in sync. /// /// When file not exists we create it, and when it exists we get its values. -fn status_file(stat_file: &str, playout_stat: &PlayoutStatus) { +fn status_file(stat_file: &str, playout_stat: &PlayoutStatus) -> Result<(), ProcError> { debug!("Start ffplayout v{VERSION}, status file path: {stat_file}"); if !PathBuf::from(stat_file).exists() { @@ -53,23 +53,19 @@ fn status_file(stat_file: &str, playout_stat: &PlayoutStatus) { "date": String::new(), }); - let json: String = serde_json::to_string(&data).expect("Serialize status data failed"); + let json: String = serde_json::to_string(&data)?; if let Err(e) = fs::write(stat_file, json) { error!("Unable to write to status file {stat_file}: {e}"); }; } else { - let stat_file = File::options() - .read(true) - .write(false) - .open(stat_file) - .expect("Could not open status file"); - - let data: StatusData = - serde_json::from_reader(stat_file).expect("Could not read status file."); + let stat_file = File::options().read(true).write(false).open(stat_file)?; + let data: StatusData = serde_json::from_reader(stat_file)?; *playout_stat.time_shift.lock().unwrap() = data.time_shift; *playout_stat.date.lock().unwrap() = data.date; } + + Ok(()) } /// Set fake time for debugging. @@ -88,14 +84,14 @@ fn fake_time(args: &Args) { /// Main function. /// Here we check the command line arguments and start the player. /// We also start a JSON RPC server if enabled. -fn main() { +fn main() -> Result<(), ProcError> { let args = get_args(); // use fake time function only in debugging mode #[cfg(debug_assertions)] fake_time(&args); - let mut config = get_config(args.clone()); + let mut config = get_config(args.clone())?; let play_control = PlayerControl::new(); let playout_stat = PlayoutStatus::new(); let proc_control = ProcessControl::new(); @@ -116,7 +112,7 @@ fn main() { } let logging = init_logging(&config, Some(proc_ctl1), Some(messages.clone())); - CombinedLogger::init(logging).unwrap(); + CombinedLogger::init(logging)?; if let Err(e) = validate_ffmpeg(&mut config) { error!("{e}"); @@ -179,16 +175,9 @@ fn main() { let f = File::options() .read(true) .write(false) - .open(&playlist_path) - .expect("Could not open json playlist file."); + .open(&playlist_path)?; - let playlist: JsonPlaylist = match serde_json::from_reader(f) { - Ok(p) => p, - Err(e) => { - error!("{e:?}"); - exit(1) - } - }; + let playlist: JsonPlaylist = serde_json::from_reader(f)?; validate_playlist(playlist, Arc::new(AtomicBool::new(false)), config); @@ -205,7 +194,7 @@ fn main() { thread::spawn(move || run_server(config_clone1, play_ctl1, play_stat, proc_ctl2)); } - status_file(&config.general.stat_file, &playout_stat); + status_file(&config.general.stat_file, &playout_stat)?; debug!( "Use config: {}", @@ -233,4 +222,6 @@ fn main() { } drop(msg); + + Ok(()) } diff --git a/ffplayout-engine/src/utils/mod.rs b/ffplayout-engine/src/utils/mod.rs index beff97ed..5c556319 100644 --- a/ffplayout-engine/src/utils/mod.rs +++ b/ffplayout-engine/src/utils/mod.rs @@ -1,7 +1,6 @@ use std::{ fs::File, path::{Path, PathBuf}, - process::exit, }; use regex::Regex; @@ -15,23 +14,22 @@ pub use arg_parse::Args; use ffplayout_lib::{ filter::Filters, utils::{ - config::Template, get_sec, parse_log_level_filter, sec_to_time, time_to_sec, Media, - OutputMode::*, PlayoutConfig, PlayoutStatus, ProcessMode::*, + config::Template, errors::ProcError, get_sec, parse_log_level_filter, sec_to_time, + time_to_sec, Media, OutputMode::*, PlayoutConfig, PlayoutStatus, ProcessMode::*, }, vec_strings, }; /// Read command line arguments, and override the config with them. -pub fn get_config(args: Args) -> PlayoutConfig { +pub fn get_config(args: Args) -> Result { let cfg_path = match args.channel { Some(c) => { let path = PathBuf::from(format!("/etc/ffplayout/{c}.yml")); if !path.is_file() { - println!( + return Err(ProcError::Custom(format!( "Config file \"{c}\" under \"/etc/ffplayout/\" not found.\n\nCheck arguments!" - ); - exit(1) + ))); } Some(path) @@ -53,17 +51,9 @@ pub fn get_config(args: Args) -> PlayoutConfig { let f = File::options() .read(true) .write(false) - .open(template_file) - .expect("JSON template file"); + .open(template_file)?; - let mut template: Template = match serde_json::from_reader(f) { - Ok(p) => p, - Err(e) => { - error!("Template file not readable! {e}"); - - exit(1) - } - }; + let mut template: Template = serde_json::from_reader(f)?; template.sources.sort_by(|d1, d2| d1.start.cmp(&d2.start)); @@ -135,7 +125,7 @@ pub fn get_config(args: Args) -> PlayoutConfig { config.processing.volume = volume; } - config + Ok(config) } /// Format ingest and HLS logging output diff --git a/lib/src/utils/errors.rs b/lib/src/utils/errors.rs index 1f797c51..21723574 100644 --- a/lib/src/utils/errors.rs +++ b/lib/src/utils/errors.rs @@ -12,6 +12,8 @@ pub enum ProcError { Custom(String), #[display(fmt = "Regex compile error {}", _0)] Regex(String), + #[display(fmt = "Thread error {}", _0)] + Thread(String), } impl From for ProcError { @@ -25,3 +27,21 @@ impl From for ProcError { Self::Regex(err.to_string()) } } + +impl From for ProcError { + fn from(err: log::SetLoggerError) -> Self { + Self::Custom(err.to_string()) + } +} + +impl From for ProcError { + fn from(err: serde_json::Error) -> Self { + Self::Custom(err.to_string()) + } +} + +impl From> for ProcError { + fn from(err: Box) -> Self { + Self::Thread(format!("{err:?}")) + } +} diff --git a/lib/src/utils/json_validate.rs b/lib/src/utils/json_validate.rs index d48ae943..a2889066 100644 --- a/lib/src/utils/json_validate.rs +++ b/lib/src/utils/json_validate.rs @@ -5,6 +5,7 @@ use std::{ atomic::{AtomicBool, Ordering}, Arc, }, + time::Instant, }; use regex::Regex; @@ -16,7 +17,12 @@ use crate::utils::{ JsonPlaylist, Media, OutputMode::Null, PlayoutConfig, FFMPEG_IGNORE_ERRORS, IMAGE_FORMAT, }; -/// check if ffmpeg can read the file and apply filter to it. +/// Validate a single media file. +/// +/// - Check if file exists +/// - Check if ffmpeg can read the file +/// - Check if Metadata exists +/// - Check if the file is not silent fn check_media( mut node: Media, pos: usize, @@ -32,6 +38,10 @@ fn check_media( if config.logging.detect_silence { process_length = 15.0; + let seek = node.duration / 4.0; + + // Seek in file, to prevent false silence detection on intros without sound. + enc_cmd.append(&mut vec_strings!["-ss", seek]); } node.add_probe(); @@ -44,7 +54,7 @@ fn check_media( ))); } - // take care, that no seek and length command is added. + // Take care, that no seek and length command is added. node.seek = 0.0; node.out = node.duration; @@ -161,6 +171,7 @@ pub fn validate_playlist( length += begin; debug!("Validate playlist from: {date}"); + let timer = Instant::now(); for (index, item) in playlist.program.iter().enumerate() { if is_terminated.load(Ordering::SeqCst) { @@ -197,5 +208,5 @@ pub fn validate_playlist( ); } - debug!("Validation done..."); + debug!("Validation done, in {:.3?} ...", timer.elapsed(),); } From f86a6c3f1dfb8ec5f3c8e74714b8eecda2b443c3 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Thu, 23 Nov 2023 22:37:51 +0100 Subject: [PATCH 7/9] get all user, delete user --- ffplayout-api/src/api/routes.rs | 71 ++++++++++++++++++++++++++++++++- ffplayout-api/src/db/handles.rs | 21 ++++++++++ ffplayout-api/src/db/models.rs | 1 + ffplayout-api/src/main.rs | 3 ++ 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/ffplayout-api/src/api/routes.rs b/ffplayout-api/src/api/routes.rs index f284ed90..839e1eb3 100644 --- a/ffplayout-api/src/api/routes.rs +++ b/ffplayout-api/src/api/routes.rs @@ -232,6 +232,45 @@ async fn get_user( } } +/// **Get User by ID** +/// +/// ```BASH +/// curl -X GET 'http://127.0.0.1:8787/api/user/2' -H 'Content-Type: application/json' \ +/// -H 'Authorization: Bearer ' +/// ``` +#[get("/user/{name}")] +#[has_any_role("Role::Admin", type = "Role")] +async fn get_user_by_name( + pool: web::Data>, + name: web::Path, +) -> Result { + match handles::select_user(&pool.into_inner(), &name).await { + Ok(user) => Ok(web::Json(user)), + Err(e) => { + error!("{e}"); + Err(ServiceError::InternalServerError) + } + } +} + +// **Get all User** +/// +/// ```BASH +/// curl -X GET 'http://127.0.0.1:8787/api/users' -H 'Content-Type: application/json' \ +/// -H 'Authorization: Bearer ' +/// ``` +#[get("/users")] +#[has_any_role("Role::Admin", type = "Role")] +async fn get_users(pool: web::Data>) -> Result { + match handles::select_users(&pool.into_inner()).await { + Ok(users) => Ok(web::Json(users)), + Err(e) => { + error!("{e}"); + Err(ServiceError::InternalServerError) + } + } +} + /// **Update current User** /// /// ```BASH @@ -245,11 +284,20 @@ async fn update_user( id: web::Path, user: web::ReqData, data: web::Json, + role: AuthDetails, ) -> Result { - if id.into_inner() == user.id { + if id.into_inner() == user.id || role.has_role(&Role::Admin) { let mut fields = String::new(); + if !data.username.is_empty() { + fields.push_str(format!("username = '{}'", data.username).as_str()); + } + if let Some(mail) = data.mail.clone() { + if !fields.is_empty() { + fields.push_str(", "); + } + fields.push_str(format!("mail = '{mail}'").as_str()); } @@ -301,6 +349,27 @@ async fn add_user( } } +// **Delete User** +/// +/// ```BASH +/// curl -X GET 'http://127.0.0.1:8787/api/user/2' -H 'Content-Type: application/json' \ +/// -H 'Authorization: Bearer ' +/// ``` +#[delete("/user/{name}")] +#[has_any_role("Role::Admin", type = "Role")] +async fn remove_user( + pool: web::Data>, + name: web::Path, +) -> Result { + match handles::delete_user(&pool.into_inner(), &name).await { + Ok(_) => return Ok("Delete user success"), + Err(e) => { + error!("{e}"); + Err(ServiceError::InternalServerError) + } + } +} + /// #### ffpapi Settings /// /// **Get Settings from Channel** diff --git a/ffplayout-api/src/db/handles.rs b/ffplayout-api/src/db/handles.rs index 960a5592..04eefbdd 100644 --- a/ffplayout-api/src/db/handles.rs +++ b/ffplayout-api/src/db/handles.rs @@ -228,6 +228,18 @@ pub async fn select_user(conn: &Pool, user: &str) -> Result, id: i32) -> Result { + let query = "SELECT id, mail, username, role_id FROM user WHERE id = $1"; + + sqlx::query_as(query).bind(id).fetch_one(conn).await +} + +pub async fn select_users(conn: &Pool) -> Result, sqlx::Error> { + let query = "SELECT id, username FROM user"; + + sqlx::query_as(query).fetch_all(conn).await +} + pub async fn insert_user( conn: &Pool, user: User, @@ -260,6 +272,15 @@ pub async fn update_user( sqlx::query(&query).bind(id).execute(conn).await } +pub async fn delete_user( + conn: &Pool, + name: &str, +) -> Result { + let query = "DELETE FROM user WHERE username = $1;"; + + sqlx::query(query).bind(name).execute(conn).await +} + pub async fn select_presets(conn: &Pool, id: i32) -> Result, sqlx::Error> { let query = "SELECT * FROM presets WHERE channel_id = $1"; diff --git a/ffplayout-api/src/db/models.rs b/ffplayout-api/src/db/models.rs index 02c428b6..770df0c0 100644 --- a/ffplayout-api/src/db/models.rs +++ b/ffplayout-api/src/db/models.rs @@ -10,6 +10,7 @@ pub struct User { #[serde(skip_deserializing)] pub id: i32, #[sqlx(default)] + #[serde(skip_serializing_if = "Option::is_none")] pub mail: Option, pub username: String, #[sqlx(default)] diff --git a/ffplayout-api/src/main.rs b/ffplayout-api/src/main.rs index f5dacb2b..62d00eba 100644 --- a/ffplayout-api/src/main.rs +++ b/ffplayout-api/src/main.rs @@ -109,6 +109,9 @@ async fn main() -> std::io::Result<()> { .wrap(auth) .service(add_user) .service(get_user) + .service(get_user_by_name) + .service(get_users) + .service(remove_user) .service(get_playout_config) .service(update_playout_config) .service(add_preset) From be2528fbb4f408b43e94dd830353eed8ddc16dee Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Fri, 24 Nov 2023 08:12:42 +0100 Subject: [PATCH 8/9] fix update id, don't update user name --- ffplayout-api/src/api/routes.rs | 8 ++------ ffplayout-frontend | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/ffplayout-api/src/api/routes.rs b/ffplayout-api/src/api/routes.rs index 839e1eb3..3faea450 100644 --- a/ffplayout-api/src/api/routes.rs +++ b/ffplayout-api/src/api/routes.rs @@ -286,13 +286,9 @@ async fn update_user( data: web::Json, role: AuthDetails, ) -> Result { - if id.into_inner() == user.id || role.has_role(&Role::Admin) { + if *id == user.id || role.has_role(&Role::Admin) { let mut fields = String::new(); - if !data.username.is_empty() { - fields.push_str(format!("username = '{}'", data.username).as_str()); - } - if let Some(mail) = data.mail.clone() { if !fields.is_empty() { fields.push_str(", "); @@ -314,7 +310,7 @@ async fn update_user( fields.push_str(format!("password = '{password_hash}', salt = '{salt}'").as_str()); } - if handles::update_user(&pool.into_inner(), user.id, fields) + if handles::update_user(&pool.into_inner(), *id, fields) .await .is_ok() { diff --git a/ffplayout-frontend b/ffplayout-frontend index 36f0919a..e060cbe8 160000 --- a/ffplayout-frontend +++ b/ffplayout-frontend @@ -1 +1 @@ -Subproject commit 36f0919aebc68a57b79c7dbce0e97f4abd115465 +Subproject commit e060cbe885a961f295fb4f6f12bc2c86b5f94192 From 104f0556ce9e1bfb445355716b7f55c9d39336d5 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Fri, 24 Nov 2023 08:13:44 +0100 Subject: [PATCH 9/9] update doc --- docs/api.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/api.md b/docs/api.md index eebf346a..6ea9b27c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -38,6 +38,19 @@ curl -X GET 'http://127.0.0.1:8787/api/user' -H 'Content-Type: application/json' -H 'Authorization: Bearer ' ``` +**Get User by ID** + +```BASH +curl -X GET 'http://127.0.0.1:8787/api/user/2' -H 'Content-Type: application/json' \ +-H 'Authorization: Bearer ' +``` + + +```BASH +curl -X GET 'http://127.0.0.1:8787/api/users' -H 'Content-Type: application/json' \ +-H 'Authorization: Bearer ' +``` + **Update current User** ```BASH @@ -53,6 +66,12 @@ curl -X POST 'http://127.0.0.1:8787/api/user/' -H 'Content-Type: application/jso -H 'Authorization: Bearer ' ``` + +```BASH +curl -X GET 'http://127.0.0.1:8787/api/user/2' -H 'Content-Type: application/json' \ +-H 'Authorization: Bearer ' +``` + #### ffpapi Settings **Get Settings from Channel**