add token auth
This commit is contained in:
parent
9e9c48e5dd
commit
21fe567ba6
9 changed files with 152 additions and 13 deletions
1
config.toml
Normal file
1
config.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
allowed_tokens = ["password"]
|
|
@ -8,6 +8,8 @@ services:
|
||||||
- mongodb
|
- mongodb
|
||||||
volumes:
|
volumes:
|
||||||
- ./itemdb/items:/itemdb
|
- ./itemdb/items:/itemdb
|
||||||
|
- ./locations:/locations
|
||||||
|
- ./config.toml:/config.toml
|
||||||
environment:
|
environment:
|
||||||
- "DB_URI=mongodb://user:pass@mongodb:27017"
|
- "DB_URI=mongodb://user:pass@mongodb:27017"
|
||||||
- "DB=cdb"
|
- "DB=cdb"
|
||||||
|
|
23
src/config.rs
Normal file
23
src/config.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
/// Allowed tokens for access
|
||||||
|
pub allowed_tokens: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
allowed_tokens: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_config() -> Config {
|
||||||
|
if let Ok(content) = std::fs::read_to_string("./config.toml") {
|
||||||
|
return toml::from_str(&content).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::default()
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use location::Location;
|
||||||
use rocket::routes as route;
|
use rocket::routes as route;
|
||||||
use rocket::{http::Method, launch};
|
use rocket::{http::Method, launch};
|
||||||
|
|
||||||
|
mod config;
|
||||||
mod db;
|
mod db;
|
||||||
mod item;
|
mod item;
|
||||||
mod json_store;
|
mod json_store;
|
||||||
|
@ -54,6 +55,8 @@ async fn rocket() -> _ {
|
||||||
location.1.clone().add(location.0).await;
|
location.1.clone().add(location.0).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let config = config::get_config();
|
||||||
|
|
||||||
rocket::build()
|
rocket::build()
|
||||||
.mount(
|
.mount(
|
||||||
"/",
|
"/",
|
||||||
|
@ -77,5 +80,6 @@ async fn rocket() -> _ {
|
||||||
)
|
)
|
||||||
.manage(itemdb)
|
.manage(itemdb)
|
||||||
.manage(locations)
|
.manage(locations)
|
||||||
|
.manage(config)
|
||||||
.attach(cors)
|
.attach(cors)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@ use rocket::{get, post, State};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::check_auth;
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::routes::Token;
|
||||||
use crate::variant::Variant;
|
use crate::variant::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::ItemDB,
|
db::ItemDB,
|
||||||
|
@ -20,7 +23,9 @@ pub struct DemandForm {
|
||||||
|
|
||||||
/// Consumes a Transaction with Price and Destination
|
/// Consumes a Transaction with Price and Destination
|
||||||
#[post("/demand", data = "<f>")]
|
#[post("/demand", data = "<f>")]
|
||||||
pub async fn demand_route(f: Json<DemandForm>) -> FallibleApiResponse {
|
pub async fn demand_route(f: Json<DemandForm>, t: Token, c: &State<Config>) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
Variant::demand(
|
Variant::demand(
|
||||||
&f.uuid,
|
&f.uuid,
|
||||||
f.price
|
f.price
|
||||||
|
@ -41,7 +46,11 @@ pub async fn demand_log_route(
|
||||||
item_id: &str,
|
item_id: &str,
|
||||||
variant_id: &str,
|
variant_id: &str,
|
||||||
itemdb: &State<ItemDB>,
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
) -> FallibleApiResponse {
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let variant = itemdb
|
let variant = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?
|
.ok_or_else(item_does_not_exist_error)?
|
||||||
|
|
|
@ -5,16 +5,22 @@ use rocket::{get, State};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
check_auth,
|
||||||
|
config::Config,
|
||||||
json_store::JSONStore,
|
json_store::JSONStore,
|
||||||
location::Location,
|
location::Location,
|
||||||
routes::{api_error, FallibleApiResponse},
|
routes::{api_error, FallibleApiResponse, Token},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[get("/location/<id>")]
|
#[get("/location/<id>")]
|
||||||
pub async fn location_info(
|
pub async fn location_info(
|
||||||
id: &str,
|
id: &str,
|
||||||
locations: &State<JSONStore<Location>>,
|
locations: &State<JSONStore<Location>>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
) -> FallibleApiResponse {
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let loc = locations
|
let loc = locations
|
||||||
.get(id)
|
.get(id)
|
||||||
.ok_or_else(|| api_error("No location with that ID"))?;
|
.ok_or_else(|| api_error("No location with that ID"))?;
|
||||||
|
@ -49,7 +55,13 @@ async fn location_api_resolve(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/locations")]
|
#[get("/locations")]
|
||||||
pub async fn locations_list(locations: &State<JSONStore<Location>>) -> FallibleApiResponse {
|
pub async fn locations_list(
|
||||||
|
locations: &State<JSONStore<Location>>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let mut lst = Vec::with_capacity(locations.len());
|
let mut lst = Vec::with_capacity(locations.len());
|
||||||
|
|
||||||
for id in locations.deref().keys() {
|
for id in locations.deref().keys() {
|
||||||
|
@ -60,7 +72,13 @@ pub async fn locations_list(locations: &State<JSONStore<Location>>) -> FallibleA
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/location_map")]
|
#[get("/location_map")]
|
||||||
pub async fn locations_info(locations: &State<JSONStore<Location>>) -> FallibleApiResponse {
|
pub async fn locations_info(
|
||||||
|
locations: &State<JSONStore<Location>>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let mut root_locations = HashMap::new();
|
let mut root_locations = HashMap::new();
|
||||||
|
|
||||||
for loc in locations.inner().deref() {
|
for loc in locations.inner().deref() {
|
||||||
|
|
|
@ -14,7 +14,10 @@ use rocket::get;
|
||||||
use rocket::State;
|
use rocket::State;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::check_auth;
|
||||||
|
use crate::config::Config;
|
||||||
use crate::db::ItemDB;
|
use crate::db::ItemDB;
|
||||||
|
use crate::routes::Token;
|
||||||
use crate::transaction::Transaction;
|
use crate::transaction::Transaction;
|
||||||
|
|
||||||
use super::api_error;
|
use super::api_error;
|
||||||
|
@ -22,14 +25,23 @@ use crate::routes::FallibleApiResponse;
|
||||||
|
|
||||||
/// Returns a JSON response with all items in the database.
|
/// Returns a JSON response with all items in the database.
|
||||||
#[get("/items")]
|
#[get("/items")]
|
||||||
pub fn get_items_route(itemdb: &State<ItemDB>) -> serde_json::Value {
|
pub fn get_items_route(itemdb: &State<ItemDB>, t: Token, c: &State<Config>) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let items = itemdb.items();
|
let items = itemdb.items();
|
||||||
json!({"items": items})
|
Ok(json!({"items": items}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an API Response for an `Item`
|
/// Return an API Response for an `Item`
|
||||||
#[get("/item/<item_id>")]
|
#[get("/item/<item_id>")]
|
||||||
pub fn item_route(item_id: &str, itemdb: &State<ItemDB>) -> FallibleApiResponse {
|
pub fn item_route(
|
||||||
|
item_id: &str,
|
||||||
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let item = itemdb
|
let item = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?;
|
.ok_or_else(item_does_not_exist_error)?;
|
||||||
|
@ -38,7 +50,14 @@ pub fn item_route(item_id: &str, itemdb: &State<ItemDB>) -> FallibleApiResponse
|
||||||
|
|
||||||
/// Returns all variants of an Item
|
/// Returns all variants of an Item
|
||||||
#[get("/item/<item_id>/variants")]
|
#[get("/item/<item_id>/variants")]
|
||||||
pub fn item_variants_page(item_id: &str, itemdb: &State<ItemDB>) -> FallibleApiResponse {
|
pub fn item_variants_page(
|
||||||
|
item_id: &str,
|
||||||
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let item = itemdb
|
let item = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?;
|
.ok_or_else(item_does_not_exist_error)?;
|
||||||
|
@ -52,7 +71,13 @@ pub fn item_variants_page(item_id: &str, itemdb: &State<ItemDB>) -> FallibleApiR
|
||||||
|
|
||||||
/// Returns an API Response for a `Transaction`
|
/// Returns an API Response for a `Transaction`
|
||||||
#[get("/transaction/<transaction>")]
|
#[get("/transaction/<transaction>")]
|
||||||
pub async fn transaction_route(transaction: &str) -> FallibleApiResponse {
|
pub async fn transaction_route(
|
||||||
|
transaction: &str,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let t = Transaction::get(transaction)
|
let t = Transaction::get(transaction)
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| api_error("No transaction with this UUID"))?;
|
.ok_or_else(|| api_error("No transaction with this UUID"))?;
|
||||||
|
@ -66,7 +91,11 @@ pub async fn unique_field_route(
|
||||||
variant_id: &str,
|
variant_id: &str,
|
||||||
field: &str,
|
field: &str,
|
||||||
itemdb: &State<ItemDB>,
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
) -> FallibleApiResponse {
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let variant = itemdb
|
let variant = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?
|
.ok_or_else(item_does_not_exist_error)?
|
||||||
|
|
|
@ -3,6 +3,9 @@ use rocket::{get, post, State};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::check_auth;
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::routes::Token;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::ItemDB,
|
db::ItemDB,
|
||||||
routes::{api_error, FallibleApiResponse},
|
routes::{api_error, FallibleApiResponse},
|
||||||
|
@ -21,8 +24,14 @@ pub struct SupplyForm {
|
||||||
|
|
||||||
/// Route for supply action. Creates a new Transaction for the specified Item Variant.
|
/// Route for supply action. Creates a new Transaction for the specified Item Variant.
|
||||||
#[post("/supply", data = "<form>")]
|
#[post("/supply", data = "<form>")]
|
||||||
pub async fn supply_route(form: Json<SupplyForm>, itemdb: &State<ItemDB>) -> FallibleApiResponse {
|
pub async fn supply_route(
|
||||||
println!("{form:?}");
|
form: Json<SupplyForm>,
|
||||||
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let variant = itemdb
|
let variant = itemdb
|
||||||
.get_item(&form.item)
|
.get_item(&form.item)
|
||||||
.ok_or_else(item_does_not_exist_error)?
|
.ok_or_else(item_does_not_exist_error)?
|
||||||
|
@ -49,7 +58,11 @@ pub async fn supply_log_route(
|
||||||
item_id: &str,
|
item_id: &str,
|
||||||
variant_id: &str,
|
variant_id: &str,
|
||||||
itemdb: &State<ItemDB>,
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
) -> FallibleApiResponse {
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let variant = itemdb
|
let variant = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?
|
.ok_or_else(item_does_not_exist_error)?
|
||||||
|
@ -63,7 +76,14 @@ pub async fn supply_log_route(
|
||||||
|
|
||||||
/// Returns current active Transactions for Item
|
/// Returns current active Transactions for Item
|
||||||
#[get("/item/<item_id>/inventory")]
|
#[get("/item/<item_id>/inventory")]
|
||||||
pub async fn inventory_route(item_id: &str, itemdb: &State<ItemDB>) -> FallibleApiResponse {
|
pub async fn inventory_route(
|
||||||
|
item_id: &str,
|
||||||
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let variant = itemdb
|
let variant = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?;
|
.ok_or_else(item_does_not_exist_error)?;
|
||||||
|
@ -79,7 +99,11 @@ pub async fn inventory_route_variant(
|
||||||
item_id: &str,
|
item_id: &str,
|
||||||
variant_id: &str,
|
variant_id: &str,
|
||||||
itemdb: &State<ItemDB>,
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
) -> FallibleApiResponse {
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let variant = itemdb
|
let variant = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?
|
.ok_or_else(item_does_not_exist_error)?
|
||||||
|
@ -97,7 +121,11 @@ pub async fn variant_stat_route(
|
||||||
item_id: &str,
|
item_id: &str,
|
||||||
variant_id: &str,
|
variant_id: &str,
|
||||||
itemdb: &State<ItemDB>,
|
itemdb: &State<ItemDB>,
|
||||||
|
t: Token,
|
||||||
|
c: &State<Config>,
|
||||||
) -> FallibleApiResponse {
|
) -> FallibleApiResponse {
|
||||||
|
check_auth!(t, c);
|
||||||
|
|
||||||
let variant = itemdb
|
let variant = itemdb
|
||||||
.get_item(item_id)
|
.get_item(item_id)
|
||||||
.ok_or_else(item_does_not_exist_error)?
|
.ok_or_else(item_does_not_exist_error)?
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use rocket::response::status::BadRequest;
|
use rocket::{
|
||||||
|
http::Status, outcome::Outcome, request::FromRequest, response::status::BadRequest, Request,
|
||||||
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
pub mod item;
|
pub mod item;
|
||||||
|
@ -11,3 +13,26 @@ fn api_error(msg: &str) -> ApiError {
|
||||||
"error": msg
|
"error": msg
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Token(pub String);
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! check_auth {
|
||||||
|
($t:ident, $c:ident) => {
|
||||||
|
if !$c.allowed_tokens.contains(&$t.0) {
|
||||||
|
return Err(api_error("Unauthorized"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rocket::async_trait]
|
||||||
|
impl<'r> FromRequest<'r> for Token {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
async fn from_request(request: &'r Request<'_>) -> rocket::request::Outcome<Self, Self::Error> {
|
||||||
|
match request.headers().get_one("token") {
|
||||||
|
Some(key) => Outcome::Success(Token(key.to_string())),
|
||||||
|
None => Outcome::Error((Status::Unauthorized, ())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue