From d2900c727d22d1bc8ba9dcbc8e7229a7f5643c43 Mon Sep 17 00:00:00 2001 From: Tiago Dinis Date: Sat, 10 Sep 2022 21:03:51 +0100 Subject: [PATCH 1/2] feat(mods): add `mods add ` command --- Cargo.lock | 71 ++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/commands/mod.rs | 1 + src/commands/mods/add.rs | 20 +++++++++ src/commands/mods/mod.rs | 2 + src/entities/app.rs | 2 + src/entities/mod.rs | 1 + src/entities/moderator.rs | 91 +++++++++++++++++++++++++++++++++++++++ src/main.rs | 23 ++++++++++ 9 files changed, 212 insertions(+) create mode 100644 src/commands/mods/add.rs create mode 100644 src/commands/mods/mod.rs create mode 100644 src/entities/moderator.rs diff --git a/Cargo.lock b/Cargo.lock index 7c8e120..a43de84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,6 +266,40 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "debugid" version = "0.8.0" @@ -330,6 +364,7 @@ dependencies = [ "reqwest", "sentry", "serde", + "serde-enum-str", "spinners", "walkdir", "zip", @@ -593,6 +628,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.3.0" @@ -1090,6 +1131,36 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-attributes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aba2af3c3b9cd6f3a919056dac6005b71fceecc1cdfa65c4df3912f64e07e60" +dependencies = [ + "darling_core", + "serde-rename-rule", + "syn", +] + +[[package]] +name = "serde-enum-str" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a41bf2fc78a58589b9a6948bfc918c9b2dc918732f2ac14eed982ffb876b39" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "serde-attributes", + "syn", +] + +[[package]] +name = "serde-rename-rule" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd2930103714ccef4f1fe5b6a5f2b6fdcfe462a6c802464714bd41e5b5097c33" + [[package]] name = "serde_derive" version = "1.0.144" diff --git a/Cargo.toml b/Cargo.toml index ef3d25c..537d1e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ directories = "4.0.1" reqwest = { version = "0.11.11", features = ["blocking", "json", "multipart", "rustls-tls"], default-features=false } sentry = {version = "0.27.0", default-features = false, features = ["rustls", "reqwest"]} serde = { version = "1.0.144", features = ["derive"] } +serde-enum-str = "0.2.5" spinners = "4.1.0" walkdir = "2.3.2" zip = "0.6.2" diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 7c0cf38..e3cbc22 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,3 +1,4 @@ +pub mod mods; pub mod aboutme; pub mod logs; pub mod stop; diff --git a/src/commands/mods/add.rs b/src/commands/mods/add.rs new file mode 100644 index 0000000..d7030c1 --- /dev/null +++ b/src/commands/mods/add.rs @@ -0,0 +1,20 @@ +use crate::{commands::{expect_token, ask_for_app}, entities::{moderator::{Mod, Feature}, app::App, user::fetch_user}}; +macro_rules! handle_result { + ($v:expr) => { + match $v { + Ok(v) => v, + Err(err) => { + super::err(&err.to_string()); + std::process::exit(1); + } + } + } +} +pub fn add(id: u128) { + let token = expect_token(); + let app_id = handle_result!(ask_for_app(token.clone(), "add a moderator")); + let app = handle_result!(App::fetch(token.clone(), app_id)); + let user = handle_result!(fetch_user(token.clone())); + let moderator = handle_result!(Mod::new(token.clone(), &user, &app, vec![Feature::SeeLogs, Feature::Status])); + super::log(&format!("Permissions {:?} have been given to {}", moderator.get_features(), id)); +} \ No newline at end of file diff --git a/src/commands/mods/mod.rs b/src/commands/mods/mod.rs new file mode 100644 index 0000000..8dd1bf3 --- /dev/null +++ b/src/commands/mods/mod.rs @@ -0,0 +1,2 @@ +pub mod add; +use super::*; \ No newline at end of file diff --git a/src/entities/app.rs b/src/entities/app.rs index f1ae766..a630da3 100644 --- a/src/entities/app.rs +++ b/src/entities/app.rs @@ -147,4 +147,6 @@ impl App { Err(err) => Err(FetchError::FailedToConnect(err)), } } + + } diff --git a/src/entities/mod.rs b/src/entities/mod.rs index 0c81630..51f8798 100644 --- a/src/entities/mod.rs +++ b/src/entities/mod.rs @@ -1,3 +1,4 @@ +pub mod moderator; use std::fmt::Display; pub mod app; diff --git a/src/entities/moderator.rs b/src/entities/moderator.rs new file mode 100644 index 0000000..1d1a59e --- /dev/null +++ b/src/entities/moderator.rs @@ -0,0 +1,91 @@ +use std::fmt::Debug; + +use serde::{Deserialize, Serialize}; +use serde_enum_str::*; + +use super::{user::User, app::App, FetchError}; +#[derive(Deserialize_enum_str, Serialize_enum_str, Clone)] +pub enum Feature { + #[serde(rename = "start_app")] + Start, + #[serde(rename = "stop_app")] + Stop, + #[serde(rename = "restart_app")] + Restart, + #[serde(rename = "logs_app")] + SeeLogs, + #[serde(rename = "commit_app")] + Commit, + #[serde(rename = "status_app")] + Status, + #[serde(rename = "edit_ram")] + SetRam, + #[serde(rename = "backup_app")] + Backup +} +impl Debug for Feature { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str( + match self { + Self::Backup => "backup", + Self::Commit => "commit", + Self::Restart => "restart", + Self::SeeLogs => "logs", + Self::SetRam => "ram", + Self::Start => "start", + Self::Status => "status", + Self::Stop => "stop" + } + ) + } +} +#[derive(Deserialize, Serialize)] +pub struct Mod { + #[serde(rename = "mod_id")] + user_id: u128, + #[serde(rename = "perms")] + features: Vec +} +impl Mod { + pub fn new(token: String, user: &User, app: &App, features: Vec) -> Result { + let moderator = Self { + user_id: user.user_id.parse().unwrap(), + features + }; + moderator.add_to(token, app)?; + Ok(moderator) + } + pub fn get_features(&self) -> Vec { + self.features.clone() + } + pub fn add_to(&self, token: String, app: &App) -> Result<(), FetchError>{ + #[derive(Deserialize)] + struct Response { + status: String, + message: Option + } + let client = reqwest::blocking::Client::new(); + let req = client + .post(crate::api_url!(format!("/app/{}/team", app.id))) + .header("api-token", token) + .json(self); + match req.send() { + Ok(res) => { + match res.json::() { + Err(err) => { + Err(FetchError::FailedWithMessage(err.to_string())) + } + Ok(response) => { + if response.status == "ok" { + Ok(()) + } else { + Err(FetchError::FailedWithMessage(response.message.unwrap())) + } + } + } + + } + Err(err) => Err(FetchError::FailedToConnect(err)), + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 96cd7fa..f7ec989 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,6 +101,19 @@ fn main() -> std::io::Result<()> { Command::new("aboutme") .about("Shows information about you.") .alias("user") + ) + .subcommand( + Command::new("mods") + .about("Manages your apps' mods") + .subcommand_required(true) + .arg_required_else_help(true) + .alias("m") + .subcommand( + Command::new("add") + .about("Adds a mod to an app, by default, the mod can only see the logs and status, use `discloud mods allow` to allow more actions.") + .arg(Arg::new("id").value_parser(value_parser!(u128)).action(clap::ArgAction::Set).required(true)) + ) + .after_help("Be careful with what people you add and what permissions you give: With Great Power comes Great Responsability.") ); let matches = cmd.get_matches(); match matches.subcommand() { @@ -144,6 +157,16 @@ fn main() -> std::io::Result<()> { commands::aboutme::aboutme(); Ok(()) } + Some(("mods", matches)) => { + match matches.subcommand() { + Some(("add", matches)) => { + let id: u128 = *matches.get_one("id").unwrap(); + commands::mods::add::add(id); + Ok(()) + } + _ => unreachable!() + } + } _ => unreachable!(), } } From a654c1f6f2c33799c3baf6deae81ec0aa6a60279 Mon Sep 17 00:00:00 2001 From: Tiago Dinis Date: Sat, 10 Sep 2022 21:24:20 +0100 Subject: [PATCH 2/2] fix: rename user_id to modID in serde In the middle of this I discovered an API bug --- src/entities/moderator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entities/moderator.rs b/src/entities/moderator.rs index 1d1a59e..b85f3d2 100644 --- a/src/entities/moderator.rs +++ b/src/entities/moderator.rs @@ -41,7 +41,7 @@ impl Debug for Feature { } #[derive(Deserialize, Serialize)] pub struct Mod { - #[serde(rename = "mod_id")] + #[serde(rename = "modID")] user_id: u128, #[serde(rename = "perms")] features: Vec