From 29f1ca8dee48ed09d40d8f263edb54708ae3fb6d Mon Sep 17 00:00:00 2001 From: JP Stringham Date: Sat, 7 Mar 2026 07:45:15 -0500 Subject: [PATCH] pushin more endpoints and stuff in --- src/app.rs | 28 +++++++++- src/app/admin.rs | 1 - src/app/admin/upstream_oauth_links.rs | 72 +++++++++++++++++++++++++ src/app/admin/user_reg_tokens.rs | 78 +++++++++++++++++++++++++-- src/main.rs | 54 +++++++++++++++---- src/mas_admin_rs_settings.json | 24 +++++++++ 6 files changed, 240 insertions(+), 17 deletions(-) create mode 100644 src/app/admin/upstream_oauth_links.rs create mode 100644 src/mas_admin_rs_settings.json diff --git a/src/app.rs b/src/app.rs index 9fcb48e..7ac0ca6 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,9 +1,15 @@ pub mod admin; pub mod setup; +use std::io::Write; + +use serde::{Deserialize, Serialize}; + use crate::json_types::*; -#[derive(Debug)] +const SAVE_PATH: &str = "mas_admin_rs_settings.json"; + +#[derive(Debug, Serialize, Deserialize)] pub struct App { matrix_base_url: String, mas_base_url: String, @@ -23,6 +29,18 @@ impl App { } } + pub fn try_load_from_file() -> Result { + let Ok(f) = std::fs::read_to_string(SAVE_PATH) else { + println!("Couldn't open save"); + return Err(()); + }; + + match serde_json::from_str::(&f) { + Ok(app) => Ok(app), + Err(_) => Err(()), + } + } + pub fn admin_api_ready(&self) -> bool { self.auth_metadata.is_some() && self.client_registration.is_some() @@ -45,4 +63,12 @@ impl App { crate::quick_format_bool(self.admin_api_ready()) ); } + + pub fn save_to_file(&self) { + let mut f = std::fs::File::create(SAVE_PATH).unwrap(); + + let json = serde_json::to_string_pretty::(&self).unwrap(); + + f.write(json.as_bytes()).unwrap(); + } } diff --git a/src/app/admin.rs b/src/app/admin.rs index 29d283e..20ef70c 100644 --- a/src/app/admin.rs +++ b/src/app/admin.rs @@ -1,7 +1,6 @@ pub mod server; pub mod user_reg_tokens; -const USERS_ENDPT: &str = "/api/admin/v1/users"; const OAUTH_LINKS_ENDPT: &str = "/api/admin/v1/upstream-oauth-links"; use crate::json_types::*; diff --git a/src/app/admin/upstream_oauth_links.rs b/src/app/admin/upstream_oauth_links.rs new file mode 100644 index 0000000..be95f45 --- /dev/null +++ b/src/app/admin/upstream_oauth_links.rs @@ -0,0 +1,72 @@ +const USER_REG_TOKENS_ENDPT: &str = "/api/admin/v1/user-registration-tokens"; + +use clap::Subcommand; + +use crate::json_types::prettify_json_str; + +use super::super::App; + +impl App { + pub fn list_user_reg_tokens(&self) { + let auth_token = self + .auth_token + .as_ref() + .expect("Need auth token to perform this action"); + + let url = format!("{}{USER_REG_TOKENS_ENDPT}", self.mas_base_url); + + let client = reqwest::blocking::Client::new(); + + let req = client + .get(url) + .header("Accept", "application/json") + .header( + "Authorization", + format!("Bearer {}", auth_token.access_token.clone()), + ) + .header("Content-Type", "application/json"); + + // println!("Req {:?}", req); + + let res = req.send().unwrap(); + + let json = prettify_json_str(res.text().unwrap().as_str()).unwrap(); + println!("{}", json); + } + + pub fn create_user_reg_token(&self, token: Option, usage_limit: Option) { + let auth_token = self + .auth_token + .as_ref() + .expect("Need auth token to perform this action"); + + let json = serde_json::to_string_pretty(&(token, usage_limit)).unwrap(); + + let url = format!("{}{USER_REG_TOKENS_ENDPT}", self.mas_base_url); + + let client = reqwest::blocking::Client::new(); + + let req = client + .post(url) + .header("Accept", "application/json") + .header( + "Authorization", + format!("Bearer {}", auth_token.access_token.clone()), + ) + .header("Content-Type", "application/json") + .body(json); + + // println!("Req {:?}", req); + + let res = req.send().unwrap(); + + let json = prettify_json_str(res.text().unwrap().as_str()).unwrap(); + println!("{}", json); + } +} + +#[derive(Debug, Subcommand, PartialEq, Eq)] +pub enum UpstreamOauthLinksCommands { + List, + Add, +} diff --git a/src/app/admin/user_reg_tokens.rs b/src/app/admin/user_reg_tokens.rs index 901dde5..b9a8f40 100644 --- a/src/app/admin/user_reg_tokens.rs +++ b/src/app/admin/user_reg_tokens.rs @@ -1,6 +1,7 @@ const USER_REG_TOKENS_ENDPT: &str = "/api/admin/v1/user-registration-tokens"; use clap::Subcommand; +use serde::{Deserialize, Serialize}; use crate::json_types::prettify_json_str; @@ -34,12 +35,17 @@ impl App { println!("{}", json); } - pub fn create_user_reg_token(&self) { + pub fn create_user_reg_token(&self, token: Option, usage_limit: Option) { let auth_token = self .auth_token .as_ref() .expect("Need auth token to perform this action"); + let value = CreateRequest { token, usage_limit }; + let json = serde_json::to_string_pretty(&value).unwrap(); + + println!("{json}"); + let url = format!("{}{USER_REG_TOKENS_ENDPT}", self.mas_base_url); let client = reqwest::blocking::Client::new(); @@ -52,19 +58,81 @@ impl App { format!("Bearer {}", auth_token.access_token.clone()), ) .header("Content-Type", "application/json") - .body("{}"); + .body(json); // println!("Req {:?}", req); let res = req.send().unwrap(); - let json = prettify_json_str(res.text().unwrap().as_str()).unwrap(); - println!("{}", json); + if res.status().is_success() { + let json = prettify_json_str(res.text().unwrap().as_str()).unwrap(); + println!("{}", json); + } else { + println!("Err: {:?}", res.text().unwrap()); + } + } + pub fn update_user_reg_token(&self, id: String, usage_limit: u32) { + let auth_token = self + .auth_token + .as_ref() + .expect("Need auth token to perform this action"); + + let value = UpdateRequest { usage_limit }; + let json = serde_json::to_string_pretty(&value).unwrap(); + + println!("{json}"); + + let url = format!("{}{USER_REG_TOKENS_ENDPT}/{id}", self.mas_base_url); + + let client = reqwest::blocking::Client::new(); + + let req = client + .put(url) + .header("Accept", "application/json") + .header( + "Authorization", + format!("Bearer {}", auth_token.access_token.clone()), + ) + .header("Content-Type", "application/json") + .body(json); + + // println!("Req {:?}", req); + + let res = req.send().unwrap(); + + if res.status().is_success() { + let json = prettify_json_str(res.text().unwrap().as_str()).unwrap(); + println!("{}", json); + } else { + println!("Err: {:?}", res.text().unwrap()); + } } } #[derive(Debug, Subcommand, PartialEq, Eq)] pub enum UserRegTokensCommands { List, - Create, + Create { + #[arg(long, short)] + token: Option, + #[arg(long, short)] + usage_limit: Option, + }, + Update { + id: String, + usage_limit: u32, + }, +} + +#[derive(Debug, Serialize, Deserialize)] +struct CreateRequest { + #[serde(skip_serializing_if = "Option::is_none")] + token: Option, + #[serde(skip_serializing_if = "Option::is_none")] + usage_limit: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +struct UpdateRequest { + usage_limit: u32, } diff --git a/src/main.rs b/src/main.rs index 6d7f002..77e89ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,9 +9,6 @@ mod app; pub mod json_types; - -use std::io::Write; - use clap::{CommandFactory, Parser, Subcommand}; use colored::{ColoredString, Colorize}; use rustyline::{DefaultEditor, error::ReadlineError}; @@ -28,8 +25,6 @@ use crate::app::{ const MATRIX_SERVER_BASE_URL: &str = "https://matrix.supersaturn.space"; const MAS_SERVER_BASE_URL: &str = "https://mas.supersaturn.space"; -const CLIENT_SECRET: &str = "asdjfja2392ijf23923ndflkas01812j312k3j_18127"; - fn main() { //curl --header "Authorization: Bearer syt_anA_YRbjQUlvKVDuAfIDIdPW_0k2VVC" -X GET http://127.0.0.1:8008/_synapse/admin/v2/users/@jp:matrix.supersaturn.space // let access_token = "Bearer mat_zA80YL1OafucuRGgdZSPIILCSquto2_nT9b73"; @@ -37,9 +32,21 @@ fn main() { println!("{}", "Welcome to auth tools CLI".bright_cyan()); println!("{} {MATRIX_SERVER_BASE_URL}\n\n", "Homeserver:".green()); - let mut app = App::new(MATRIX_SERVER_BASE_URL, MAS_SERVER_BASE_URL); - app.get_auth_metadata(); - app.register_client(); + let mut app = match App::try_load_from_file() { + Ok(a) => { + println!("Loaded existing app."); + a + } + Err(_) => { + println!("No saved settings found, loading."); + let mut a = App::new(MATRIX_SERVER_BASE_URL, MAS_SERVER_BASE_URL); + + a.get_auth_metadata(); + a.register_client(); + + a + } + }; app.print_status(); @@ -88,6 +95,23 @@ fn main() { continue; } + Commands::Save => { + app.save_to_file(); + continue; + } + Commands::Load => { + app = match App::try_load_from_file() { + Ok(a) => a, + Err(_) => { + println!("Could not load settings from file."); + continue; + } + } + } + Commands::Quit => { + println!("Goodbye."); + break; + } _ => { if !app.admin_api_ready() { println!( @@ -100,14 +124,21 @@ fn main() { } match cli.command { - Commands::Setup(_) => unreachable!("Blocked by above match"), + Commands::Setup(_) | Commands::Load | Commands::Save | Commands::Quit => { + unreachable!("Blocked by above match") + } Commands::Server(sub) => match sub.command { ServerCommands::ShowSiteConfig => app.show_site_config(), ServerCommands::ShowVersion => app.show_version(), }, Commands::UserRegistrationTokens(sub) => match sub.command { UserRegTokensCommands::List => app.list_user_reg_tokens(), - UserRegTokensCommands::Create => app.create_user_reg_token(), + UserRegTokensCommands::Create { token, usage_limit } => { + app.create_user_reg_token(token, usage_limit); + } + UserRegTokensCommands::Update { id, usage_limit } => { + app.update_user_reg_token(id, usage_limit); + } }, Commands::ShowOauthLinks => app.show_oauth_links(), } @@ -144,6 +175,9 @@ enum Commands { #[command(arg_required_else_help = true)] UserRegistrationTokens(UserRegTokensArgs), ShowOauthLinks, + Save, + Load, + Quit, } #[derive(Debug, Parser)] diff --git a/src/mas_admin_rs_settings.json b/src/mas_admin_rs_settings.json new file mode 100644 index 0000000..030ac99 --- /dev/null +++ b/src/mas_admin_rs_settings.json @@ -0,0 +1,24 @@ +{ + "matrix_base_url": "https://matrix.supersaturn.space", + "mas_base_url": "https://mas.supersaturn.space", + "auth_metadata": { + "device_authorization_endpoint": "https://mas.supersaturn.space/oauth2/device", + "token_endpoint": "https://mas.supersaturn.space/oauth2/token", + "registration_endpoint": "https://mas.supersaturn.space/oauth2/registration" + }, + "client_registration": { + "client_id": "01KK1Z6GHZSNB4V1BPDQVYP696", + "client_id_issued_at": 1772814025, + "grant_types": [ + "refresh_token", + "urn:ietf:params:oauth:grant-type:device_code" + ] + }, + "auth_token": { + "token_type": "Bearer", + "access_token": "mat_FEHVueqxGCnuVRwBD0mPKpP9xcMuvo_gKwmE3", + "refresh_token": "mar_tHwdr8Lr1SoQlmwM6r8uqVvt8WbUYN_EmYTG4", + "expires_in": 300, + "scope": "urn:mas:admin urn:matrix:client:api:* urn:synapse:admin:*" + } +} \ No newline at end of file