Added local api server + geoffrey_cli
ci/woodpecker/push/woodpecker Pipeline failed
Details
ci/woodpecker/push/woodpecker Pipeline failed
Details
+ Local api server is designed to allow local access to Geoffrey without a token + Uses a unix domain socket, allowing permissions to be handled by the OS + Started work on a tool to exploit this, geoffrey-climain
parent
c3c3814d77
commit
333329c631
|
@ -158,7 +158,7 @@ dependencies = [
|
|||
"libc",
|
||||
"num-integer",
|
||||
"num-traits 0.2.14",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -198,7 +198,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"nom",
|
||||
"rust-ini",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde-hjson",
|
||||
"serde_json",
|
||||
"toml",
|
||||
|
@ -369,6 +369,17 @@ version = "0.3.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.19"
|
||||
|
@ -390,6 +401,7 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
|
@ -428,12 +440,13 @@ dependencies = [
|
|||
"log",
|
||||
"rand 0.8.4",
|
||||
"regex",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
"simple_logger",
|
||||
"strsim 0.10.0",
|
||||
"structopt",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"warp",
|
||||
]
|
||||
|
||||
|
@ -447,7 +460,7 @@ dependencies = [
|
|||
"geoffrey_models",
|
||||
"log",
|
||||
"reqwest",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
"serde_plain",
|
||||
"serenity",
|
||||
|
@ -456,6 +469,18 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geoffrey_cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"geoffrey_models",
|
||||
"hyper",
|
||||
"hyperlocal",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geoffrey_db"
|
||||
version = "0.1.0"
|
||||
|
@ -466,7 +491,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"log",
|
||||
"regex",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
"sled",
|
||||
]
|
||||
|
@ -477,7 +502,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"chrono",
|
||||
"log",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
|
@ -571,6 +596,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.6"
|
||||
|
@ -655,6 +686,19 @@ dependencies = [
|
|||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyperlocal"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"hex",
|
||||
"hyper",
|
||||
"pin-project",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
|
@ -1225,15 +1269,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.8"
|
||||
version = "0.11.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c4e0a76dc12a116108933f6301b95e83634e0c47b0afbed6abbaa0601e99258"
|
||||
checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"bytes 1.1.0",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
|
@ -1250,7 +1295,7 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
"rustls 0.20.2",
|
||||
"rustls-pemfile",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
|
@ -1405,9 +1450,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.133"
|
||||
version = "1.0.136"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -1426,9 +1471,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.133"
|
||||
version = "1.0.136"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1437,13 +1482,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.74"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142"
|
||||
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
|
||||
dependencies = [
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1452,7 +1497,7 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95455e7e29fada2052e72170af226fbe368a4ca33dee847875325d9fdb133858"
|
||||
dependencies = [
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1464,7 +1509,7 @@ dependencies = [
|
|||
"form_urlencoded",
|
||||
"itoa 0.4.8",
|
||||
"ryu",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1482,7 +1527,7 @@ dependencies = [
|
|||
"futures",
|
||||
"percent-encoding",
|
||||
"reqwest",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tracing",
|
||||
|
@ -1692,9 +1737,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.15.0"
|
||||
version = "1.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
|
||||
checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a"
|
||||
dependencies = [
|
||||
"bytes 1.1.0",
|
||||
"libc",
|
||||
|
@ -1796,7 +1841,7 @@ version = "0.5.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2016,7 +2061,7 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
"pin-project",
|
||||
"scoped-tls",
|
||||
"serde 1.0.133",
|
||||
"serde 1.0.136",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
|
|
|
@ -3,5 +3,6 @@ members = [
|
|||
"geoffrey_models",
|
||||
"geoffrey_db",
|
||||
"geoffrey_api",
|
||||
"geoffrey_bot"
|
||||
"geoffrey_bot",
|
||||
"geoffrey_cli"
|
||||
]
|
|
@ -16,6 +16,7 @@ own library for reuse.
|
|||
* [`geoffrey_api`](./geoffrey_api): API wrapper around the database to provide data to the website, bot, plugin, etc.
|
||||
It will implement the command API and the model API. A lot of Geoffrey's logic is implemented here.
|
||||
* [`geoffrey_bot`](./geoffrey_bot): Discord bot for Geoffrey. Uses [serenity](https://github.com/serenity-rs/serenity)
|
||||
* ['geoffrey_cli`](./geoffrey_cli): CLI tool for interacting with Geoffrey locally or on a remote server.
|
||||
|
||||
## License
|
||||
[License](LICENSE)
|
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio = { version = "1.16.1", features = ["full"] }
|
||||
warp = "0.3"
|
||||
serde = "1.0.124"
|
||||
serde_json = "1.0.64"
|
||||
|
@ -20,6 +20,7 @@ rand = "0.8.4"
|
|||
regex = "1.5.4"
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
strsim = "0.10.0"
|
||||
tokio-stream = { version = "0.1.8", features = ["net"] }
|
||||
|
||||
# Doing this for now, as there seems to be an issue with using timestamps
|
||||
[dependencies.simple_logger]
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub enum RequestType {
|
||||
POST,
|
||||
GET,
|
||||
}
|
||||
|
||||
pub trait ApiEndpoint {
|
||||
fn endpoint_name() -> String;
|
||||
fn request_type() -> RequestType;
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::helper::validate_string_parameter;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::item::ItemListing;
|
||||
|
@ -11,21 +9,28 @@ use geoffrey_models::models::player::Player;
|
|||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::settings::GeoffreySettings;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::helper::validate_string_parameter;
|
||||
use crate::Result;
|
||||
|
||||
pub struct AddItem {}
|
||||
|
||||
impl Command for AddItem {
|
||||
type Req = AddItemParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for AddItem {
|
||||
fn endpoint_name() -> String {
|
||||
"add_item".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for AddItem {
|
||||
type Req = AddItemParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::helper::validate_string_parameter;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_models::models::locations::{Location, LocationDb};
|
||||
use geoffrey_models::models::parameters::add_location_params::AddLocationParams;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::settings::GeoffreySettings;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::helper::validate_string_parameter;
|
||||
use crate::Result;
|
||||
|
||||
pub struct AddLocation {}
|
||||
|
||||
impl Command for AddLocation {
|
||||
type Req = AddLocationParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for AddLocation {
|
||||
fn endpoint_name() -> String {
|
||||
"add_location".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for AddLocation {
|
||||
type Req = AddLocationParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,28 +1,34 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
|
||||
use geoffrey_models::models::parameters::add_token_params::AddTokenParams;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::token::Token;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct AddToken {}
|
||||
|
||||
impl Command for AddToken {
|
||||
type Req = AddTokenParams;
|
||||
type Resp = Token;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for AddToken {
|
||||
fn endpoint_name() -> String {
|
||||
"add_token".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for AddToken {
|
||||
type Req = AddTokenParams;
|
||||
type Resp = Token;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::ADMIN
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::locations::{Location, LocationDb};
|
||||
|
@ -8,21 +7,27 @@ use geoffrey_models::models::parameters::delete_params::DeleteParams;
|
|||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct Delete {}
|
||||
|
||||
impl Command for Delete {
|
||||
type Req = DeleteParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for Delete {
|
||||
fn endpoint_name() -> String {
|
||||
"delete".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for Delete {
|
||||
type Req = DeleteParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::locations::{Location, LocationDb};
|
||||
|
@ -8,21 +7,27 @@ use geoffrey_models::models::parameters::edit_params::EditParams;
|
|||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct Edit {}
|
||||
|
||||
impl Command for Edit {
|
||||
type Req = EditParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for Edit {
|
||||
fn endpoint_name() -> String {
|
||||
"edit".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for Edit {
|
||||
type Req = EditParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,27 +1,32 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_models::models::locations::{Location, LocationDb};
|
||||
use geoffrey_models::models::parameters::find_params::FindParams;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct FindCommand {}
|
||||
|
||||
impl Command for FindCommand {
|
||||
type Req = FindParams;
|
||||
type Resp = Vec<Location>;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for FindCommand {
|
||||
fn endpoint_name() -> String {
|
||||
"find".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::GET
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for FindCommand {
|
||||
type Req = FindParams;
|
||||
type Resp = Vec<Location>;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::ALL
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use strsim::normalized_damerau_levenshtein;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::locations::{Location, LocationDb};
|
||||
|
@ -8,22 +9,27 @@ use geoffrey_models::models::parameters::info_params::InfoParams;
|
|||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
use strsim::normalized_damerau_levenshtein;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct InfoCommand {}
|
||||
|
||||
impl Command for InfoCommand {
|
||||
type Req = InfoParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for InfoCommand {
|
||||
fn endpoint_name() -> String {
|
||||
"info".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::GET
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for InfoCommand {
|
||||
type Req = InfoParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::ALL
|
||||
|
|
|
@ -1,29 +1,35 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::{Duration, Utc};
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
|
||||
use geoffrey_models::models::link::Link;
|
||||
use geoffrey_models::models::parameters::link_params::LinkParameters;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use geoffrey_models::GeoffreyDatabaseModel;
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct LinkCommand {}
|
||||
|
||||
impl Command for LinkCommand {
|
||||
type Req = LinkParameters;
|
||||
type Resp = Link;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for LinkCommand {
|
||||
fn endpoint_name() -> String {
|
||||
"link".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for LinkCommand {
|
||||
type Req = LinkParameters;
|
||||
type Resp = Link;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use warp::filters::BoxedFilter;
|
||||
use warp::Filter;
|
||||
|
||||
use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam};
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::response::APIResponse;
|
||||
use geoffrey_models::models::settings::GeoffreySettings;
|
||||
use geoffrey_models::models::token::{Permissions, Token};
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::add_item::AddItem;
|
||||
use crate::commands::add_location::AddLocation;
|
||||
use crate::commands::delete::Delete;
|
||||
|
@ -11,23 +28,9 @@ use crate::commands::report_out_of_stock::ReportOutOfStock;
|
|||
use crate::commands::restock::Restock;
|
||||
use crate::commands::selling::Selling;
|
||||
use crate::commands::set_portal::SetPortal;
|
||||
use crate::commands::settings::Settings;
|
||||
use crate::context::Context;
|
||||
use crate::helper::{get_player_from_req, get_token_from_req};
|
||||
use crate::Result;
|
||||
use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam};
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::response::APIResponse;
|
||||
use geoffrey_models::models::settings::GeoffreySettings;
|
||||
use geoffrey_models::models::token::{Permissions, Token};
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
use warp::filters::BoxedFilter;
|
||||
use warp::Filter;
|
||||
|
||||
pub mod add_item;
|
||||
pub mod add_location;
|
||||
|
@ -45,19 +48,10 @@ pub mod selling;
|
|||
pub mod set_portal;
|
||||
pub mod settings;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub enum RequestType {
|
||||
POST,
|
||||
GET,
|
||||
}
|
||||
|
||||
pub trait Command {
|
||||
pub trait Command: ApiEndpoint {
|
||||
type Req: GeoffreyParam + 'static;
|
||||
type Resp: Serialize + DeserializeOwned + Send + Debug;
|
||||
|
||||
fn command_name() -> String;
|
||||
fn request_type() -> RequestType;
|
||||
fn command_level() -> CommandLevel;
|
||||
fn run_command(ctx: Arc<Context>, req: &Self::Req, user: Option<Player>) -> Result<Self::Resp>;
|
||||
|
||||
|
@ -96,11 +90,11 @@ pub fn handle_command<T: Command>(
|
|||
ctx: Arc<Context>,
|
||||
req: CommandRequest<T::Req>,
|
||||
) -> Result<T::Resp> {
|
||||
log::info!("Running command {}", T::command_name());
|
||||
log::info!("Running command {}", T::endpoint_name());
|
||||
log::debug!("User: {:?} Request params: {:?}", req.user_id, req.params);
|
||||
|
||||
let user = get_player_from_req::<T::Req>(&ctx.db, &req)?;
|
||||
let token = get_token_from_req::<T::Req>(&ctx.db, &req)?;
|
||||
let token = get_token_from_req(&ctx.db, &req)?;
|
||||
|
||||
match T::user_is_authorized(&token, &user) {
|
||||
Ok(_) => {
|
||||
|
@ -113,7 +107,7 @@ pub fn handle_command<T: Command>(
|
|||
|
||||
#[allow(clippy::needless_return)]
|
||||
pub fn create_command_filter<T: Command>(ctx: Arc<Context>) -> BoxedFilter<(impl warp::Reply,)> {
|
||||
let filter = warp::path(T::command_name())
|
||||
let filter = warp::path(T::endpoint_name())
|
||||
.and(warp::any().map(move || ctx.clone()))
|
||||
.and(warp::body::json())
|
||||
.map(|ctx: Arc<Context>, req: CommandRequest<T::Req>| {
|
||||
|
@ -155,9 +149,3 @@ pub fn command_filter(
|
|||
.or(create_command_filter::<SetPortal>(ctx)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn model_filter(
|
||||
ctx: Arc<Context>,
|
||||
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
||||
warp::path("model").and(create_command_filter::<Settings>(ctx))
|
||||
}
|
||||
|
|
|
@ -1,27 +1,32 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_models::models::link::Link;
|
||||
use geoffrey_models::models::parameters::register_params::RegisterParameters;
|
||||
use geoffrey_models::models::player::{Player, UserID};
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use geoffrey_models::GeoffreyDatabaseModel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct Register {}
|
||||
|
||||
impl Command for Register {
|
||||
type Req = RegisterParameters;
|
||||
type Resp = Player;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for Register {
|
||||
fn endpoint_name() -> String {
|
||||
"register".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for Register {
|
||||
type Req = RegisterParameters;
|
||||
type Resp = Player;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::ALL
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::locations::{Location, LocationDataDb, LocationDb, LocationType};
|
||||
|
@ -8,21 +7,27 @@ use geoffrey_models::models::parameters::item_command_params::ItemCommandParams;
|
|||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct RemoveItem {}
|
||||
|
||||
impl Command for RemoveItem {
|
||||
type Req = ItemCommandParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for RemoveItem {
|
||||
fn endpoint_name() -> String {
|
||||
"remove_item".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for RemoveItem {
|
||||
type Req = ItemCommandParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::item::ItemListing;
|
||||
|
@ -9,22 +9,27 @@ use geoffrey_models::models::parameters::item_command_params::ItemCommandParams;
|
|||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct ReportOutOfStock {}
|
||||
|
||||
impl Command for ReportOutOfStock {
|
||||
type Req = ItemCommandParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for ReportOutOfStock {
|
||||
fn endpoint_name() -> String {
|
||||
"report_out_of_stock".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for ReportOutOfStock {
|
||||
type Req = ItemCommandParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::item::ItemListing;
|
||||
|
@ -9,22 +9,27 @@ use geoffrey_models::models::parameters::item_command_params::ItemCommandParams;
|
|||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct Restock {}
|
||||
|
||||
impl Command for Restock {
|
||||
type Req = ItemCommandParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for Restock {
|
||||
fn endpoint_name() -> String {
|
||||
"restock".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for Restock {
|
||||
type Req = ItemCommandParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,27 +1,32 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_models::models::item::ItemListing;
|
||||
use geoffrey_models::models::locations::{LocationDataDb, LocationDb};
|
||||
use geoffrey_models::models::parameters::selling_params::{ItemSort, Order, SellingParams};
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::selling_listing::SellingListing;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct Selling {}
|
||||
|
||||
impl Command for Selling {
|
||||
type Req = SellingParams;
|
||||
type Resp = Vec<SellingListing>;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for Selling {
|
||||
fn endpoint_name() -> String {
|
||||
"selling".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::GET
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for Selling {
|
||||
type Req = SellingParams;
|
||||
type Resp = Vec<SellingListing>;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::ALL
|
||||
|
@ -99,19 +104,21 @@ impl Command for Selling {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::commands::selling::Selling;
|
||||
use crate::commands::Command;
|
||||
use crate::config::{GeoffreyAPIConfig, ServerConfig};
|
||||
use crate::context::Context;
|
||||
use crate::Args;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
use geoffrey_models::models::item::ItemListing;
|
||||
use geoffrey_models::models::locations::shop::Shop;
|
||||
use geoffrey_models::models::locations::{LocationDataDb, LocationDb};
|
||||
use geoffrey_models::models::parameters::selling_params::SellingParams;
|
||||
use geoffrey_models::models::settings::GeoffreySettings;
|
||||
use geoffrey_models::models::Position;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::commands::selling::Selling;
|
||||
use crate::commands::Command;
|
||||
use crate::config::{GeoffreyAPIConfig, ServerConfig};
|
||||
use crate::context::Context;
|
||||
use crate::Args;
|
||||
|
||||
fn test_selling_lookup_speed(iter: i32, shop_count: i32, items_for_sale: i32) -> f32 {
|
||||
let config = GeoffreyAPIConfig {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_db::helper::load_location;
|
||||
use geoffrey_db::query::QueryBuilder;
|
||||
use geoffrey_models::models::locations::{Location, LocationDb};
|
||||
|
@ -8,21 +7,27 @@ use geoffrey_models::models::parameters::set_portal_params::SetPortalParams;
|
|||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::commands::Command;
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
|
||||
pub struct SetPortal {}
|
||||
|
||||
impl Command for SetPortal {
|
||||
type Req = SetPortalParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
impl ApiEndpoint for SetPortal {
|
||||
fn endpoint_name() -> String {
|
||||
"set_portal".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for SetPortal {
|
||||
type Req = SetPortalParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
|
|
|
@ -1,31 +1 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use geoffrey_models::models::parameters::EmptyRequest;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::settings::GeoffreySettings;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Settings {}
|
||||
|
||||
impl Command for Settings {
|
||||
type Req = EmptyRequest;
|
||||
type Resp = GeoffreySettings;
|
||||
|
||||
fn command_name() -> String {
|
||||
"settings".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::GET
|
||||
}
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::ALL
|
||||
}
|
||||
|
||||
fn run_command(ctx: Arc<Context>, _: &Self::Req, _: Option<Player>) -> Result<Self::Resp> {
|
||||
Ok(ctx.cfg.geoffrey_settings.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ pub struct GeoffreyAPIConfig {
|
|||
pub struct ServerConfig {
|
||||
pub db_path: PathBuf,
|
||||
pub host: String,
|
||||
pub local_socket: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl GeoffreyAPIConfig {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::Result;
|
||||
use geoffrey_db::database::Database;
|
||||
use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam};
|
||||
use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam, GeoffreyRequest};
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::token::Token;
|
||||
|
@ -18,12 +18,12 @@ pub fn get_player_from_req<T: GeoffreyParam>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_token_from_req<T: GeoffreyParam>(
|
||||
pub fn get_token_from_req<T: GeoffreyParam, U: GeoffreyRequest<T>>(
|
||||
db: &Database,
|
||||
req: &CommandRequest<T>,
|
||||
req: &U,
|
||||
) -> Result<Option<Token>> {
|
||||
Ok(db
|
||||
.filter(|_, token: &Token| token.secret == req.token)?
|
||||
.filter(|_, token: &Token| token.secret == req.get_token())?
|
||||
.next())
|
||||
}
|
||||
|
||||
|
|
|
@ -8,22 +8,28 @@ use warp::Filter;
|
|||
|
||||
use structopt::StructOpt;
|
||||
|
||||
use tokio::net::UnixListener;
|
||||
|
||||
use geoffrey_models::logging::LogLevel;
|
||||
use geoffrey_models::models::parameters::add_token_params::AddTokenParams;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::token::Permissions;
|
||||
|
||||
use crate::commands::add_token::AddToken;
|
||||
use crate::commands::{command_filter, model_filter, Command};
|
||||
use crate::commands::{command_filter, Command};
|
||||
use crate::config::GeoffreyAPIConfig;
|
||||
use crate::context::Context;
|
||||
use crate::logging::init_logging;
|
||||
use crate::model::{local_model_filter, remote_model_filter};
|
||||
use tokio_stream::wrappers::UnixListenerStream;
|
||||
|
||||
mod api_endpoint;
|
||||
mod commands;
|
||||
mod config;
|
||||
mod context;
|
||||
mod helper;
|
||||
mod logging;
|
||||
mod model;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, GeoffreyAPIError>;
|
||||
|
||||
|
@ -66,7 +72,39 @@ pub struct CreateTokenCommand {
|
|||
pub permissions: Vec<Permissions>,
|
||||
}
|
||||
|
||||
async fn run_server(ctx: Arc<Context>) {
|
||||
async fn run_local_server(ctx: &Arc<Context>) {
|
||||
let socket_path = ctx
|
||||
.cfg
|
||||
.server_config
|
||||
.local_socket
|
||||
.as_ref()
|
||||
.expect("Expected local_socket to be defined");
|
||||
|
||||
if socket_path.exists() {
|
||||
if let Err(e) = std::fs::remove_file(&socket_path) {
|
||||
log::error!("Unable to cleanup local socket: {}", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let listener = match UnixListener::bind(socket_path) {
|
||||
Ok(l) => l,
|
||||
Err(e) => {
|
||||
log::error!("Unable to open local socket: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let unix_listener_stream = UnixListenerStream::new(listener);
|
||||
|
||||
let local_api = local_model_filter(ctx.clone());
|
||||
|
||||
warp::serve(local_api.clone())
|
||||
.run_incoming(unix_listener_stream)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn run_remote_server(ctx: &Arc<Context>) {
|
||||
let socket_addr = match SocketAddr::from_str(ctx.cfg.server_config.host.as_str()) {
|
||||
Ok(socket_addr) => socket_addr,
|
||||
Err(e) => {
|
||||
|
@ -79,11 +117,24 @@ async fn run_server(ctx: Arc<Context>) {
|
|||
}
|
||||
};
|
||||
|
||||
let api = command_filter(ctx.clone()).or(model_filter(ctx.clone()));
|
||||
let api = command_filter(ctx.clone()).or(remote_model_filter(ctx.clone()));
|
||||
|
||||
warp::serve(api).run(socket_addr).await;
|
||||
}
|
||||
|
||||
async fn run_server(ctx: Arc<Context>) {
|
||||
tokio::select! {
|
||||
// Start local api
|
||||
_ = run_local_server(&ctx), if ctx.cfg.server_config.local_socket.is_some() => {
|
||||
log::warn!("Socket API exited")
|
||||
}
|
||||
// Start HTTP api
|
||||
_ = run_remote_server(&ctx) => {
|
||||
log::warn!("HTTP API exited")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_token(ctx: Arc<Context>, perms: Vec<Permissions>) {
|
||||
match AddToken::run_command(ctx, &AddTokenParams { permissions: perms }, None) {
|
||||
Ok(token) => {
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
mod settings;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::helper::get_token_from_req;
|
||||
use crate::model::settings::Settings;
|
||||
use crate::Result;
|
||||
use geoffrey_models::models::parameters::{GeoffreyParam, ModelRequest};
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::response::APIResponse;
|
||||
use geoffrey_models::models::token::{Permissions, Token};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
use warp::filters::BoxedFilter;
|
||||
use warp::Filter;
|
||||
|
||||
pub trait ModelEndpoint: ApiEndpoint {
|
||||
type Req: GeoffreyParam + 'static;
|
||||
type Resp: Serialize + DeserializeOwned + Send + Debug;
|
||||
|
||||
fn token_permission() -> Vec<Permissions>;
|
||||
fn run_endpoint(ctx: Arc<Context>, req: &Self::Req) -> Result<Self::Resp>;
|
||||
|
||||
fn check_token_permission(token: &Token) -> bool {
|
||||
for perm in Self::token_permission() {
|
||||
if !token.check_permission(perm) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_remote_model_request<T: ModelEndpoint>(
|
||||
ctx: Arc<Context>,
|
||||
req: ModelRequest<T::Req>,
|
||||
) -> Result<T::Resp> {
|
||||
let token = get_token_from_req(&ctx.db, &req)?;
|
||||
|
||||
if let Some(token) = token {
|
||||
if T::check_token_permission(&token) {
|
||||
return T::run_endpoint(ctx, &req.params);
|
||||
}
|
||||
}
|
||||
|
||||
Err(GeoffreyAPIError::TokenNotAuthorized)
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_return)]
|
||||
pub fn create_remote_model_filter<T: ModelEndpoint>(
|
||||
ctx: Arc<Context>,
|
||||
) -> BoxedFilter<(impl warp::Reply,)> {
|
||||
let filter = warp::path(T::endpoint_name())
|
||||
.and(warp::any().map(move || ctx.clone()))
|
||||
.and(warp::body::json())
|
||||
.map(|ctx: Arc<Context>, req: ModelRequest<T::Req>| {
|
||||
log::info!("Running model query {}", T::endpoint_name());
|
||||
log::debug!("Request params: {:?}", req.params);
|
||||
|
||||
let reply = handle_remote_model_request::<T>(ctx, req);
|
||||
|
||||
if let Ok(reply) = reply {
|
||||
log::debug!("Successfully processed model request");
|
||||
warp::reply::json(&APIResponse::Response::<T::Resp>(reply))
|
||||
} else {
|
||||
let e = reply.err().unwrap();
|
||||
let msg = e.to_string();
|
||||
log::warn!("Got error when processing model request '{:?}': {}", e, msg);
|
||||
warp::reply::json(&APIResponse::<T::Resp>::Error { error: e, msg })
|
||||
}
|
||||
});
|
||||
|
||||
if T::request_type() == RequestType::POST {
|
||||
return filter.and(warp::post()).boxed();
|
||||
} else {
|
||||
return filter.and(warp::get()).boxed();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_return)]
|
||||
pub fn create_local_model_filter<T: ModelEndpoint>(
|
||||
ctx: Arc<Context>,
|
||||
) -> BoxedFilter<(impl warp::Reply,)> {
|
||||
let filter = warp::path(T::endpoint_name())
|
||||
.and(warp::any().map(move || ctx.clone()))
|
||||
.and(warp::body::json())
|
||||
.map(|ctx: Arc<Context>, req: T::Req| {
|
||||
log::info!("Running local model query {}", T::endpoint_name());
|
||||
log::debug!("Request params: {:?}", req);
|
||||
let reply = T::run_endpoint(ctx, &req);
|
||||
|
||||
if let Ok(reply) = reply {
|
||||
log::debug!("Successfully processed model request");
|
||||
warp::reply::json(&APIResponse::Response::<T::Resp>(reply))
|
||||
} else {
|
||||
let e = reply.err().unwrap();
|
||||
let msg = e.to_string();
|
||||
log::warn!("Got error when processing model request '{:?}': {}", e, msg);
|
||||
warp::reply::json(&APIResponse::<T::Resp>::Error { error: e, msg })
|
||||
}
|
||||
});
|
||||
|
||||
if T::request_type() == RequestType::POST {
|
||||
return filter.and(warp::post()).boxed();
|
||||
} else {
|
||||
return filter.and(warp::get()).boxed();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remote_model_filter(
|
||||
ctx: Arc<Context>,
|
||||
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
||||
warp::path("model").and(create_remote_model_filter::<Settings>(ctx))
|
||||
}
|
||||
|
||||
pub fn local_model_filter(
|
||||
ctx: Arc<Context>,
|
||||
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
||||
warp::path("model").and(create_local_model_filter::<Settings>(ctx))
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use geoffrey_models::models::settings::GeoffreySettings;
|
||||
|
||||
use crate::api_endpoint::{ApiEndpoint, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::model::ModelEndpoint;
|
||||
use crate::Result;
|
||||
use geoffrey_models::models::parameters::EmptyRequest;
|
||||
use geoffrey_models::models::token::Permissions;
|
||||
|
||||
pub struct Settings {}
|
||||
|
||||
impl ApiEndpoint for Settings {
|
||||
fn endpoint_name() -> String {
|
||||
"settings".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::GET
|
||||
}
|
||||
}
|
||||
|
||||
impl ModelEndpoint for Settings {
|
||||
type Req = EmptyRequest;
|
||||
type Resp = GeoffreySettings;
|
||||
|
||||
fn token_permission() -> Vec<Permissions> {
|
||||
vec![Permissions::ModelGet]
|
||||
}
|
||||
|
||||
fn run_endpoint(ctx: Arc<Context>, _: &Self::Req) -> Result<Self::Resp> {
|
||||
Ok(ctx.cfg.geoffrey_settings.clone())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "geoffrey_cli"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
hyper = { version = "0.14", features = ["full"] }
|
||||
hyperlocal = "0.8.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
geoffrey_models = { path = "../geoffrey_models" }
|
||||
serde = "1.0.136"
|
||||
serde_json = "1.0.78"
|
|
@ -0,0 +1,28 @@
|
|||
use geoffrey_models::models::parameters::EmptyRequest;
|
||||
use hyper::body::{Body, HttpBody};
|
||||
use hyper::Client;
|
||||
use hyper::{Method, Request};
|
||||
use hyperlocal::{UnixClientExt, Uri};
|
||||
use tokio::io::{stdout, AsyncWriteExt as _};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let client = Client::unix();
|
||||
|
||||
let uri: hyper::Uri = Uri::new("/tmp/geoffrey.socket", "/model/settings/").into();
|
||||
|
||||
let params = EmptyRequest {};
|
||||
|
||||
let req = Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri(uri)
|
||||
.header("content-type", "application/json")
|
||||
.body(Body::from(serde_json::to_string(¶ms).unwrap()))
|
||||
.unwrap();
|
||||
|
||||
let mut resp = client.request(req).await.unwrap();
|
||||
|
||||
while let Some(chunk) = resp.body_mut().data().await {
|
||||
stdout().write_all(&chunk.unwrap()).await.unwrap();
|
||||
}
|
||||
}
|
|
@ -18,6 +18,11 @@ use std::fmt::Debug;
|
|||
|
||||
pub trait GeoffreyParam: Serialize + DeserializeOwned + Debug + Clone + Send + Sync {}
|
||||
|
||||
pub trait GeoffreyRequest<T> {
|
||||
fn get_token(&self) -> String;
|
||||
fn get_params(&self) -> &T;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct CommandRequest<T> {
|
||||
pub token: String,
|
||||
|
@ -25,6 +30,32 @@ pub struct CommandRequest<T> {
|
|||
pub params: T,
|
||||
}
|
||||
|
||||
impl<T> GeoffreyRequest<T> for CommandRequest<T> {
|
||||
fn get_token(&self) -> String {
|
||||
self.token.clone()
|
||||
}
|
||||
|
||||
fn get_params(&self) -> &T {
|
||||
&self.params
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ModelRequest<T> {
|
||||
pub token: String,
|
||||
pub params: T,
|
||||
}
|
||||
|
||||
impl<T> GeoffreyRequest<T> for ModelRequest<T> {
|
||||
fn get_token(&self) -> String {
|
||||
self.token.clone()
|
||||
}
|
||||
|
||||
fn get_params(&self) -> &T {
|
||||
&self.params
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct EmptyRequest {}
|
||||
|
||||
|
|
Loading…
Reference in New Issue