Compare commits

...

2 Commits

Author SHA1 Message Date
921e410c9b Fix DB mapping
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-28 20:06:40 +00:00
1da463facd Added basic log-retrieval for the CLI 2023-04-28 19:08:26 +00:00
4 changed files with 867 additions and 532 deletions

View File

@ -4,7 +4,7 @@
#[macro_use] extern crate rocket_contrib; #[macro_use] extern crate rocket_contrib;
use std::{env, str, fs::{self, File}, time::{SystemTime, UNIX_EPOCH}, io::Write, collections::HashSet}; use std::{env, str, fs::{self, File}, time::{SystemTime, UNIX_EPOCH}, io::Write, collections::HashSet};
use rocket::{self, routes, get, post, put, config::{Config, Limits}, response::Responder, request::{self, Request, FromRequest}, Outcome, http::Status}; use rocket::{self, routes, get, post, put, catch, config::{Config, Limits}, response::Responder, request::{self, Request, FromRequest}, Outcome, http::Status};
use rocket_contrib::json::{Json, JsonValue}; use rocket_contrib::json::{Json, JsonValue};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use jsonwebtoken::{self, encode, decode, Header, Validation, EncodingKey, DecodingKey, Algorithm}; use jsonwebtoken::{self, encode, decode, Header, Validation, EncodingKey, DecodingKey, Algorithm};
@ -14,7 +14,7 @@ use tar::Archive;
use base64::{Engine as _, engine::general_purpose}; use base64::{Engine as _, engine::general_purpose};
use uuid::Uuid; use uuid::Uuid;
const DB_FILE: &str = "db.db3";///usr/local/var/capsules_db/db.db3"; const DB_FILE: &str = "/usr/local/var/capsules_db/db.db3";
const CAPSULE_DIR: &str = "/usr/local/var/capsules"; const CAPSULE_DIR: &str = "/usr/local/var/capsules";
const TMP_FILE: &str = "/tmp/capsulearchive.tar.gz"; // TODO: use tempfile https://docs.rs/tempfile/3.2.0/tempfile/index.html const TMP_FILE: &str = "/tmp/capsulearchive.tar.gz"; // TODO: use tempfile https://docs.rs/tempfile/3.2.0/tempfile/index.html
const BLOCKLIST: [&str; 9] = ["gemini", "capsule", "root", "webmaster", "admin", "www", "mail", "email", "api"]; const BLOCKLIST: [&str; 9] = ["gemini", "capsule", "root", "webmaster", "admin", "www", "mail", "email", "api"];
@ -104,6 +104,11 @@ enum Resp {
NotFound(JsonValue), NotFound(JsonValue),
} }
#[catch(400)]
fn bad_request(_: &Request) -> Resp {
return Resp::BadRequest(json!({"message": "There was a problem with your request"}));
}
#[get("/")] #[get("/")]
fn index() -> Resp { fn index() -> Resp {
return Resp::NotFound(json!({"message": "There is no resource available at this path."})); return Resp::NotFound(json!({"message": "There is no resource available at this path."}));

1316
cli/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -17,3 +17,5 @@ reqwest = { version = "0.11", features = ["json", "blocking"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
serde_yaml = "0.8" serde_yaml = "0.8"
chrono = "0.4.24"
prettytable = "0.10.0"

View File

@ -5,6 +5,8 @@ use clap::{Arg, App, SubCommand};
use flate2::{Compression, write::GzEncoder}; use flate2::{Compression, write::GzEncoder};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use tempfile::tempdir; use tempfile::tempdir;
use chrono::prelude::*;
use prettytable::{Table, row};
use dirs; use dirs;
use base64; use base64;
use reqwest; use reqwest;
@ -205,6 +207,59 @@ fn create_capsule() -> Result<bool>{
} }
} }
#[derive(Deserialize, Debug)]
struct LogsResponse {
logs: Option<Vec<Log>>,
message: Option<String>,
}
#[derive(Deserialize, Debug)]
struct Log {
path: String,
timestamp: i64,
}
impl Log {
fn time(&self) -> String {
let naive = NaiveDateTime::from_timestamp_opt(self.timestamp, 0).unwrap();
let datetime: DateTime<Utc> = DateTime::from_utc(naive, Utc);
let newdate = format!("{}", datetime.format("%Y-%m-%d %H:%M:%S"));
return newdate;
}
}
// PUTs the base64-encoded capsule tarball to the server.
fn capsule_logs(flag_capsule_name: Option<&str>) -> Result<bool>{
let capsule_name: String = match flag_capsule_name {
Some(x) => String::from(x),
None => prompt_for("Which capsule do you want to view logs for?"),
};
let capsule_config = read_config_capsule(&capsule_name).expect("The configuration for your specified capsule could not be found.");
let client = reqwest::blocking::Client::new();
let res = client.get(&format!("{}/logs", get_api_url()))
.header("api-key", &capsule_config.access_token).send()?;
let status = res.status();
let response_data = res.json::<LogsResponse>()?;
if status.is_success() {
match response_data.logs {
None => println!("No logs found"),
Some(logs) => {
let mut table = Table::new();
table.add_row(row!["TIME", "CAPSULE", "PATH"]);
for log in logs {
table.add_row(row![log.time(), capsule_name, log.path]);
}
table.printstd();
},
}
return Ok(true);
} else {
let error_message = match response_data.message {
None => String::from("Unknown error"),
Some(message) => message,
};
println!("Unable to get the logs for your capsule: {}", &error_message);
return Err(Box::from("Unable to get logs"));
}
}
fn main() { fn main() {
// Setup config // Setup config
@ -214,7 +269,7 @@ fn main() {
// Read command-line commands/args // Read command-line commands/args
let app_args = App::new("Capsule.Town") let app_args = App::new("Capsule.Town")
.version("0.1") .version("0.2")
.author("Will W. (wilw.dev)") .author("Will W. (wilw.dev)")
.about("Publishes your capsule to capsule.town") .about("Publishes your capsule to capsule.town")
.subcommand(SubCommand::with_name("create") .subcommand(SubCommand::with_name("create")
@ -225,7 +280,14 @@ fn main() {
.short("c") .short("c")
.long("capsule") .long("capsule")
.takes_value(true) .takes_value(true)
.help("Name of the capsule to be published"))); .help("Name of the capsule to be published")))
.subcommand(SubCommand::with_name("logs")
.about("View access logs for your capsule")
.arg(Arg::with_name("capsule")
.short("c")
.long("capsule")
.takes_value(true)
.help("Name of the capsule to view logs for")));
let matches = app_args.get_matches(); let matches = app_args.get_matches();
// Handle commands // Handle commands
@ -235,8 +297,12 @@ fn main() {
let capsule_name = sub_match.value_of("capsule"); let capsule_name = sub_match.value_of("capsule");
publish_capsule(capsule_name) publish_capsule(capsule_name)
}, },
("logs", Some(sub_match)) => {
let capsule_name = sub_match.value_of("capsule");
capsule_logs(capsule_name)
},
_ => { _ => {
println!("Unknown command. Available commands: create, publish"); println!("Unknown command. Available commands: create, publish, logs");
Err(Box::from("Unable to continue")) Err(Box::from("Unable to continue"))
}, },
} { } {