Compare commits

..

2 Commits

Author SHA1 Message Date
Joey Hines 3711e7011c
Refactored parameter handling + added delete command
+ CommandRequest is now a struct that contains a generic parameter for the type
+ This streamlines adding new command parameters and reduces duplicate code
+ Added delete commands
2021-12-17 20:03:15 -07:00
Joey Hines 4c1d1cd6d0
Added a remove method to GeoffreyDB
+ clippy + fmt
2021-12-17 17:24:51 -07:00
23 changed files with 186 additions and 236 deletions

View File

@ -36,7 +36,7 @@ impl Command for AddItem {
} }
} }
fn run_command(ctx: Arc<Context>, req: Self::Req, user: Option<Player>) -> Result<Self::Resp> { fn run_command(ctx: Arc<Context>, req: &Self::Req, user: Option<Player>) -> Result<Self::Resp> {
let user = user.unwrap(); let user = user.unwrap();
let shops: Vec<LocationDb> = ctx let shops: Vec<LocationDb> = ctx

View File

@ -26,7 +26,7 @@ impl Command for AddLocation {
CommandLevel::REGISTERED CommandLevel::REGISTERED
} }
fn run_command(ctx: Arc<Context>, req: Self::Req, user: Option<Player>) -> Result<Self::Resp> { fn run_command(ctx: Arc<Context>, req: &Self::Req, user: Option<Player>) -> Result<Self::Resp> {
let user = user.unwrap(); let user = user.unwrap();
let location = LocationDb::new( let location = LocationDb::new(

View File

@ -28,7 +28,7 @@ impl Command for AddToken {
CommandLevel::ADMIN CommandLevel::ADMIN
} }
fn run_command(ctx: Arc<Context>, req: Self::Req, _: Option<Player>) -> Result<Self::Resp> { fn run_command(ctx: Arc<Context>, req: &Self::Req, _: Option<Player>) -> Result<Self::Resp> {
let mut token = Token::default(); let mut token = Token::default();
let secret: String = rand::thread_rng() let secret: String = rand::thread_rng()
@ -39,8 +39,8 @@ impl Command for AddToken {
token.secret = secret; token.secret = secret;
for permission in req.permissions { for permission in &req.permissions {
token.set_permission(permission); token.set_permission(*permission);
} }
ctx.db.insert(token).map_err(GeoffreyAPIError::from) ctx.db.insert(token).map_err(GeoffreyAPIError::from)

View File

@ -0,0 +1,48 @@
use crate::commands::{Command, RequestType};
use crate::context::Context;
use crate::Result;
use geoffrey_db::helper::load_location;
use geoffrey_models::models::locations::{Location, LocationDb};
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;
pub struct Delete {}
impl Command for Delete {
type Req = DeleteParams;
type Resp = Location;
fn command_name() -> String {
"delete".to_string()
}
fn request_type() -> RequestType {
RequestType::POST
}
fn command_level() -> CommandLevel {
CommandLevel::REGISTERED
}
fn run_command(ctx: Arc<Context>, req: &Self::Req, user: Option<Player>) -> Result<Self::Resp> {
let user = user.unwrap();
let filter = regex::Regex::new(format!(r"(?i)^{}$", req.location).as_str()).unwrap();
let location: LocationDb = ctx
.db
.filter(|_, loc: &LocationDb| {
filter.is_match(&loc.name) && loc.owners().contains(&user.id.unwrap())
})?
.next()
.ok_or(GeoffreyAPIError::EntryNotFound)?;
let location = load_location(&ctx.db, &location).map_err(GeoffreyAPIError::from)?;
ctx.db.remove::<LocationDb>(location.id)?;
Ok(location)
}
}

View File

@ -27,7 +27,7 @@ impl Command for FindCommand {
CommandLevel::ALL CommandLevel::ALL
} }
fn run_command(ctx: Arc<Context>, req: Self::Req, _: Option<Player>) -> Result<Self::Resp> { fn run_command(ctx: Arc<Context>, req: &Self::Req, _: Option<Player>) -> Result<Self::Resp> {
let query = req.query.to_lowercase(); let query = req.query.to_lowercase();
let players: Vec<u64> = ctx let players: Vec<u64> = ctx
.db .db

View File

@ -1,5 +1,6 @@
use crate::commands::add_item::AddItem; use crate::commands::add_item::AddItem;
use crate::commands::add_location::AddLocation; use crate::commands::add_location::AddLocation;
use crate::commands::delete::Delete;
use crate::commands::find::FindCommand; use crate::commands::find::FindCommand;
use crate::commands::register::Register; use crate::commands::register::Register;
use crate::commands::selling::Selling; use crate::commands::selling::Selling;
@ -7,7 +8,7 @@ use crate::commands::set_portal::SetPortal;
use crate::context::Context; use crate::context::Context;
use crate::helper::{get_player_from_req, get_token_from_req}; use crate::helper::{get_player_from_req, get_token_from_req};
use crate::Result; use crate::Result;
use geoffrey_models::models::parameters::CommandRequest; use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam};
use geoffrey_models::models::player::Player; use geoffrey_models::models::player::Player;
use geoffrey_models::models::response::api_error::GeoffreyAPIError; use geoffrey_models::models::response::api_error::GeoffreyAPIError;
use geoffrey_models::models::response::APIResponse; use geoffrey_models::models::response::APIResponse;
@ -23,6 +24,7 @@ use warp::Filter;
pub mod add_item; pub mod add_item;
pub mod add_location; pub mod add_location;
pub mod add_token; pub mod add_token;
pub mod delete;
pub mod find; pub mod find;
pub mod register; pub mod register;
pub mod selling; pub mod selling;
@ -36,13 +38,13 @@ pub enum RequestType {
} }
pub trait Command { pub trait Command {
type Req: CommandRequest; type Req: GeoffreyParam + 'static;
type Resp: Serialize + DeserializeOwned + Send; type Resp: Serialize + DeserializeOwned + Send + Debug;
fn command_name() -> String; fn command_name() -> String;
fn request_type() -> RequestType; fn request_type() -> RequestType;
fn command_level() -> CommandLevel; fn command_level() -> CommandLevel;
fn run_command(ctx: Arc<Context>, req: Self::Req, user: Option<Player>) -> Result<Self::Resp>; fn run_command(ctx: Arc<Context>, req: &Self::Req, user: Option<Player>) -> Result<Self::Resp>;
fn validate_parameters(_: &Self::Req) -> Result<()> { fn validate_parameters(_: &Self::Req) -> Result<()> {
Ok(()) Ok(())
@ -75,17 +77,20 @@ pub trait Command {
} }
} }
pub fn handle_command<T: Command>(ctx: Arc<Context>, req: T::Req) -> Result<T::Resp> { 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::command_name());
log::debug!("Request: {:?}", req); log::debug!("Request: {:?}", req);
let user = get_player_from_req(&ctx.db, &req)?; let user = get_player_from_req::<T::Req>(&ctx.db, &req)?;
let token = get_token_from_req(&ctx.db, &req)?; let token = get_token_from_req::<T::Req>(&ctx.db, &req)?;
match T::user_is_authorized(&token, &user) { match T::user_is_authorized(&token, &user) {
Ok(_) => { Ok(_) => {
T::validate_parameters(&req)?; T::validate_parameters(&req.params)?;
T::run_command(ctx, req, user) T::run_command(ctx, &req.params, user)
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -96,7 +101,7 @@ pub fn create_command_filter<T: Command>(ctx: Arc<Context>) -> BoxedFilter<(impl
let filter = warp::path(T::command_name()) let filter = warp::path(T::command_name())
.and(warp::any().map(move || ctx.clone())) .and(warp::any().map(move || ctx.clone()))
.and(warp::body::json()) .and(warp::body::json())
.map(|ctx: Arc<Context>, req: T::Req| { .map(|ctx: Arc<Context>, req: CommandRequest<T::Req>| {
let reply = handle_command::<T>(ctx, req); let reply = handle_command::<T>(ctx, req);
if let Ok(reply) = reply { if let Ok(reply) = reply {
log::debug!("Successfully processed command"); log::debug!("Successfully processed command");
@ -125,6 +130,7 @@ pub fn command_filter(
.or(create_command_filter::<Register>(ctx.clone())) .or(create_command_filter::<Register>(ctx.clone()))
.or(create_command_filter::<Selling>(ctx.clone())) .or(create_command_filter::<Selling>(ctx.clone()))
.or(create_command_filter::<AddItem>(ctx.clone())) .or(create_command_filter::<AddItem>(ctx.clone()))
.or(create_command_filter::<Delete>(ctx.clone()))
.or(create_command_filter::<SetPortal>(ctx)), .or(create_command_filter::<SetPortal>(ctx)),
) )
} }

View File

@ -26,10 +26,10 @@ impl Command for Register {
fn run_command( fn run_command(
ctx: Arc<Context>, ctx: Arc<Context>,
req: Self::Req, req: &Self::Req,
_: Option<Player>, _: Option<Player>,
) -> crate::Result<Self::Resp> { ) -> crate::Result<Self::Resp> {
let player = Player::new(req.username.as_str(), req.new_user_id); let player = Player::new(req.username.as_str(), req.user_id.clone());
ctx.db.insert(player).map_err(GeoffreyAPIError::from) ctx.db.insert(player).map_err(GeoffreyAPIError::from)
} }

View File

@ -27,7 +27,7 @@ impl Command for Selling {
CommandLevel::ALL CommandLevel::ALL
} }
fn run_command(ctx: Arc<Context>, req: Self::Req, _: Option<Player>) -> Result<Self::Resp> { fn run_command(ctx: Arc<Context>, req: &Self::Req, _: Option<Player>) -> Result<Self::Resp> {
let mut listings: Vec<SellingListing> = ctx let mut listings: Vec<SellingListing> = ctx
.db .db
.filter(|_, loc: &LocationDb| { .filter(|_, loc: &LocationDb| {
@ -69,7 +69,7 @@ impl Command for Selling {
.flatten() .flatten()
.collect(); .collect();
let sort = req.sort.unwrap_or(ItemSort::Restock); let sort = req.sort.as_ref().unwrap_or(&ItemSort::Restock);
match sort { match sort {
ItemSort::Price => { ItemSort::Price => {
@ -80,16 +80,16 @@ impl Command for Selling {
} }
} }
let ordering = if let Some(order) = req.order { let ordering = if let Some(order) = &req.order {
order order
} else { } else {
match sort { match sort {
ItemSort::Price => Order::Low, ItemSort::Price => &Order::Low,
ItemSort::Restock => Order::High, ItemSort::Restock => &Order::High,
} }
}; };
if ordering == Order::High { if *ordering == Order::High {
listings.reverse(); listings.reverse();
} }

View File

@ -27,7 +27,7 @@ impl Command for SetPortal {
CommandLevel::REGISTERED CommandLevel::REGISTERED
} }
fn run_command(ctx: Arc<Context>, req: Self::Req, user: Option<Player>) -> Result<Self::Resp> { fn run_command(ctx: Arc<Context>, req: &Self::Req, user: Option<Player>) -> Result<Self::Resp> {
let user = user.unwrap(); let user = user.unwrap();
let filter = regex::Regex::new(format!(r"(?i)^{}$", req.loc_name).as_str()).unwrap(); let filter = regex::Regex::new(format!(r"(?i)^{}$", req.loc_name).as_str()).unwrap();
@ -39,7 +39,7 @@ impl Command for SetPortal {
.next() .next()
.ok_or(GeoffreyAPIError::EntryNotFound)?; .ok_or(GeoffreyAPIError::EntryNotFound)?;
location.portal = Some(req.portal); location.portal = Some(req.portal.clone());
let location = ctx.db.insert(location)?; let location = ctx.db.insert(location)?;

View File

@ -1,21 +1,27 @@
use crate::Result; use crate::Result;
use geoffrey_db::database::Database; use geoffrey_db::database::Database;
use geoffrey_models::models::parameters::CommandRequest; use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam};
use geoffrey_models::models::player::Player; use geoffrey_models::models::player::Player;
use geoffrey_models::models::token::Token; use geoffrey_models::models::token::Token;
pub fn get_player_from_req<T: CommandRequest>(db: &Database, req: &T) -> Result<Option<Player>> { pub fn get_player_from_req<T: GeoffreyParam>(
if let Some(user_id) = req.user_id() { db: &Database,
req: &CommandRequest<T>,
) -> Result<Option<Player>> {
if let Some(user_id) = &req.user_id {
Ok(db Ok(db
.filter(|_, player: &Player| player.has_user_id(&user_id))? .filter(|_, player: &Player| player.has_user_id(user_id))?
.next()) .next())
} else { } else {
Ok(None) Ok(None)
} }
} }
pub fn get_token_from_req<T: CommandRequest>(db: &Database, req: &T) -> Result<Option<Token>> { pub fn get_token_from_req<T: GeoffreyParam>(
db: &Database,
req: &CommandRequest<T>,
) -> Result<Option<Token>> {
Ok(db Ok(db
.filter(|_, token: &Token| token.secret == req.token())? .filter(|_, token: &Token| token.secret == req.token)?
.next()) .next())
} }

View File

@ -70,14 +70,7 @@ async fn run_server(ctx: Arc<Context>) {
} }
fn create_token(ctx: Arc<Context>, perms: Vec<Permissions>) { fn create_token(ctx: Arc<Context>, perms: Vec<Permissions>) {
match AddToken::run_command( match AddToken::run_command(ctx, &AddTokenParams { permissions: perms }, None) {
ctx,
AddTokenParams {
token: "".to_string(),
permissions: perms,
},
None,
) {
Ok(token) => { Ok(token) => {
// Don't log this to keep tokens out of the log // Don't log this to keep tokens out of the log
println!("Added admin token with secret: {}", token.secret) println!("Added admin token with secret: {}", token.secret)

View File

@ -1,4 +1,4 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use async_trait::async_trait; use async_trait::async_trait;
use reqwest::Error; use reqwest::Error;
@ -7,7 +7,7 @@ use serde::Serialize;
use serenity::model::interactions::application_command::ApplicationCommandInteraction; use serenity::model::interactions::application_command::ApplicationCommandInteraction;
use serenity::Error as SerenityError; use serenity::Error as SerenityError;
use geoffrey_models::models::parameters::CommandRequest; use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam};
use geoffrey_models::models::player::UserID; use geoffrey_models::models::player::UserID;
use geoffrey_models::models::response::api_error::GeoffreyAPIError; use geoffrey_models::models::response::api_error::GeoffreyAPIError;
use geoffrey_models::models::response::APIResponse; use geoffrey_models::models::response::APIResponse;
@ -74,8 +74,8 @@ impl From<reqwest::Error> for CommandError {
#[async_trait] #[async_trait]
pub trait BotCommand: Send + 'static { pub trait BotCommand: Send + 'static {
type ApiParams: CommandRequest; type ApiParams: GeoffreyParam;
type ApiResp: Serialize + DeserializeOwned + Send; type ApiResp: Serialize + DeserializeOwned + Send + Debug;
fn command_name() -> String; fn command_name() -> String;
@ -89,7 +89,7 @@ pub trait BotCommand: Send + 'static {
async fn run_api_query( async fn run_api_query(
ctx: GeoffreyContext, ctx: GeoffreyContext,
params: Self::ApiParams, params: CommandRequest<Self::ApiParams>,
) -> Result<APIResponse<Self::ApiResp>, CommandError> { ) -> Result<APIResponse<Self::ApiResp>, CommandError> {
let command_url = Self::command_url(&ctx.cfg.api.base_url); let command_url = Self::command_url(&ctx.cfg.api.base_url);
let resp: APIResponse<Self::ApiResp> = ctx let resp: APIResponse<Self::ApiResp> = ctx
@ -154,7 +154,7 @@ pub trait BotCommand: Send + 'static {
user_id: UserID, user_id: UserID,
command_interact: ApplicationCommandInteraction, command_interact: ApplicationCommandInteraction,
) -> Result<String, CommandError> { ) -> Result<String, CommandError> {
let mut args = Self::process_arguments(command_interact).await?; let args = Self::process_arguments(command_interact).await?;
log::info!( log::info!(
"Running command {}, with args {:?}", "Running command {}, with args {:?}",
@ -162,10 +162,13 @@ pub trait BotCommand: Send + 'static {
args args
); );
args.set_token(ctx.cfg.api.token.clone()); let request = CommandRequest {
args.set_user_id(user_id); token: ctx.cfg.api.token.clone(),
user_id: Some(user_id),
params: args,
};
let resp = Self::run_api_query(ctx, args).await?; let resp = Self::run_api_query(ctx, request).await?;
match resp { match resp {
APIResponse::Response(resp) => Ok(Self::build_response(resp)), APIResponse::Response(resp) => Ok(Self::build_response(resp)),

View File

@ -2,12 +2,22 @@ use crate::error::{GeoffreyDBError, Result};
use crate::migration::do_migration; use crate::migration::do_migration;
use geoffrey_models::models::db_metadata::DBMetadata; use geoffrey_models::models::db_metadata::DBMetadata;
use geoffrey_models::GeoffreyDatabaseModel; use geoffrey_models::GeoffreyDatabaseModel;
use sled::IVec;
use std::convert::TryInto; use std::convert::TryInto;
use std::path::Path; use std::path::Path;
const DB_VERSION: u64 = 3; const DB_VERSION: u64 = 3;
const DB_METADATA_ID: u64 = 1; const DB_METADATA_ID: u64 = 1;
fn option_bytes_to_model<T: GeoffreyDatabaseModel>(bytes: Option<IVec>, id: u64) -> Result<T> {
if let Some(bytes) = bytes {
Ok(T::try_from_bytes(&bytes)?)
} else {
log::debug!("{} of id {} was not found in the database", T::tree(), id);
Err(GeoffreyDBError::NotFound)
}
}
pub struct Database { pub struct Database {
pub(crate) db: sled::Db, pub(crate) db: sled::Db,
} }
@ -66,14 +76,7 @@ impl Database {
T: GeoffreyDatabaseModel, T: GeoffreyDatabaseModel,
{ {
let tree = self.get_tree::<T>()?; let tree = self.get_tree::<T>()?;
let id_bytes = id.to_be_bytes(); option_bytes_to_model(tree.get(id.to_be_bytes())?, id)
if let Some(bytes) = tree.get(id_bytes)? {
Ok(T::try_from_bytes(&bytes)?)
} else {
log::debug!("{} of id {} was not found in the database", T::tree(), id);
Err(GeoffreyDBError::NotFound)
}
} }
pub fn clear_tree<T>(&self) -> Result<()> pub fn clear_tree<T>(&self) -> Result<()>
@ -110,6 +113,14 @@ impl Database {
})) }))
} }
pub fn remove<T>(&self, id: u64) -> Result<T>
where
T: GeoffreyDatabaseModel,
{
let tree = self.db.open_tree(T::tree())?;
option_bytes_to_model(tree.remove(id.to_be_bytes())?, id)
}
pub fn tree_iter<T>(&self) -> Result<sled::Iter> pub fn tree_iter<T>(&self) -> Result<sled::Iter>
where where
T: GeoffreyDatabaseModel, T: GeoffreyDatabaseModel,
@ -228,6 +239,21 @@ mod tests {
cleanup(); cleanup();
} }
#[test]
fn test_remove() {
let _lock = LOCK.lock().unwrap();
cleanup();
let player = Player::new("CoolZero123", UserID::DiscordUUID { discord_uuid: 0u64 });
let p2 = DB.insert::<Player>(player.clone()).unwrap();
let p3 = DB.remove::<Player>(p2.id.unwrap()).unwrap();
assert!(DB.get::<Player>(p3.id.unwrap()).is_err());
assert_eq!(p3.id.unwrap(), p2.id.unwrap());
cleanup();
}
#[test] #[test]
fn test_insert_speed() { fn test_insert_speed() {
let _lock = LOCK.lock().unwrap(); let _lock = LOCK.lock().unwrap();

View File

@ -1,11 +1,8 @@
use crate::models::parameters::CommandRequest; use crate::models::parameters::GeoffreyParam;
use crate::models::player::UserID;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AddItemParams { pub struct AddItemParams {
pub token: String,
pub user_id: UserID,
pub item_name: String, pub item_name: String,
pub price: u32, pub price: u32,
pub quantity: u32, pub quantity: u32,
@ -15,8 +12,6 @@ pub struct AddItemParams {
impl AddItemParams { impl AddItemParams {
pub fn new(item_name: String, price: u32, quantity: u32, shop: String) -> Self { pub fn new(item_name: String, price: u32, quantity: u32, shop: String) -> Self {
Self { Self {
token: Default::default(),
user_id: Default::default(),
item_name, item_name,
price, price,
quantity, quantity,
@ -25,20 +20,4 @@ impl AddItemParams {
} }
} }
impl CommandRequest for AddItemParams { impl GeoffreyParam for AddItemParams {}
fn token(&self) -> String {
self.token.clone()
}
fn user_id(&self) -> Option<UserID> {
Some(self.user_id.clone())
}
fn set_token(&mut self, token: String) {
self.token = token;
}
fn set_user_id(&mut self, user_id: UserID) {
self.user_id = user_id;
}
}

View File

@ -1,13 +1,10 @@
use crate::models::locations::LocationType; use crate::models::locations::LocationType;
use crate::models::parameters::CommandRequest; use crate::models::parameters::GeoffreyParam;
use crate::models::player::UserID;
use crate::models::{Portal, Position}; use crate::models::{Portal, Position};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AddLocationParams { pub struct AddLocationParams {
pub token: String,
pub user_id: UserID,
pub name: String, pub name: String,
pub position: Position, pub position: Position,
pub loc_type: LocationType, pub loc_type: LocationType,
@ -22,8 +19,6 @@ impl AddLocationParams {
portal: Option<Portal>, portal: Option<Portal>,
) -> Self { ) -> Self {
Self { Self {
token: Default::default(),
user_id: Default::default(),
name, name,
position, position,
loc_type, loc_type,
@ -32,20 +27,4 @@ impl AddLocationParams {
} }
} }
impl CommandRequest for AddLocationParams { impl GeoffreyParam for AddLocationParams {}
fn token(&self) -> String {
self.token.clone()
}
fn user_id(&self) -> Option<UserID> {
Some(self.user_id.clone())
}
fn set_user_id(&mut self, user_id: UserID) {
self.user_id = user_id;
}
fn set_token(&mut self, token: String) {
self.token = token;
}
}

View File

@ -1,28 +1,16 @@
use crate::models::parameters::CommandRequest; use crate::models::parameters::GeoffreyParam;
use crate::models::token::Permissions; use crate::models::token::Permissions;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AddTokenParams { pub struct AddTokenParams {
pub token: String,
pub permissions: Vec<Permissions>, pub permissions: Vec<Permissions>,
} }
impl AddTokenParams { impl AddTokenParams {
fn new(permissions: Vec<Permissions>) -> Self { fn new(permissions: Vec<Permissions>) -> Self {
Self { Self { permissions }
token: Default::default(),
permissions,
}
} }
} }
impl CommandRequest for AddTokenParams { impl GeoffreyParam for AddTokenParams {}
fn token(&self) -> String {
self.token.clone()
}
fn set_token(&mut self, token: String) {
self.token = token;
}
}

View File

@ -0,0 +1,15 @@
use crate::models::parameters::GeoffreyParam;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DeleteParams {
pub location: String,
}
impl DeleteParams {
pub fn new(location: String) -> Self {
Self { location }
}
}
impl GeoffreyParam for DeleteParams {}

View File

@ -1,27 +1,15 @@
use crate::models::parameters::CommandRequest; use crate::models::parameters::GeoffreyParam;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FindParams { pub struct FindParams {
pub token: String,
pub query: String, pub query: String,
} }
impl FindParams { impl FindParams {
pub fn new(query: String) -> Self { pub fn new(query: String) -> Self {
Self { Self { query }
token: Default::default(),
query,
}
} }
} }
impl CommandRequest for FindParams { impl GeoffreyParam for FindParams {}
fn token(&self) -> String {
self.token.clone()
}
fn set_token(&mut self, token: String) {
self.token = token;
}
}

View File

@ -1,43 +1,22 @@
pub mod add_item_params; pub mod add_item_params;
pub mod add_location_params; pub mod add_location_params;
pub mod add_token_params; pub mod add_token_params;
pub mod delete_params;
pub mod find_params; pub mod find_params;
pub mod register_params; pub mod register_params;
pub mod selling_params; pub mod selling_params;
pub mod set_portal_params; pub mod set_portal_params;
use crate::models::player::{Player, UserID}; use crate::models::player::UserID;
use crate::models::token::{Permissions, Token};
use crate::models::CommandLevel;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
pub trait CommandRequest: pub trait GeoffreyParam: Serialize + DeserializeOwned + Debug + Clone + Send + Sync {}
Serialize + DeserializeOwned + Debug + Clone + Send + 'static + Sync
{
fn token(&self) -> String;
fn user_id(&self) -> Option<UserID> {
None
}
fn set_token(&mut self, token: String); #[derive(Serialize, Deserialize, Debug, Clone)]
fn set_user_id(&mut self, _: UserID) {} pub struct CommandRequest<T> {
pub token: String,
fn check_permission( pub user_id: Option<UserID>,
&self, pub params: T,
player: &Player,
command_level: &CommandLevel,
token: &Token,
) -> bool {
if player.auth_level >= *command_level {
if *command_level == CommandLevel::ADMIN {
token.check_permission(Permissions::Admin)
} else {
true
}
} else {
false
}
}
} }

View File

@ -1,34 +1,17 @@
use crate::models::parameters::CommandRequest; use crate::models::parameters::GeoffreyParam;
use crate::models::player::UserID; use crate::models::player::UserID;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RegisterParameters { pub struct RegisterParameters {
pub token: String,
pub new_user_id: UserID,
pub username: String, pub username: String,
pub user_id: UserID,
} }
impl RegisterParameters { impl RegisterParameters {
pub fn new(username: String) -> Self { pub fn new(username: String, user_id: UserID) -> Self {
RegisterParameters { RegisterParameters { username, user_id }
token: Default::default(),
new_user_id: Default::default(),
username,
}
} }
} }
impl CommandRequest for RegisterParameters { impl GeoffreyParam for RegisterParameters {}
fn token(&self) -> String {
self.token.clone()
}
fn set_user_id(&mut self, user_id: UserID) {
self.new_user_id = user_id;
}
fn set_token(&mut self, token: String) {
self.token = token;
}
}

View File

@ -1,5 +1,4 @@
use crate::models::parameters::CommandRequest; use crate::models::parameters::GeoffreyParam;
use crate::models::player::UserID;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::str::FromStr; use std::str::FromStr;
@ -35,7 +34,7 @@ impl FromStr for ItemSort {
} }
} }
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
pub enum Order { pub enum Order {
High, High,
Low, Low,
@ -68,7 +67,6 @@ impl FromStr for Order {
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SellingParams { pub struct SellingParams {
pub token: String,
pub query: String, pub query: String,
pub sort: Option<ItemSort>, pub sort: Option<ItemSort>,
pub order: Option<Order>, pub order: Option<Order>,
@ -76,25 +74,8 @@ pub struct SellingParams {
impl SellingParams { impl SellingParams {
pub fn new(query: String, sort: Option<ItemSort>, order: Option<Order>) -> Self { pub fn new(query: String, sort: Option<ItemSort>, order: Option<Order>) -> Self {
Self { Self { query, sort, order }
token: Default::default(),
query,
sort,
order,
}
} }
} }
impl CommandRequest for SellingParams { impl GeoffreyParam for SellingParams {}
fn token(&self) -> String {
self.token.clone()
}
fn user_id(&self) -> Option<UserID> {
None
}
fn set_token(&mut self, token: String) {
self.token = token;
}
}

View File

@ -1,41 +1,17 @@
use crate::models::parameters::CommandRequest; use crate::models::parameters::GeoffreyParam;
use crate::models::player::UserID;
use crate::models::Portal; use crate::models::Portal;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SetPortalParams { pub struct SetPortalParams {
pub token: String,
pub user_id: UserID,
pub loc_name: String, pub loc_name: String,
pub portal: Portal, pub portal: Portal,
} }
impl SetPortalParams { impl SetPortalParams {
pub fn new(loc_name: String, portal: Portal) -> Self { pub fn new(loc_name: String, portal: Portal) -> Self {
Self { Self { loc_name, portal }
token: Default::default(),
user_id: Default::default(),
loc_name,
portal,
}
} }
} }
impl CommandRequest for SetPortalParams { impl GeoffreyParam for SetPortalParams {}
fn token(&self) -> String {
self.token.clone()
}
fn user_id(&self) -> Option<UserID> {
Some(self.user_id.clone())
}
fn set_user_id(&mut self, user_id: UserID) {
self.user_id = user_id;
}
fn set_token(&mut self, token: String) {
self.token = token;
}
}

View File

@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::TryFrom; use std::convert::TryFrom;
#[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialOrd, PartialEq, Copy)]
pub enum Permissions { pub enum Permissions {
ModelGet = 0, ModelGet = 0,
ModelPost, ModelPost,