Skip to content

Commit

Permalink
half-finished auth
Browse files Browse the repository at this point in the history
  • Loading branch information
The0x539 committed Jun 8, 2021
1 parent f6bb4c1 commit e34edc5
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 0 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2018"

[dependencies]
chrono = { version = "0.4.19", features = ["serde"] }
directories = "3.0.2"
druid = { version = "0.7.0", features = ["im", "image"] }
futures = "0.3.15"
image = "0.23.14"
Expand Down
2 changes: 2 additions & 0 deletions src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use url::Url;
use crate::error::{HttpErr, ImageErr, JsonErr, Result};
use crate::schema;

pub mod auth;

static RATE_LIMIT: Lazy<RateLimiter> = Lazy::new(|| RateLimiter::new(5, Duration::from_secs(1)));
static CLIENT: Lazy<Client> = Lazy::new(Client::new);

Expand Down
127 changes: 127 additions & 0 deletions src/endpoint/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#![allow(dead_code)]

use chrono::{DateTime, Duration, Utc};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::path::PathBuf;

use super::{CLIENT, RATE_LIMIT};

fn auth_file_location() -> PathBuf {
crate::data_dir().join("auth.json")
}

fn open_or_create_token() -> Token {
let loc = auth_file_location();
if loc.exists() {
let f = File::open(loc).expect("Failed to open auth token file");
serde_json::from_reader(f).expect("Failed to deserialize auth token")
} else {
todo!()
}
}

static TOKEN: Lazy<Token> = Lazy::new(|| todo!());

#[derive(Debug, Deserialize, Serialize)]
struct Token {
session_token: String,
refresh_token: String,
session_expiry: DateTime<Utc>,
refresh_expiry: DateTime<Utc>,
}

#[derive(Debug, Deserialize)]
struct TokenResponse {
session: String,
refresh: String,
}

impl Token {
fn needs_refresh(&self) -> bool {
self.session_expiry - Utc::now() < Duration::seconds(30)
}

fn needs_relogin(&self) -> bool {
self.refresh_expiry - Utc::now() < Duration::zero()
}

async fn refresh(&mut self) -> reqwest::Result<()> {
if !self.needs_refresh() {
return Ok(());
}
if self.needs_relogin() {
*self = Self::login().await?;
return Ok(());
}

#[derive(Serialize)]
struct Refresh<'a> {
token: &'a str,
}
let refresh = Refresh {
token: &self.refresh_token,
};

let permit = RATE_LIMIT.request().await;
let now = Utc::now();
let new_token = CLIENT
.post("https://api.mangadex.org/auth/refresh")
.json(&refresh)
.send()
.await?
.error_for_status()?
.json::<TokenResponse>()
.await?;

self.session_token = new_token.session;
self.refresh_token = new_token.refresh;
self.session_expiry = now + Duration::minutes(15);

drop(permit);

Ok(())
}

async fn login() -> reqwest::Result<Self> {
fn read(prompt: &str) -> String {
println!("{}", prompt);
let mut s = String::new();
std::io::stdin().read_line(&mut s).unwrap();
s
}
let username = read("username:");
let password = read("password:");

#[derive(Serialize)]
struct Login<'a> {
username: &'a str,
password: &'a str,
}
let login = Login {
username: username.trim(),
password: password.trim(),
};

let permit = RATE_LIMIT.request().await;
let now = Utc::now();
let token = CLIENT
.post("https://api.mangadex.org/auth/login")
.json(&login)
.send()
.await?
.error_for_status()?
.json::<TokenResponse>()
.await?;

drop(permit);

Ok(Self {
session_token: token.session,
refresh_token: token.refresh,
session_expiry: now + Duration::minutes(15),
refresh_expiry: now + Duration::days(30),
})
}
}
11 changes: 11 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,19 @@ use snafu::ResultExt;
use tokio::runtime::Runtime;
use tokio::sync::mpsc;

use std::path::PathBuf;

use druid::{AppLauncher, WindowDesc};

fn data_dir() -> PathBuf {
let p_dirs = directories::ProjectDirs::from("", "The0x539", "md-rs")
.expect("Could not determine project directory");

let dir = p_dirs.data_dir();
std::fs::create_dir_all(dir).expect("Failed to ensure existence of project directory");
dir.to_owned()
}

fn main() -> Result<()> {
let (tx, rx) = mpsc::unbounded_channel();

Expand Down

0 comments on commit e34edc5

Please sign in to comment.