Migrate to API v3

This commit is contained in:
Andrey Golovizin 2024-03-09 15:58:37 +01:00
parent 4946ec2228
commit 33a60aa4c9
3 changed files with 44 additions and 54 deletions

View file

@ -9,14 +9,20 @@ use crate::keys::Key;
const BASE_URL: &str = "https://api.azirevpn.com";
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct CheckResult {
pub(crate) struct CheckResponse {
pub status: String,
pub data: CheckData,
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct CheckData {
pub connected: bool,
pub ip: String, // XXX
pub location: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct Locations {
pub(crate) struct LocationsResponse {
pub status: String,
pub locations: Vec<Location>,
}
@ -41,46 +47,47 @@ impl Location {
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct Addresses {
pub(crate) struct AddressResponse {
pub status: String,
pub ipv4: WireguardConfigIpv4,
pub ipv6: WireguardConfigIpv6,
pub data: AddressData,
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct AddressData {
pub ipv4_address: Ipv4Addr,
pub ipv4_netmask: u8,
pub ipv6_address: Ipv6Addr,
pub ipv6_netmask: u8,
pub dns: Vec<IpAddr>,
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct WireguardConfigIpv4 {
pub address: Ipv4Addr,
pub netmask: u8,
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct WireguardConfigIpv6 {
pub address: Ipv6Addr,
pub netmask: u8,
pub(crate) struct AddIpRequest<'a> {
pub key: &'a str,
}
pub(crate) fn check() -> anyhow::Result<CheckResult> {
let url = format!("{}/v1/check", BASE_URL);
let response: CheckResult = ureq::get(&url).call()?.into_json()?;
pub(crate) fn check() -> anyhow::Result<CheckData> {
let url = format!("{}/v3/check", BASE_URL);
let response: CheckResponse = ureq::get(&url).call()?.into_json()?;
debug!("response = {:?}", &response);
Ok(response)
Ok(response.data)
}
pub(crate) fn get_locations() -> anyhow::Result<Locations> {
let url = format!("{}/v2/locations", BASE_URL);
let response: Locations = ureq::get(&url).call()?.into_json()?;
pub(crate) fn get_locations() -> anyhow::Result<Vec<Location>> {
let url = format!("{}/v3/locations", BASE_URL);
let response: LocationsResponse = ureq::get(&url).call()?.into_json()?;
debug!("response = {:?}", &response);
Ok(response)
Ok(response.locations)
}
pub(crate) fn add_ip(username: &str, token: &str, public_key: &Key) -> anyhow::Result<Addresses> {
let url = format!("{}/v2/ip/add", BASE_URL);
let response: Addresses = ureq::post(&url)
.send_form(&[
("username", username),
("token", token),
("key", &public_key.to_base64()),
])?
pub(crate) fn add_ip(token: &str, public_key: &Key) -> anyhow::Result<AddressData> {
let url = format!("{}/v3/ips", BASE_URL);
let authorization = format!("Bearer {token}");
let request = AddIpRequest {
key: &public_key.to_base64(),
};
let response: AddressResponse = ureq::post(&url)
.set("Authorization", &authorization)
.send_json(&request)?
.into_json()?;
debug!("response = {:?}", &response);
Ok(response)
Ok(response.data)
}

View file

@ -43,10 +43,6 @@ impl MachineConfig {
Ok(())
}
pub(crate) fn username(&self) -> anyhow::Result<String> {
Ok(std::fs::read_to_string(self.username_path())?)
}
pub(crate) fn token(&self) -> anyhow::Result<String> {
Ok(std::fs::read_to_string(self.token_path())?)
}
@ -60,11 +56,6 @@ impl MachineConfig {
Key::try_from_base64(key_data.trim_end())
}
pub(crate) fn save_username(&self, username: &str) -> anyhow::Result<()> {
std::fs::write(self.username_path(), username)?;
Ok(())
}
pub(crate) fn save_token(&self, token: &str) -> anyhow::Result<()> {
std::fs::write(self.token_path(), token)?;
Ok(())
@ -80,10 +71,6 @@ impl MachineConfig {
&self.path
}
fn username_path(&self) -> PathBuf {
self.path().join("username")
}
fn token_path(&self) -> PathBuf {
self.path().join("token")
}

View file

@ -31,7 +31,6 @@ struct Opts {
#[derive(Parser, Debug)]
struct LoginOpts {
username: String,
token: String,
}
@ -79,7 +78,6 @@ fn main() -> Result<(), anyhow::Error> {
fn login(opts: &Opts, login_opts: &LoginOpts) -> Result<(), anyhow::Error> {
let machine_config = config::MachineConfig::new(opts.machine.as_ref())?;
machine_config.save_username(&login_opts.username)?;
machine_config.save_token(&login_opts.token)?;
Ok(())
}
@ -109,7 +107,7 @@ fn list_locations(opts: &Opts) -> Result<(), anyhow::Error> {
if opts.json {
println!("{}", serde_json::to_string(&locations)?);
} else {
for (i, location) in locations.locations.iter().enumerate() {
for (i, location) in locations.iter().enumerate() {
if i > 0 {
println!()
};
@ -128,16 +126,14 @@ fn get_config(opts: &Opts, config_opts: &ConfigOpts) -> Result<(), anyhow::Error
let machine_config = MachineConfig::new(opts.machine.as_ref())?;
let locations = api::get_locations()?;
let location = locations
.locations
.iter()
.find(|location| location.name == config_opts.location)
.ok_or_else(|| anyhow::anyhow!("no such location: {}", config_opts.location))?;
debug!("location = {:?}", &location);
let keys = get_keys(&machine_config)?;
debug!("keys = {:?}", &keys);
let username = machine_config.username()?;
let token = machine_config.token()?;
let addresses = api::add_ip(&username, &token, &keys.public_key)?;
let addresses = api::add_ip(&token, &keys.public_key)?;
write_config(
&mut std::io::stdout().lock(),
@ -152,17 +148,17 @@ fn write_config(
output: &mut dyn Write,
config_opts: &ConfigOpts,
location: &api::Location,
config: &api::Addresses,
config: &api::AddressData,
keys: &WireguardKeyPair,
) -> Result<(), anyhow::Error> {
writeln!(output, "[Interface]")?;
writeln!(output, "PrivateKey = {}", &keys.private_key.to_base64())?;
let allowed_addresses = if config_opts.no_ipv6 {
vec![IpAddr::V4(config.ipv4.address)]
vec![IpAddr::V4(config.ipv4_address)]
} else {
vec![
IpAddr::V4(config.ipv4.address),
IpAddr::V6(config.ipv6.address),
IpAddr::V4(config.ipv4_address),
IpAddr::V6(config.ipv6_address),
]
};
write_list(output, "Address = ", allowed_addresses)?;