gt/src/request.rs

128 lines
4.2 KiB
Rust

use std::{collections::HashMap, process};
use clap::ArgMatches;
use reqwest::blocking::Client;
use crate::config::Configuration;
pub enum AuthenticationType {
BasicAuth,
ApiToken,
None,
}
pub struct Request<'a> {
pub client: Client,
pub arg_value: ArgMatches<'a>,
pub map: HashMap<String, String>,
pub url: Option<String>,
pub authentication: Authentication,
}
pub struct Authentication {
pub basic: bool,
pub api_token: bool,
pub credentials: (Option<String>, Option<String>),
pub auth_type: AuthenticationType,
}
impl<'a> Request<'a> {
/// Public constructor for a request with a simple username and password
pub fn with_basic_request(
config: Configuration,
arg: ArgMatches,
auth: Authentication,
) -> Request {
Request {
client: Client::new(),
arg_value: arg,
map: HashMap::new(),
url: Some(format!("{}{}", config.base_url, config.base_api)),
authentication: auth,
}
}
/// Public constructor for a request with an API token
pub fn with_api_request(
config: Configuration,
arg: ArgMatches,
auth: Authentication,
) -> Request {
Request {
client: Client::new(),
arg_value: arg,
map: HashMap::new(),
url: Some(format!("{}{}", config.base_url, config.base_api)),
authentication: auth,
}
}
}
impl Authentication {
/// Public constructor for getting authentication, provided by the configuration
/// file. The most secure methods are checked first, filtering down to the least
/// secure methods. Currently, only two methods are supported: API token, and
/// username/password combo.
pub fn new(config: &Configuration) -> Authentication {
// TODO: might be broken, haven't tested
// this is horror code, I know it
// match the damn thing
// someone is going to take this and put it in r/badcode lol
let basic_auth = config.password.as_ref().unwrap().to_string();
let api_auth = config.api_token.as_ref().unwrap().to_string();
if api_auth.is_empty() {
if !(basic_auth.is_empty()) {
Authentication::with_basic(
config.username.as_ref().unwrap().to_string(),
basic_auth,
)
} else {
println!("Must have some form of authentication! Exiting...");
process::exit(3)
}
} else {
Authentication::with_api_token(config.username.as_ref().unwrap().to_string(), api_auth)
}
}
/// Private constructor once the public constructor figures out what kind of authentication
/// is being used. This constructor uses the username/password combo, a less secure of
/// authenticating that the API token.
fn with_basic(user: String, pass: String) -> Authentication {
Authentication {
basic: true,
api_token: false,
credentials: (Some(user), Some(pass)),
auth_type: AuthenticationType::BasicAuth,
}
}
/// Private constructor once the public constructor figures out what kind of authentication
/// is being used. This constructor uses the API token, a more secure way of authenticating
/// instead of using the basic username and password.
fn with_api_token(user: String, api_token: String) -> Authentication {
Authentication {
basic: false,
api_token: true,
credentials: (Some(user), Some(api_token)),
auth_type: AuthenticationType::ApiToken,
}
}
/// Public method that based on the what kind of authentication is being used, it can
/// determine what kind of requesting method is going to be used. See the Request
/// structure for more details.
pub fn request_chooser(self, config: Configuration, arg: ArgMatches<'static>) -> Request {
if let true = self.api_token {
Request::with_api_request(config, arg.to_owned(), self)
} else {
match self.basic {
true => Request::with_basic_request(config, arg.to_owned(), self),
false => panic!(),
}
}
}
}