summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2022-06-28 16:45:16 -0400
committerCara Salter <cara@devcara.com>2022-06-28 16:45:16 -0400
commit06b1533c226627950b57dc7c71a2d9baede85707 (patch)
treee98490f919ed422f95b63d3b1e303a73f215b1a6
parenta764356ba2934c8bc6114d079e687407dba7ccce (diff)
downloadsolarctl-06b1533c226627950b57dc7c71a2d9baede85707.tar.gz
solarctl-06b1533c226627950b57dc7c71a2d9baede85707.zip
auth: Login command and user authentication0.3.0
-rw-r--r--.envrc1
-rw-r--r--Cargo.lock43
-rw-r--r--Cargo.toml9
-rw-r--r--src/main.rs69
4 files changed, 120 insertions, 2 deletions
diff --git a/.envrc b/.envrc
deleted file mode 100644
index 3550a30..0000000
--- a/.envrc
+++ /dev/null
@@ -1 +0,0 @@
-use flake
diff --git a/Cargo.lock b/Cargo.lock
index d9ccd96..fa9359e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -174,6 +174,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
+name = "dirs"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -839,6 +859,17 @@ dependencies = [
]
[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1038,9 +1069,12 @@ dependencies = [
"color-eyre",
"eyre",
"reqwest",
+ "serde",
+ "serde_json",
"solarlib",
"tabular",
"thiserror",
+ "xdg",
]
[[package]]
@@ -1521,3 +1555,12 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [
"winapi",
]
+
+[[package]]
+name = "xdg"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6"
+dependencies = [
+ "dirs",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 29629f2..7cf3e27 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,9 @@ eyre = "0.6"
tabular = "0.2"
+xdg = "2"
+serde_json = "1"
+
[dependencies.solarlib]
git = "https://git.carathe.dev/solard/solarlib"
branch = "master"
@@ -29,3 +32,9 @@ features = [
"blocking",
"json"
]
+
+[dependencies.serde]
+version = "1"
+features = [
+ "derive"
+]
diff --git a/src/main.rs b/src/main.rs
index e629d0d..70fd438 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,15 @@
+use std::fs;
use std::process::Command;
use clap::Parser;
mod errors;
use errors::CliError;
+use reqwest::header;
use tabular::{row, Table};
use reqwest::{blocking::Client, StatusCode};
use solarlib::planet::{Planet, Memory, CpuCount};
use solarlib::star::NewPlanet;
+use serde::{Serialize, Deserialize};
/// Manage solard and homeworld instances
#[derive(Parser)]
@@ -19,6 +22,11 @@ struct Args {
action: Action
}
+#[derive(Serialize, Deserialize)]
+struct ServerConfig {
+ pub token: String
+}
+
#[derive(clap::Subcommand)]
enum Action {
/// List planets on the server
@@ -60,13 +68,33 @@ enum Action {
/// The Sha256 hash of the ship
ship: String
+ },
+
+ /// Goes through the first-time authentication process to create a token that expires after one
+ /// year, storing it in the process.
+ Login {
+ key: String
}
}
fn main() {
color_eyre::install().unwrap();
let args = Args::parse();
- let client = reqwest::blocking::Client::new();
+ let xdg_dirs = xdg::BaseDirectories::with_profile("solarctl", args.server.clone()).unwrap();
+
+ let mut headers = header::HeaderMap::new();
+
+ if let Some(p) = xdg_dirs.find_config_file("config.json") {
+ let c = fs::read_to_string(p).unwrap();
+ if let Ok(cfg) = serde_json::from_str::<ServerConfig>(&c) {
+ headers.insert(header::AUTHORIZATION, header::HeaderValue::from_str(&cfg.token).unwrap());
+ }
+
+ } else {
+ println!("No config file found! You will need to authenticate with the `login` subcommand");
+ }
+
+ let client = reqwest::blocking::ClientBuilder::new().default_headers(headers).build().unwrap();
let root = args.server.clone();
@@ -91,6 +119,9 @@ fn main() {
},
Action::Create { max_mem, max_cpus, disk_size_mb, name, ship } => {
create(root, client, max_mem, max_cpus, disk_size_mb, name, ship).unwrap();
+ },
+ Action::Login { key } => {
+ login(root, client, key);
}
};
}
@@ -233,3 +264,39 @@ fn create(s: String, c: Client, mem: u64, cpus: u64, disk_size: u64, name: Strin
Ok(())
}
+
+fn login(s: String, c: Client, k: String) -> Result<(), CliError> {
+ let url = format!("http://{}/auth/begin?key={}", s, k);
+
+ println!("Obtaining token...");
+ let res = c.post(url).send()?;
+
+ match res.status() {
+ StatusCode::OK => {
+ let token = res.text()?;
+ let xdg_dirs = xdg::BaseDirectories::with_profile("solarctl", s).unwrap();
+
+ if let Some(p) = xdg_dirs.find_config_file("config.json") {
+ let cfg = ServerConfig {
+ token
+ };
+
+ fs::write(p, serde_json::to_string_pretty(&cfg).unwrap()).unwrap();
+
+ } else {
+ let p = xdg_dirs.place_config_file("config.json").unwrap();
+ let cfg = ServerConfig {
+ token
+ };
+
+ fs::write(p, serde_json::to_string_pretty(&cfg).unwrap()).unwrap();
+ }
+
+ },
+ _ => {
+ return Err(CliError::Cli(format!("Could not authenticate: {}", res.text()?)));
+ }
+ };
+
+ Ok(())
+}