hoppinworld_backend

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

commit 74a6e29b54c3079a61153724be139e59e73f4f7c
parent e1b0523f390d00b4b2b585c2df5ab7b64aa57d21
Author: Joël Lupien (Jojolepro) <jojolepromain@gmail.com>
Date:   Mon, 24 Dec 2018 14:05:55 -0500

map data?

Diffstat:
MCargo.lock | 38++++++++++++++++++++++++++++++++++++++
MCargo.toml | 5+++--
Amigrations/2018-11-04-153437_mapdata/down.sql | 9+++++++++
Amigrations/2018-11-04-153437_mapdata/up.sql | 8++++++++
Msrc/db.rs | 1-
Msrc/endpoint.rs | 37++++++++++++++++++++++++++++++++-----
Msrc/main.rs | 3+++
Msrc/model.rs | 22+++++++++++++++++++++-
Msrc/schema.rs | 5+++++
9 files changed, 119 insertions(+), 9 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -443,6 +443,8 @@ dependencies = [ "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "validator_derive 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -498,6 +500,11 @@ dependencies = [ ] [[package]] +name = "if_chain" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "interpolate_idents" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1307,6 +1314,34 @@ dependencies = [ ] [[package]] +name = "validator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "validator_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.12 (registry+https://github.com/rust-lang/crates.io-index)", + "validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "vcpkg" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1427,6 +1462,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" "checksum hyper-sync-rustls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6df6f419a9f116cc93b5f39a5ded1161e088a2c8424c8fcd1d4049193424a4" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" "checksum interpolate_idents 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "001fa82e9e01b73b7c11450434d0959dcbd46c0debc75c1841280cf3fbc68255" "checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" @@ -1523,6 +1559,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" "checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6" +"checksum validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "236a5eda3df2c877872e98dbc55d497d943792e6405d8fc65bd4f8a5e3b53c99" +"checksum validator_derive 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d360d6f5754972c0c1da14fb3d5580daa31aee566e1e45e2f8d3bf5950ecd3e9" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml @@ -21,4 +21,6 @@ bcrypt = "0.2.0" chrono = "0.4.4" backend_utils = { git = "https://github.com/jojolepro/backend-utils-rs" } lettre = { git = "https://github.com/lettre/lettre", rev = "c988b1760ad8179d9e7f3fb8594d2b86cf2a0a49" } -lettre_email = { git = "https://github.com/lettre/lettre", rev = "c988b1760ad8179d9e7f3fb8594d2b86cf2a0a49" }- \ No newline at end of file +lettre_email = { git = "https://github.com/lettre/lettre", rev = "c988b1760ad8179d9e7f3fb8594d2b86cf2a0a49" } +validator = "0.8.0" +validator_derive = "0.8.0" diff --git a/migrations/2018-11-04-153437_mapdata/down.sql b/migrations/2018-11-04-153437_mapdata/down.sql @@ -0,0 +1,8 @@ +-- This file should undo anything in `up.sql` + +ALTER TABLE map DROP COLUMN mapper; +ALTER TABLE map DROP COLUMN difficulty; +ALTER TABLE map DROP COLUMN categories; +ALTER TABLE map DROP COLUMN tags; + +ALTER TABLE `map` DROP CONSTRAINT `map_fk0`;+ \ No newline at end of file diff --git a/migrations/2018-11-04-153437_mapdata/up.sql b/migrations/2018-11-04-153437_mapdata/up.sql @@ -0,0 +1,7 @@ +-- Your SQL goes here +ALTER TABLE map ADD COLUMN mapper int NOT NULL; +ALTER TABLE map ADD COLUMN difficulty varchar(32) NOT NULL; +ALTER TABLE map ADD COLUMN categories varchar(64) NOT NULL; +ALTER TABLE map ADD COLUMN tags varchar(64) NOT NULL; + +ALTER TABLE `map` ADD CONSTRAINT `map_fk0` FOREIGN KEY (`mapper`) REFERENCES `user`(`id`);+ \ No newline at end of file diff --git a/src/db.rs b/src/db.rs @@ -122,4 +122,3 @@ pub fn segment_scores_from_string(data: &String) -> Option<Vec<f32>> { Some(try_seg_times.map(|e| e.unwrap()).collect::<Vec<_>>()) } } - diff --git a/src/endpoint.rs b/src/endpoint.rs @@ -8,6 +8,7 @@ use rocket_contrib::Json; use rocket::{Outcome, Request}; use lettre_email::EmailBuilder; use lettre::{ClientSecurity, EmailAddress, Envelope, SendableEmail, SmtpClient, Transport, SmtpTransport, SendmailTransport}; +use validator::Validate; pub struct UserLogged { pub user: User, @@ -104,9 +105,12 @@ pub fn login(login: Json<LoginRequest>, db: DbConn) -> Result<Json<LoginResult>, /// Registers a new user using `RegisterData` as json. /// #Test -/// curl -X POST -H "Content-Type: application/json" http://127.0.0.1:27015/register -d '{"name":"test", "email":"test@test.com"}' +/// curl -X POST -H "Content-Type: application/json" https://hoppinworld.net:27015/register -d '{"username":"test", "email":"test@test.com"}' #[post("/register", format = "application/json", data = "<register>")] pub fn register(db: DbConn, register: Json<UserInsert>) -> Result<(), ReturnStatus> { + if let Err(_) = register.validate() { + return Err(ReturnStatus::new(Status::BadRequest).with_message("Failed to validate input data".to_string())); + } match user_add(&db, &*register) { Ok(1) => { let token = Uuid::new_v4(); @@ -184,12 +188,17 @@ pub fn register(db: DbConn, register: Json<UserInsert>) -> Result<(), ReturnStat /// Changes the password of a user using the reset token and the new password (`ChangePassword` as json). /// #Test -/// curl -X POST -H "Content-Type: application/json" http://raidable.ddns.net:27015/changepassword -d '{"token":"uuid", "password":"pass"}' +/// curl -X POST -H "Content-Type: application/json" https://raidable.ddns.net:27015/changepassword -d '{"token":"uuid", "password":"pass"}' #[post("/changepassword", format = "application/json", data = "<data>")] pub fn change_password(db: DbConn, data: Json<ChangePasswordRequest>) -> Result<(), ReturnStatus> { + if data.password.len() < 8 || data.password.len() > 64 { + return Err(ReturnStatus::new(Status::BadRequest).with_message("Password must be between 8 and 64 characters.".to_string())); + } + // TODO: Check expiration date on db match user_from_password_reset_token(&db, &data.token) { Ok(user) => match set_user_password(&db, user.id, &data.password) { + // TODO: Remove all ResetPassword entries from db for user. Ok(_) => Ok(()), Err(e) => { error!("An error occured while changing the user password: {:?}", e); @@ -198,7 +207,7 @@ pub fn change_password(db: DbConn, data: Json<ChangePasswordRequest>) -> Result< }, Err(diesel::result::Error::NotFound) => { info!("Failed attempt to reset password: Token is invalid."); - Err(ReturnStatus::new(Status::BadRequest)) + Err(ReturnStatus::new(Status::BadRequest).with_message("The password reset token is invalid, did it expire?".to_string())) } Err(e) => { error!( @@ -328,10 +337,28 @@ fn map_scores(db: DbConn, mapid: i32) -> Result<Json<Vec<ScoreDisplay>>, ReturnS /// Returns the map info for a specific map #[get("/map/<mapid>")] -fn map_info(db: DbConn, mapid: i32) -> Result<Json<Map>, ReturnStatus> { +fn map_info(db: DbConn, mapid: i32) -> Result<Json<MapDisplay>, ReturnStatus> { match map_from_id(&db, mapid) { Ok(map) => { - Ok(Json(map)) + // Convert Map to MapDisplay + let mapper_name = user_from_id(&db, map.mapper).map(|u| u.username).unwrap_or_else(|_| { + error!("Failed to find user from map creator for map id: {}", map.id); + String::from("???") // Unknown mapper + }); + + let map_display = MapDisplay { + id: map.id, + status: map.status, + name: map.name, + segment_count: map.segment_count, + path: map.path, + mapper: map.mapper, + mapper_name, + difficulty: map.difficulty, + categories: map.categories.split(",").map(|e| e.to_string()).collect(), + tags: map.tags.split(",").map(|e| e.to_string()).collect(), + }; + Ok(Json(map_display)) } Err(diesel::result::Error::NotFound) => { Err(ReturnStatus::new(Status::BadRequest).with_message("Map not found for specified id".to_string())) diff --git a/src/main.rs b/src/main.rs @@ -20,6 +20,9 @@ extern crate chrono; extern crate backend_utils; extern crate lettre; extern crate lettre_email; +extern crate validator; +#[macro_use] +extern crate validator_derive; pub use backend_utils::*; diff --git a/src/model.rs b/src/model.rs @@ -5,6 +5,7 @@ use super::schema::*; use chrono::prelude::*; use diesel::prelude::*; +use validator::Validate; //use super::schema::user; @@ -17,10 +18,11 @@ pub struct User { pub token: Option<String>, } -#[derive(Deserialize, Insertable)] +#[derive(Deserialize, Insertable, Validate)] #[table_name = "user"] pub struct UserInsert { pub username: String, + #[validate(email)] pub email: String, } @@ -125,6 +127,24 @@ pub struct Map { /// Maps that get outdated following updates will be deleted from the servers and the path will be null? /// not sure if this should be the case. pub path: Option<String>, + pub mapper: i32, + pub difficulty: String, + pub categories: String, + pub tags: String, +} + +#[derive(Debug, Serialize)] +pub struct MapDisplay { + pub id: i32, + pub status: String, + pub name: String, + pub segment_count: i32, + pub path: Option<String>, + pub mapper: i32, + pub mapper_name: String, + pub difficulty: String, + pub categories: Vec<String>, + pub tags: Vec<String>, } #[derive(Queryable)] diff --git a/src/schema.rs b/src/schema.rs @@ -13,6 +13,10 @@ table! { name -> Varchar, segment_count -> Integer, path -> Nullable<Varchar>, + mapper -> Integer, + difficulty -> Varchar, + categories -> Varchar, + tags -> Varchar, } } @@ -100,6 +104,7 @@ table! { } } +joinable!(map -> user (mapper)); joinable!(password_reset -> user (userid)); joinable!(replay -> score (scoreid)); joinable!(score -> map (mapid));