Skip to content

Commit

Permalink
Remove tarkov.dev data caching, add oauth token refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
Blightbuster committed Nov 5, 2024
1 parent aa065a9 commit 46b6f8d
Show file tree
Hide file tree
Showing 15 changed files with 1,310 additions and 1,157 deletions.
1,885 changes: 1,211 additions & 674 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions migrations/20241104201856_auth.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DROP TABLE IF EXISTS item_ CASCADE;
DROP TABLE IF EXISTS trader_ CASCADE;
DROP TABLE IF EXISTS price_data_ CASCADE;
DROP TABLE IF EXISTS trader_price_data_ CASCADE;
23 changes: 15 additions & 8 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ pub struct Config {
pub port: u16,
pub database_url: String,
pub auth_key: String,
pub service: bool,
pub oauth_client_id_discord: String,
pub oauth_client_secret_discord: String,
pub oauth_client_token_endpoint_discord: String,
pub env: Environment,
_private: (),
}
Expand All @@ -17,14 +19,18 @@ impl Config {
port: u16,
database_url: impl Into<String>,
auth_key: impl Into<String>,
service: bool,
oauth_client_id_discord: impl Into<String>,
oauth_client_secret_discord: impl Into<String>,
oauth_client_token_endpoint_discord: impl Into<String>,
env: Environment,
) -> ConfigHandle {
Arc::new(Self {
port,
database_url: database_url.into(),
auth_key: auth_key.into(),
service,
oauth_client_id_discord: oauth_client_id_discord.into(),
oauth_client_secret_discord: oauth_client_secret_discord.into(),
oauth_client_token_endpoint_discord: oauth_client_token_endpoint_discord.into(),
env,
_private: (),
})
Expand All @@ -38,11 +44,12 @@ impl Config {
.expect("Invalid value for PORT"),
database_url: env::var("DATABASE_URL").expect("Could not find env DATABASE_URL"),
auth_key: env::var("AUTH_KEY").expect("Could not find env AUTH_KEY"),
service: match env::var("SERVICE").ok().as_deref() {
Some("true") | Some("TRUE") | None => true,
Some("false") | Some("FALSE") => false,
Some(env) => panic!("Invalid value for SERVICE: {}", env),
},
oauth_client_id_discord: env::var("OAUTH_CLIENT_ID_DISCORD")
.expect("Could not find env OAUTH_CLIENT_ID_DISCORD"),
oauth_client_secret_discord: env::var("OAUTH_CLIENT_SECRET_DISCORD")
.expect("Could not find env OAUTH_CLIENT_SECRET_DISCORD"),
oauth_client_token_endpoint_discord: env::var("OAUTH_CLIENT_TOKEN_ENDPOINT_DISCORD")
.expect("Could not find env OAUTH_CLIENT_TOKEN_ENDPOINT_DISCORD"),
env: match env::var("ENVIRONMENT")
.expect("Could not find env ENVIRONMENT")
.as_str()
Expand Down
31 changes: 0 additions & 31 deletions src/fetch/mod.rs

This file was deleted.

40 changes: 0 additions & 40 deletions src/fetch/models.rs

This file was deleted.

23 changes: 3 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@

mod config;
mod db;
mod fetch;
mod server;
mod service;
mod state;
pub mod server;

pub use self::{
config::{Config, ConfigHandle, Environment},
server::models,
};
pub use self::config::{Config, ConfigHandle, Environment};

pub async fn init(
conf: ConfigHandle,
Expand All @@ -37,19 +31,8 @@ pub async fn init(
// Run migrations
run_migrations(&db).await.unwrap();

// Init state
let state = state::State::new();
if let Err(e) = state.update_from_db(&db).await {
log::error!("failed to update from db: {}", e);
}

// Start service
if conf.service {
service::start(state.clone(), db.clone());
}

// Start server
server::init(state, conf, db).await
server::init(conf, db).await
}

pub async fn start(conf: ConfigHandle, addr: impl Into<std::net::IpAddr>) {
Expand Down
52 changes: 32 additions & 20 deletions src/server/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use super::{
models,
util::PercentDecoded,
};
use crate::{db::Db, state::StateHandle};
use crate::{db::Db, ConfigHandle};
use reqwest::StatusCode;
use serde_json::json;
use warp::Reply;

type Result<T> = std::result::Result<T, warp::Rejection>;
Expand Down Expand Up @@ -159,25 +161,35 @@ pub async fn delete_file(file_name: PercentDecoded, db: Db) -> Result<impl Reply
Ok(warp::reply::json(&serde_json::json!({})))
}

#[derive(Debug, serde::Deserialize)]
pub struct GetAllItemsReqQuery {
lang: Option<String>,
}
pub async fn post_oauth_refresh(
conf: ConfigHandle,
data: models::OAuthRefreshData,
) -> Result<impl Reply> {
if data.client_id != conf.oauth_client_id_discord {
return Err(Error::from(StatusCode::BAD_REQUEST).into());
}

let uri = &conf.oauth_client_token_endpoint_discord;
let body = json!({
"grant_type": "refresh_token",
"client_id": conf.oauth_client_id_discord,
"client_secret": conf.oauth_client_secret_discord,
"refresh_token": data.refresh_token,
});

let response = reqwest::Client::new()
.post(uri)
.form(&body)
.send()
.await
.server_error()?;

pub async fn get_all_items(query: GetAllItemsReqQuery, state: StateHandle) -> Result<impl Reply> {
let market_items = state
.get(query.lang.as_deref())
.ok_or(Error::server_error())?;
let data = response
.error_for_status()
.server_error()?
.json::<models::AccessTokenResponse>()
.await
.server_error()?;

Ok(warp::http::Response::builder()
.header(
warp::http::header::CONTENT_TYPE,
warp::http::HeaderValue::from_static("application/json"),
)
.header(
warp::http::header::CONTENT_ENCODING,
warp::http::HeaderValue::from_static("gzip"),
)
.body(market_items)
.unwrap())
Ok(warp::reply::json(&data))
}
3 changes: 1 addition & 2 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ mod util;
pub mod models;

pub async fn init(
state: crate::state::StateHandle,
conf: crate::ConfigHandle,
db: crate::db::Db,
) -> impl warp::Filter<Extract = impl warp::Reply, Error = std::convert::Infallible> + Clone {
use warp::Filter;

routes::routes(&state, &conf, &db)
routes::routes(&conf, &db)
.recover(recover::recover)
.with(warp::log("app"))
}
48 changes: 22 additions & 26 deletions src/server/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,29 @@ pub struct Resource {
pub value: String,
}

#[derive(Debug, Clone, serde::Serialize)]
pub struct Item {
pub id: String,
#[serde(rename = "iconLink")]
pub icon_link: Option<String>,
#[serde(rename = "wikiLink")]
pub wiki_link: Option<String>,
#[serde(rename = "imageLink")]
pub image_link: Option<String>,
#[serde(flatten)]
pub price_data: PriceData,
#[serde(rename = "traderPrices")]
pub trader_prices: Vec<TraderPriceData>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct OAuthRefreshData {
#[serde(rename = "client_id")]
pub client_id: String,

#[derive(Debug, Clone, serde::Serialize)]
pub struct PriceData {
pub timestamp: i64,
#[serde(rename = "basePrice")]
pub base_price: i64,
#[serde(rename = "avg24hPrice")]
pub avg_24h_price: i64,
#[serde(rename = "refresh_token")]
pub refresh_token: String,
}

#[derive(Debug, Clone, serde::Serialize)]
pub struct TraderPriceData {
#[serde(rename = "traderId")]
pub trader_id: String,
pub price: i64,
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct AccessTokenResponse {
#[serde(rename = "access_token")]
pub access_token: String,

#[serde(rename = "token_type")]
pub token_type: String,

#[serde(rename = "expires_in")]
pub expires_in: i32,

#[serde(rename = "refresh_token")]
pub refresh_token: String,

#[serde(rename = "scope")]
pub scope: String,
}
34 changes: 17 additions & 17 deletions src/server/routes.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
use super::{endpoints, middlewares, util::PercentDecoded};
use crate::{db::Db, state::StateHandle, ConfigHandle};
use super::{endpoints, middlewares, models, util::PercentDecoded};
use crate::{db::Db, ConfigHandle};
use warp::{Filter, Rejection, Reply};

pub fn routes(
state: &StateHandle,
conf: &ConfigHandle,
db: &Db,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
index()
.or(resource_editor())
.or(resources(conf, db))
.or(file(conf, db))
.or(items(state))
.or(oauth_refresh(conf))
}

fn index() -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
Expand Down Expand Up @@ -93,26 +92,27 @@ fn file(
warp::path!("file" / ..).and(get_file.or(get_all_files).or(upload_file).or(delete_file))
}

fn items(state: &StateHandle) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path!("all")
.and(warp::get())
.and(warp::query())
.and(with_state(state))
.and_then(endpoints::get_all_items)
}

fn with_state(
state: &StateHandle,
) -> impl Filter<Extract = (StateHandle,), Error = std::convert::Infallible> + Clone {
let state = state.clone();
warp::any().map(move || state.clone())
fn oauth_refresh(
conf: &ConfigHandle,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path!("oauth" / "refresh" / ..)
.and(warp::post())
.and(with_conf(conf.clone()))
.and(warp::body::json())
.and_then(endpoints::post_oauth_refresh)
}

fn with_db(db: &Db) -> impl Filter<Extract = (Db,), Error = std::convert::Infallible> + Clone {
let db = db.clone();
warp::any().map(move || db.clone())
}

fn with_conf(
conf: ConfigHandle,
) -> impl Filter<Extract = (ConfigHandle,), Error = std::convert::Infallible> + Clone {
warp::any().map(move || conf.clone())
}

fn with_auth(conf: &ConfigHandle) -> impl Filter<Extract = (), Error = Rejection> + Clone {
middlewares::authenticate(conf.auth_key.clone())
}
Loading

0 comments on commit 46b6f8d

Please sign in to comment.