Move rad-web binary to radicle-httpd package

Signed-off-by: Thomas Scholtes <geigerzaehler@axiom.fm>
This commit is contained in:
Thomas Scholtes
2023-11-22 11:27:11 +01:00
committed by cloudhead
parent d707f0978e
commit cd071f031c
6 changed files with 142 additions and 2 deletions
+4
View File
@@ -37,6 +37,7 @@ tower-http = { version = "0.3.4", default-features = false, features = ["trace",
tracing = { version = "0.1.37", default-features = false, features = ["std", "log"] }
tracing-logfmt = { version = "0.2", optional = true }
tracing-subscriber = { version = "0.3", default-features = false, features = ["std", "ansi", "fmt"] }
ureq = { version = "2.9", default-features = false, features = ["json"] }
[dependencies.radicle]
path = "../radicle"
@@ -45,6 +46,9 @@ version = "0.2.0"
[dependencies.radicle-term]
path = "../radicle-term"
[dependencies.radicle-cli]
path = "../radicle-cli"
[dev-dependencies]
hyper = { version = "0.14.17", default-features = false, features = ["client"] }
pretty_assertions = { version = "1.3.0" }
+2 -2
View File
@@ -122,9 +122,9 @@ async fn session_delete_handler(
#[cfg(test)]
mod routes {
use crate::commands::web::{sign, SessionInfo};
use axum::body::Body;
use axum::http::StatusCode;
use radicle_cli::commands::rad_web::{self, SessionInfo};
use crate::api::auth::{AuthState, Session};
use crate::test::{self, get, post, put};
@@ -154,7 +154,7 @@ mod routes {
// Create request body
let signer = ctx.profile.signer().unwrap();
let signature = rad_web::sign(signer, &session_info).unwrap();
let signature = sign(signer, &session_info).unwrap();
let body = serde_json::to_vec(&super::AuthChallenge {
sig: signature,
pk: session_info.public_key,
+10
View File
@@ -0,0 +1,10 @@
use radicle_cli::terminal as term;
use radicle_httpd::commands::web as rad_web;
fn main() {
term::run_command_args::<rad_web::Options, _>(
rad_web::HELP,
rad_web::run,
std::env::args_os().skip(1).collect(),
)
}
+2
View File
@@ -0,0 +1,2 @@
//! Extra CLI commands relating to HTTPd.
pub mod web;
+123
View File
@@ -0,0 +1,123 @@
use std::ffi::OsString;
use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use radicle::crypto::{PublicKey, Signature, Signer};
use radicle_cli::terminal as term;
use radicle_cli::terminal::args::{Args, Error, Help};
pub const HELP: Help = Help {
name: "web",
description: "Connect web with node",
version: env!("CARGO_PKG_VERSION"),
usage: r#"
Usage
rad web [<option>...]
Options
--backend, -b httpd to bind to
--frontend, -f Web interface to bind to
--verbose, -v Verbose output
--json Output as json
--help Print help
"#,
};
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SessionInfo {
pub session_id: String,
pub public_key: PublicKey,
}
#[derive(Debug)]
pub struct Options {
pub backend: String,
pub frontend: String,
pub json: bool,
pub verbose: bool,
}
impl Args for Options {
fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
use lexopt::prelude::*;
let mut parser = lexopt::Parser::from_args(args);
let mut backend = None;
let mut frontend = None;
let mut json = false;
let mut verbose = false;
while let Some(arg) = parser.next()? {
match arg {
Long("verbose") | Short('v') => verbose = true,
Long("backend") | Short('b') => {
backend = Some(parser.value()?.to_string_lossy().to_string())
}
Long("frontend") | Short('f') => {
frontend = Some(parser.value()?.to_string_lossy().to_string())
}
Long("json") => json = true,
Long("help") | Short('h') => {
return Err(Error::Help.into());
}
_ => {
return Err(anyhow!(arg.unexpected()));
}
}
}
Ok((
Options {
json,
verbose,
backend: backend.unwrap_or(String::from("http://0.0.0.0:8080")),
frontend: frontend.unwrap_or(String::from("https://app.radicle.xyz")),
},
vec![],
))
}
}
pub fn sign(signer: Box<dyn Signer>, session: &SessionInfo) -> Result<Signature, anyhow::Error> {
signer
.try_sign(format!("{}:{}", session.session_id, session.public_key).as_bytes())
.map_err(anyhow::Error::from)
}
pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
let session: SessionInfo = ureq::post(&format!("{}/api/v1/sessions", options.backend))
.call()?
.into_json()?;
let profile = ctx.profile()?;
let signer = profile.signer()?;
let signature = sign(signer, &session)?;
if options.json {
println!(
"{}",
serde_json::json!({
"sessionId": session.session_id,
"publicKey": session.public_key,
"signature": signature,
})
)
} else {
term::blank();
term::info!("Open the following link to authenticate:");
term::info!(
" 👉 {}/session/{}?pk={}&sig={}",
options.frontend,
session.session_id,
session.public_key,
signature,
);
term::blank();
}
Ok(())
}
+1
View File
@@ -1,6 +1,7 @@
#![allow(clippy::type_complexity)]
#![allow(clippy::too_many_arguments)]
#![recursion_limit = "256"]
pub mod commands;
pub mod error;
use std::collections::HashMap;