Added user_id checking to commands
+ Refactored to make CommandRequest a trait that all the parameter structs implment + Created handle_command to handle all the preprocessing needed before running the commandmain
parent
b3c0e2dcb0
commit
8e6b652d5e
|
@ -1,19 +1,17 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::helper::get_player_from_req;
|
||||
use crate::Result;
|
||||
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::parameters::CommandRequest;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::sync::Arc;
|
||||
use geoffrey_models::models::player::Player;
|
||||
|
||||
pub struct AddLocation {}
|
||||
|
||||
impl Command for AddLocation {
|
||||
type Req = CommandRequest<AddLocationParams>;
|
||||
type Req = AddLocationParams;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
|
@ -28,22 +26,19 @@ impl Command for AddLocation {
|
|||
CommandLevel::REGISTERED
|
||||
}
|
||||
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req) -> Result<Self::Resp> {
|
||||
if let Some(player) = get_player_from_req(&ctx.db, &req)? {
|
||||
let args = &req.arguments;
|
||||
let location = LocationDb::new(
|
||||
args.name.as_str(),
|
||||
args.position,
|
||||
player.id.unwrap(),
|
||||
args.tunnel.clone(),
|
||||
args.loc_type.into(),
|
||||
);
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req, user: Option<Player>) -> Result<Self::Resp> {
|
||||
let user = user.unwrap();
|
||||
|
||||
let location = ctx.db.insert(location)?;
|
||||
let location = LocationDb::new(
|
||||
req.name.as_str(),
|
||||
req.position,
|
||||
user.id.unwrap(),
|
||||
req.tunnel.clone(),
|
||||
req.loc_type.into(),
|
||||
);
|
||||
|
||||
load_location(&ctx.db, &location).map_err(|err| err.into())
|
||||
} else {
|
||||
Err(GeoffreyAPIError::PlayerNotRegistered)
|
||||
}
|
||||
let location = ctx.db.insert(location)?;
|
||||
|
||||
load_location(&ctx.db, &location).map_err(|err| err.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::Result;
|
|||
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::parameters::CommandRequest;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
|
@ -13,7 +12,7 @@ use std::sync::Arc;
|
|||
pub struct FindCommand {}
|
||||
|
||||
impl Command for FindCommand {
|
||||
type Req = CommandRequest<FindParams>;
|
||||
type Req = FindParams;
|
||||
type Resp = Vec<Location>;
|
||||
|
||||
fn command_name() -> String {
|
||||
|
@ -28,8 +27,8 @@ impl Command for FindCommand {
|
|||
CommandLevel::ALL
|
||||
}
|
||||
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req) -> Result<Self::Resp> {
|
||||
let query = req.arguments.query.to_lowercase();
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req, _: Option<Player>) -> Result<Self::Resp> {
|
||||
let query = req.query.to_lowercase();
|
||||
let players: Vec<u64> = ctx
|
||||
.db
|
||||
.filter(|_, player: &Player| {
|
||||
|
|
|
@ -11,6 +11,11 @@ use std::fmt::Debug;
|
|||
use std::sync::Arc;
|
||||
use warp::filters::BoxedFilter;
|
||||
use warp::Filter;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use crate::helper::get_player_from_req;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::parameters::CommandRequest;
|
||||
|
||||
|
||||
pub mod add_location;
|
||||
pub mod find;
|
||||
|
@ -24,13 +29,44 @@ pub enum RequestType {
|
|||
}
|
||||
|
||||
pub trait Command {
|
||||
type Req: Serialize + DeserializeOwned + Send + 'static + Debug;
|
||||
type Req: CommandRequest;
|
||||
type Resp: Serialize + DeserializeOwned + Send;
|
||||
|
||||
fn command_name() -> String;
|
||||
fn request_type() -> RequestType;
|
||||
fn command_level() -> CommandLevel;
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req) -> Result<Self::Resp>;
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req, user: Option<Player>) -> Result<Self::Resp>;
|
||||
|
||||
fn user_is_authorized(user: &Option<Player>) -> Result<()> {
|
||||
if Self::command_level() == CommandLevel::ALL {
|
||||
Ok(())
|
||||
}
|
||||
else {
|
||||
if let Some(user) = user {
|
||||
if user.auth_level >= Self::command_level() {
|
||||
Ok(())
|
||||
}
|
||||
else {
|
||||
Err(GeoffreyAPIError::PermissionInsufficient)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Err(GeoffreyAPIError::PlayerNotRegistered)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_command<T: Command>(ctx: Arc<Context>, req: T::Req) -> Result<T::Resp> {
|
||||
log::info!("Running command {}", T::command_name());
|
||||
log::debug!("Request: {:?}", req);
|
||||
|
||||
let user = get_player_from_req(&ctx.db, &req)?;
|
||||
|
||||
match T::user_is_authorized(&user) {
|
||||
Ok(_) => T::run_command(ctx, req, user),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_return)]
|
||||
|
@ -39,10 +75,7 @@ pub fn create_command_filter<T: Command>(ctx: Arc<Context>) -> BoxedFilter<(impl
|
|||
.and(warp::any().map(move || ctx.clone()))
|
||||
.and(warp::body::json())
|
||||
.map(|ctx: Arc<Context>, req: T::Req| {
|
||||
log::info!("Running command {}", T::command_name());
|
||||
log::debug!("Request: {:?}", req);
|
||||
|
||||
let reply = T::run_command(ctx, req);
|
||||
let reply = handle_command::<T>(ctx, req);
|
||||
if let Ok(reply) = reply {
|
||||
log::debug!("Successfully processed command");
|
||||
warp::reply::json(&APIResponse::Response::<T::Resp>(reply))
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use geoffrey_models::models::parameters::register_params::RegisterParameters;
|
||||
use geoffrey_models::models::parameters::CommandRequest;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
|
@ -10,7 +9,7 @@ use std::sync::Arc;
|
|||
pub struct Register {}
|
||||
|
||||
impl Command for Register {
|
||||
type Req = CommandRequest<RegisterParameters>;
|
||||
type Req = RegisterParameters;
|
||||
type Resp = Player;
|
||||
|
||||
fn command_name() -> String {
|
||||
|
@ -25,11 +24,11 @@ impl Command for Register {
|
|||
CommandLevel::ALL
|
||||
}
|
||||
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req) -> crate::Result<Self::Resp> {
|
||||
let player = Player::new(req.arguments.username.as_str(), req.arguments.user_id);
|
||||
fn run_command(ctx: Arc<Context>, req: Self::Req, _: Option<Player>) -> crate::Result<Self::Resp> {
|
||||
let player = Player::new(req.username.as_str(), req.new_user_id);
|
||||
|
||||
ctx.db
|
||||
.insert(player)
|
||||
.map_err(|err| GeoffreyAPIError::DatabaseError(err.to_string()))
|
||||
.map_err(GeoffreyAPIError::from)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ use geoffrey_db::database::Database;
|
|||
use geoffrey_models::models::parameters::CommandRequest;
|
||||
use geoffrey_models::models::player::Player;
|
||||
|
||||
pub fn get_player_from_req<T>(db: &Database, req: &CommandRequest<T>) -> Result<Option<Player>> {
|
||||
if let Some(user_id) = &req.user {
|
||||
pub fn get_player_from_req<T: CommandRequest>(db: &Database, req: &T) -> Result<Option<Player>> {
|
||||
if let Some(user_id) = req.user_id() {
|
||||
Ok(db
|
||||
.filter(|_, player: &Player| player.has_user_id(user_id))?
|
||||
.filter(|_, player: &Player| player.has_user_id(&user_id))?
|
||||
.next())
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,25 @@
|
|||
use crate::models::locations::LocationType;
|
||||
use crate::models::{Position, Tunnel};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::models::player::UserID;
|
||||
use crate::models::parameters::CommandRequest;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct AddLocationParams {
|
||||
token: u64,
|
||||
user_id: UserID,
|
||||
pub name: String,
|
||||
pub position: Position,
|
||||
pub loc_type: LocationType,
|
||||
pub tunnel: Option<Tunnel>,
|
||||
}
|
||||
|
||||
impl CommandRequest for AddLocationParams {
|
||||
fn token(&self) -> u64 {
|
||||
self.token
|
||||
}
|
||||
|
||||
fn user_id(&self) -> Option<UserID> {
|
||||
Some(self.user_id.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::models::parameters::CommandRequest;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct FindParams {
|
||||
pub token: u64,
|
||||
pub query: String,
|
||||
}
|
||||
|
||||
impl CommandRequest for FindParams {
|
||||
fn token(&self) -> u64 {
|
||||
self.token
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,18 +5,14 @@ pub mod register_params;
|
|||
use crate::models::player::{Player, UserID};
|
||||
use crate::models::token::{Permissions, Token};
|
||||
use crate::models::CommandLevel;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Serialize;
|
||||
use std::fmt::Debug;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct CommandRequest<T> {
|
||||
pub user: Option<UserID>,
|
||||
pub arguments: T,
|
||||
pub token: u64,
|
||||
}
|
||||
|
||||
impl<T> CommandRequest<T> {
|
||||
fn has_user_id(&self) -> bool {
|
||||
self.user.is_some()
|
||||
pub trait CommandRequest: Serialize + DeserializeOwned + Debug + Clone + Send + 'static {
|
||||
fn token(&self) -> u64;
|
||||
fn user_id(&self) -> Option<UserID> {
|
||||
None
|
||||
}
|
||||
|
||||
fn check_permission(
|
||||
|
@ -35,4 +31,4 @@ impl<T> CommandRequest<T> {
|
|||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,16 @@
|
|||
use crate::models::player::UserID;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::models::parameters::CommandRequest;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct RegisterParameters {
|
||||
pub token: u64,
|
||||
pub new_user_id: UserID,
|
||||
pub username: String,
|
||||
pub user_id: UserID,
|
||||
}
|
||||
|
||||
impl CommandRequest for RegisterParameters {
|
||||
fn token(&self) -> u64 {
|
||||
self.token
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue