Add API tokens support #9
66
virtweb_backend/examples/api_curl.rs
Normal file
66
virtweb_backend/examples/api_curl.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use clap::Parser;
|
||||||
|
use std::os::unix::prelude::CommandExt;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use virtweb_backend::api_tokens::TokenVerb;
|
||||||
|
use virtweb_backend::extractors::api_auth_extractor::TokenClaims;
|
||||||
|
use virtweb_backend::utils::jwt_utils::{sign_jwt, TokenPrivKey};
|
||||||
|
use virtweb_backend::utils::time_utils::time;
|
||||||
|
|
||||||
|
/// curl wrapper to query Virtweb backend API
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
struct Args {
|
||||||
|
/// URL of VirtWeb
|
||||||
|
#[arg(short('u'), long, env, default_value = "http://localhost:8000")]
|
||||||
|
virtweb_url: String,
|
||||||
|
|
||||||
|
/// Token ID
|
||||||
|
#[arg(short('i'), long, env)]
|
||||||
|
token_id: String,
|
||||||
|
|
||||||
|
/// Token private key
|
||||||
|
#[arg(short('t'), long, env)]
|
||||||
|
token_key: String,
|
||||||
|
|
||||||
|
/// Request verb
|
||||||
|
#[arg(short('X'), long, default_value = "GET")]
|
||||||
|
verb: String,
|
||||||
|
|
||||||
|
/// Request URI
|
||||||
|
uri: String,
|
||||||
|
|
||||||
|
/// Command line arguments to pass to cURL
|
||||||
|
#[clap(trailing_var_arg = true, allow_hyphen_values = true)]
|
||||||
|
run: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
|
let full_url = format!("{}{}", args.virtweb_url, args.uri);
|
||||||
|
log::debug!("Full URL: {full_url}");
|
||||||
|
|
||||||
|
let key = TokenPrivKey::ES384 {
|
||||||
|
r#priv: args.token_key,
|
||||||
|
};
|
||||||
|
let claims = TokenClaims {
|
||||||
|
sub: args.token_id.to_string(),
|
||||||
|
iat: time() as usize,
|
||||||
|
exp: time() as usize + 50,
|
||||||
|
verb: TokenVerb::from_str(&args.verb).expect("Invalid request verb!"),
|
||||||
|
path: args.uri,
|
||||||
|
nonce: uuid::Uuid::new_v4().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let jwt = sign_jwt(&key, &claims).expect("Failed to sign JWT!");
|
||||||
|
|
||||||
|
Command::new("curl")
|
||||||
|
.args(["-X", &args.verb])
|
||||||
|
.args(["-H", &format!("x-token-id: {}", args.token_id)])
|
||||||
|
.args(["-H", &format!("x-token-content: {jwt}")])
|
||||||
|
.args(args.run)
|
||||||
|
.arg(full_url)
|
||||||
|
.exec();
|
||||||
|
panic!("Failed to run curl!")
|
||||||
|
}
|
@ -7,6 +7,7 @@ use crate::utils::jwt_utils::{TokenPrivKey, TokenPubKey};
|
|||||||
use crate::utils::time_utils::time;
|
use crate::utils::time_utils::time;
|
||||||
use actix_http::Method;
|
use actix_http::Method;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Copy, Debug)]
|
#[derive(serde::Serialize, serde::Deserialize, Clone, Copy, Debug)]
|
||||||
pub struct TokenID(pub uuid::Uuid);
|
pub struct TokenID(pub uuid::Uuid);
|
||||||
@ -95,6 +96,21 @@ impl TokenVerb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for TokenVerb {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"GET" => Ok(TokenVerb::GET),
|
||||||
|
"POST" => Ok(TokenVerb::POST),
|
||||||
|
"PUT" => Ok(TokenVerb::PUT),
|
||||||
|
"PATCH" => Ok(TokenVerb::PATCH),
|
||||||
|
"DELETE" => Ok(TokenVerb::DELETE),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Structure used to create a token
|
/// Structure used to create a token
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
pub struct NewToken {
|
pub struct NewToken {
|
||||||
|
Loading…
Reference in New Issue
Block a user