Added set_portal to the API

+ Bumped DB version to 3
+ Renamed "tunnel" to "portal" on the location models
+ Added a new migration
+ Cargo + Clippy
main
Joey Hines 2021-12-07 20:33:25 -07:00
parent 3b8c7fc60f
commit 199516f3cc
No known key found for this signature in database
GPG Key ID: 80F567B5C968F91B
17 changed files with 249 additions and 54 deletions

1
Cargo.lock generated
View File

@ -426,6 +426,7 @@ dependencies = [
"geoffrey_models",
"log",
"rand 0.8.4",
"regex",
"serde 1.0.130",
"serde_json",
"simple_logger",

View File

@ -17,4 +17,5 @@ config = "0.11.0"
structopt = "0.3.21"
log = "0.4.14"
simple_logger = "1.13.0"
rand = "0.8.4"
rand = "0.8.4"
regex = "1.5.4"

View File

@ -3,6 +3,7 @@ use crate::commands::add_location::AddLocation;
use crate::commands::find::FindCommand;
use crate::commands::register::Register;
use crate::commands::selling::Selling;
use crate::commands::set_portal::SetPortal;
use crate::context::Context;
use crate::helper::{get_player_from_req, get_token_from_req};
use crate::Result;
@ -25,6 +26,7 @@ pub mod add_token;
pub mod find;
pub mod register;
pub mod selling;
pub mod set_portal;
#[derive(Debug, Clone, PartialEq)]
#[allow(clippy::upper_case_acronyms)]
@ -122,6 +124,7 @@ pub fn command_filter(
.or(create_command_filter::<AddLocation>(ctx.clone()))
.or(create_command_filter::<Register>(ctx.clone()))
.or(create_command_filter::<Selling>(ctx.clone()))
.or(create_command_filter::<AddItem>(ctx)),
.or(create_command_filter::<AddItem>(ctx.clone()))
.or(create_command_filter::<SetPortal>(ctx)),
)
}

View File

@ -53,7 +53,7 @@ impl Command for Selling {
listing: item.clone(),
shop_name: shop.name.clone(),
shop_loc: shop.position,
portal: shop.tunnel.clone(),
portal: shop.portal.clone(),
})
} else {
None

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::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;
pub struct SetPortal {}
impl Command for SetPortal {
type Req = SetPortalParams;
type Resp = Location;
fn command_name() -> String {
"set_portal".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.loc_name).as_str()).unwrap();
let mut location: LocationDb = ctx
.db
.filter(|_, loc: &LocationDb| {
loc.owners().contains(&user.id.unwrap()) && filter.is_match(loc.name.as_str())
})?
.next()
.ok_or(GeoffreyAPIError::EntryNotFound)?;
location.portal = Some(req.portal);
let location = ctx.db.insert(location)?;
load_location(&ctx.db, &location).map_err(|err| err.into())
}
}

View File

@ -1,15 +1,15 @@
use crate::error::{GeoffreyDBError, Result};
use crate::migration::do_migration;
use geoffrey_models::models::db_metadata::DBMetadata;
use geoffrey_models::GeoffreyDatabaseModel;
use std::convert::TryInto;
use std::path::Path;
use geoffrey_models::models::db_metadata::DBMetadata;
use crate::migration::do_migration;
const DB_VERSION: u64 = 2;
const DB_VERSION: u64 = 3;
const DB_METADATA_ID: u64 = 1;
pub struct Database {
pub(crate) db: sled::Db,
pub(crate) db: sled::Db,
}
impl Database {

View File

@ -1,10 +1,10 @@
use crate::migration::Migration;
use crate::database::Database;
use crate::migration::Migration;
use geoffrey_models::models::locations::LocationDb;
use geoffrey_models::GeoffreyDatabaseModel;
use json::JsonValue;
pub(crate) struct PosAndNetherMigration {}
pub(crate) struct PosAndNetherMigration {}
impl Migration for PosAndNetherMigration {
fn up(db: &Database) -> crate::error::Result<()> {
@ -36,7 +36,7 @@ impl Migration for PosAndNetherMigration {
let (id, loc_ivec) = entry?;
let mut loc = json::parse(std::str::from_utf8(&loc_ivec).unwrap()).unwrap();
loc["position"]["y"] = loc["position"]["z"].clone();
loc["position"]["y"] = loc["position"]["z"].clone();
loc["position"]["z"].clear();
// Clear out the tunnel entry, there is not a great way to convert
@ -46,7 +46,6 @@ impl Migration for PosAndNetherMigration {
}
Ok(())
}
fn version() -> u64 {
@ -57,12 +56,12 @@ impl Migration for PosAndNetherMigration {
#[cfg(test)]
mod tests {
use crate::database::Database;
use std::path::Path;
use crate::migration::migration_2::PosAndNetherMigration;
use crate::migration::Migration;
use geoffrey_models::models::locations::LocationDb;
use geoffrey_models::GeoffreyDatabaseModel;
use sled::IVec;
use crate::migration::migration_2::PosAndNetherMigration;
use crate::migration::Migration;
use std::path::Path;
#[test]
fn test_migration_2() {
@ -70,7 +69,8 @@ mod tests {
let loc_tree = db.db.open_tree(LocationDb::tree()).unwrap();
let old_loc_format = json::parse(r#"{
let old_loc_format = json::parse(
r#"{
"id": 55,
"name": "Test",
"position": {
@ -79,9 +79,13 @@ mod tests {
"dimension": "Overworld"
},
"loc_data": "Base"
}"#).unwrap();
}"#,
)
.unwrap();
loc_tree.insert(IVec::from(vec![55]), old_loc_format.to_string().as_bytes()).unwrap();
loc_tree
.insert(IVec::from(vec![55]), old_loc_format.to_string().as_bytes())
.unwrap();
PosAndNetherMigration::up(&db).unwrap();
@ -95,4 +99,4 @@ mod tests {
std::fs::remove_dir_all("../migration_2_db").unwrap();
}
}
}

View File

@ -0,0 +1,99 @@
use crate::database::Database;
use crate::migration::Migration;
use geoffrey_models::models::locations::LocationDb;
use geoffrey_models::GeoffreyDatabaseModel;
pub(crate) struct TunnelToPortalMigration {}
impl Migration for TunnelToPortalMigration {
fn up(db: &Database) -> crate::error::Result<()> {
let loc_tree = db.db.open_tree(LocationDb::tree())?;
for entry in loc_tree.iter() {
let (id, loc_ivec) = entry?;
let mut loc = json::parse(std::str::from_utf8(&loc_ivec).unwrap()).unwrap();
let tunnel = loc["tunnel"].clone();
loc["portal"] = tunnel;
loc_tree.insert(id, loc.to_string().as_bytes())?;
}
Ok(())
}
fn down(db: &Database) -> crate::error::Result<()> {
let loc_tree = db.db.open_tree(LocationDb::tree())?;
for entry in loc_tree.iter() {
let (id, loc_ivec) = entry?;
let mut loc = json::parse(std::str::from_utf8(&loc_ivec).unwrap()).unwrap();
let portal = loc["portal"].clone();
loc["tunnel"] = portal;
loc_tree.insert(id, loc.to_string().as_bytes())?;
}
Ok(())
}
fn version() -> u64 {
2
}
}
#[cfg(test)]
mod tests {
use crate::database::Database;
use crate::migration::migration_3::TunnelToPortalMigration;
use crate::migration::Migration;
use geoffrey_models::models::locations::LocationDb;
use geoffrey_models::GeoffreyDatabaseModel;
use sled::IVec;
use std::path::Path;
#[test]
fn test_migration_2() {
let db = Database::new(Path::new("../migration_3_db/")).unwrap();
let loc_tree = db.db.open_tree(LocationDb::tree()).unwrap();
let old_loc = json::parse(
r#"{
"id": 55,
"name": "Test",
"position": {
"x": 55,
"y": 55,
"z": 55,
"dimension": "Overworld"
},
"tunnel": {
"x": 8,
"z": 8
},
"loc_data": "Base"
}"#,
)
.unwrap();
loc_tree
.insert(IVec::from(vec![55]), old_loc.to_string().as_bytes())
.unwrap();
TunnelToPortalMigration::up(&db).unwrap();
let new_loc = loc_tree.get(IVec::from(vec![55])).unwrap().unwrap();
let new_loc = json::parse(std::str::from_utf8(&new_loc).unwrap()).unwrap();
assert_eq!(new_loc["portal"]["x"], 8);
assert_eq!(new_loc["portal"]["z"], 8);
drop(db);
std::fs::remove_dir_all("../migration_3_db").unwrap();
}
}

View File

@ -1,9 +1,11 @@
use crate::database::Database;
use crate::error::Result;
use crate::migration::migration_2::PosAndNetherMigration;
use crate::migration::migration_3::TunnelToPortalMigration;
use geoffrey_models::models::db_metadata::DBMetadata;
mod migration_2;
mod migration_3;
trait Migration {
fn up(db: &Database) -> Result<()>;
@ -12,10 +14,11 @@ trait Migration {
}
fn upgrade(db: &Database, current_version: u64, target_version: u64) -> Result<()> {
for ver in current_version+1..=target_version {
for ver in current_version + 1..=target_version {
match ver {
2 => PosAndNetherMigration::up(db)?,
_ => ()
3 => TunnelToPortalMigration::up(db)?,
_ => (),
}
}
@ -25,8 +28,9 @@ fn upgrade(db: &Database, current_version: u64, target_version: u64) -> Result<(
fn downgrade(db: &Database, current_version: u64, target_version: u64) -> Result<()> {
for ver in (target_version..current_version).rev() {
match ver {
2 => PosAndNetherMigration::up(db)?,
_ => ()
2 => PosAndNetherMigration::down(db)?,
3 => TunnelToPortalMigration::down(db)?,
_ => (),
}
}
@ -36,11 +40,11 @@ fn downgrade(db: &Database, current_version: u64, target_version: u64) -> Result
pub fn do_migration(db: &Database, target_version: u64) -> Result<()> {
let current_version = db.version().unwrap_or(0);
#[allow(clippy::comparison_chain)]
if target_version > current_version {
upgrade(db, current_version, target_version)?;
}
else if target_version < current_version {
downgrade(db, current_version, target_version)?;
} else if target_version < current_version {
downgrade(db, current_version, target_version)?;
}
let metadata = DBMetadata {

View File

@ -5,7 +5,6 @@ use std::fmt::Debug;
pub mod models;
pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned + Debug {
fn id(&self) -> Option<u64>;
fn set_id(&mut self, id: u64);

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::GeoffreyDatabaseModel;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
pub struct DBMetadata {
@ -17,5 +17,3 @@ impl GeoffreyDatabaseModel for DBMetadata {
"DBMetadata".to_string()
}
}

View File

@ -6,7 +6,7 @@ use crate::models::locations::market::{Market, MarketDb};
use crate::models::locations::shop::Shop;
use crate::models::locations::town::{Town, TownDb};
use crate::models::player::Player;
use crate::models::{Position, Portal};
use crate::models::{Portal, Position};
use crate::GeoffreyDatabaseModel;
use std::fmt::{Display, Formatter};
use std::str::FromStr;
@ -111,7 +111,7 @@ pub struct LocationDb {
pub name: String,
pub position: Position,
owners: HashSet<u64>,
pub tunnel: Option<Portal>,
pub portal: Option<Portal>,
pub loc_data: LocationDataDb,
}
@ -131,7 +131,7 @@ impl LocationDb {
name: name.to_string(),
position,
owners,
tunnel,
portal: tunnel,
loc_data: loc_type,
}
}
@ -173,7 +173,7 @@ pub struct Location {
pub name: String,
pub position: Position,
pub owners: Vec<Player>,
pub tunnel: Option<Portal>,
pub portal: Option<Portal>,
pub loc_data: LocationData,
}
@ -188,7 +188,7 @@ impl Location {
name: location.name,
position: location.position,
owners,
tunnel: location.tunnel,
portal: location.portal,
loc_data,
}
}
@ -228,7 +228,7 @@ mod tests {
);
let l2 = LocationDb::new(
"teSt",
Position::new(0, 0, 0,Dimension::Overworld),
Position::new(0, 0, 0, Dimension::Overworld),
0u64,
None,
LocationDataDb::Base,

View File

@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::str::FromStr;
pub mod db_metadata;
pub mod item;
pub mod locations;
pub mod meta;
@ -9,7 +10,6 @@ pub mod parameters;
pub mod player;
pub mod response;
pub mod token;
pub mod db_metadata;
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub enum Dimension {
@ -86,40 +86,36 @@ impl Position {
impl Display for Position {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(x={}, y={}, z={}) {} ", self.x, self.y, self.z, self.dimension)
write!(
f,
"(x={}, y={}, z={}) {} ",
self.x, self.y, self.z, self.dimension
)
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Portal {
x: i32,
z: i32
z: i32,
}
impl Portal {
pub fn new(x: i32, z: i32) -> Self {
Self {
x,
z
}
Self { x, z }
}
pub fn direction(&self) -> Direction {
if self.x.abs() > self.z.abs() {
if self.x < 0 {
Direction::West
}
else {
} else {
Direction::East
}
}
else {
if self.z < 0 {
Direction::North
}
else {
Direction::South
}
} else if self.z < 0 {
Direction::North
} else {
Direction::South
}
}
}

View File

@ -1,7 +1,7 @@
use crate::models::locations::LocationType;
use crate::models::parameters::CommandRequest;
use crate::models::player::UserID;
use crate::models::{Position, Portal};
use crate::models::{Portal, Position};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]

View File

@ -4,6 +4,7 @@ pub mod add_token_params;
pub mod find_params;
pub mod register_params;
pub mod selling_params;
pub mod set_portal_params;
use crate::models::player::{Player, UserID};
use crate::models::token::{Permissions, Token};

View File

@ -0,0 +1,41 @@
use crate::models::parameters::CommandRequest;
use crate::models::player::UserID;
use crate::models::Portal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SetPortalParams {
pub token: String,
pub user_id: UserID,
pub loc_name: String,
pub portal: Portal,
}
impl SetPortalParams {
pub fn new(loc_name: String, portal: Portal) -> Self {
Self {
token: Default::default(),
user_id: Default::default(),
loc_name,
portal,
}
}
}
impl CommandRequest 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

@ -1,5 +1,5 @@
use crate::models::item::ItemListing;
use crate::models::{Position, Portal};
use crate::models::{Portal, Position};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Clone)]