From 7bf4d9954a9dd02dabbdc9dec74ce7bc536660dc Mon Sep 17 00:00:00 2001 From: ntr Date: Wed, 10 Jul 2019 13:12:32 +1000 Subject: [PATCH] reimage --- client/src/socket.jsx | 2 +- server/src/account.rs | 342 +++++++++++++++++++++------------------- server/src/construct.rs | 36 ++++- server/src/game.rs | 13 +- server/src/img.rs | 2 +- server/src/instance.rs | 4 +- server/src/mtx.rs | 96 ++++++++--- server/src/net.rs | 12 +- server/src/payments.rs | 14 +- server/src/rpc.rs | 29 +++- server/src/ws.rs | 3 +- 11 files changed, 336 insertions(+), 217 deletions(-) diff --git a/client/src/socket.jsx b/client/src/socket.jsx index 8d9c71f0..8fb26a42 100644 --- a/client/src/socket.jsx +++ b/client/src/socket.jsx @@ -141,7 +141,7 @@ function createSocket(events) { function sendMtxApply(constructId, mtx) { send({ method: 'mtx_apply', params: { construct_id: constructId, mtx } }); - events.clearMtxActive(); + // events.clearMtxActive(); } // ------------- diff --git a/server/src/account.rs b/server/src/account.rs index 8e1d4c9f..a310c595 100644 --- a/server/src/account.rs +++ b/server/src/account.rs @@ -27,174 +27,194 @@ pub struct Account { pub subscribed: bool, } -impl Account { - pub fn select(tx: &mut Transaction, id: Uuid) -> Result { - let query = " - SELECT id, name, credits, subscribed - FROM accounts - WHERE id = $1; - "; +pub fn select(tx: &mut Transaction, id: Uuid) -> Result { + let query = " + SELECT id, name, credits, subscribed + FROM accounts + WHERE id = $1; + "; - let result = tx - .query(query, &[&id])?; + let result = tx + .query(query, &[&id])?; - let row = result.iter().next() - .ok_or(format_err!("account not found {:?}", id))?; + let row = result.iter().next() + .ok_or(format_err!("account not found {:?}", id))?; - let db_credits: i64 = row.get(2); - let credits = u32::try_from(db_credits) - .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; + let db_credits: i64 = row.get(2); + let credits = u32::try_from(db_credits) + .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; - let subscribed: bool = row.get(3); - - Ok(Account { id, name: row.get(1), credits, subscribed }) - } - - pub fn from_token(tx: &mut Transaction, token: String) -> Result { - let query = " - SELECT id, name, subscribed, credits - FROM accounts - WHERE token = $1 - AND token_expiry > now(); - "; - - let result = tx - .query(query, &[&token])?; - - let row = result.iter().next() - .ok_or(err_msg("invalid token"))?; - - let id: Uuid = row.get(0); - let name: String = row.get(1); - let subscribed: bool = row.get(2); - let db_credits: i64 = row.get(3); - - let credits = u32::try_from(db_credits) - .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; - - Ok(Account { id, name, credits, subscribed }) - } - - pub fn login(tx: &mut Transaction, name: &String, password: &String) -> Result { - let query = " - SELECT id, password, name, credits, subscribed - FROM accounts - WHERE name = $1 - "; - - let result = tx - .query(query, &[&name])?; - - let row = match result.iter().next() { - Some(row) => row, - None => { - let mut rng = thread_rng(); - let garbage: String = iter::repeat(()) - .map(|()| rng.sample(Alphanumeric)) - .take(64) - .collect(); - - // verify garbage to prevent timing attacks - verify(garbage.clone(), &garbage).ok(); - return Err(err_msg("account not found")); - }, - }; - - let id: Uuid = row.get(0); - let hash: String = row.get(1); - let name: String = row.get(2); - let db_credits: i64 = row.get(3); - let subscribed: bool = row.get(4); - - if !verify(password, &hash)? { - return Err(err_msg("password does not match")); - } - - let credits = u32::try_from(db_credits) - .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; - - Ok(Account { id, name, credits, subscribed }) - } - - pub fn new_token(tx: &mut Transaction, id: Uuid) -> Result { - let mut rng = thread_rng(); - let token: String = iter::repeat(()) - .map(|()| rng.sample(Alphanumeric)) - .take(64) - .collect(); - - // update token - let query = " - UPDATE accounts - SET token = $1, updated_at = now(), token_expiry = now() + interval '1 week' - WHERE id = $2 - RETURNING id, name; - "; - - let result = tx - .query(query, &[&token, &id])?; - - let row = result.iter().next() - .ok_or(format_err!("account not updated {:?}", id))?; - - let name: String = row.get(1); - - info!("login account={:?}", name); - - Ok(token) - } - - pub fn add_credits(tx: &mut Transaction, id: Uuid, credits: i64) -> Result { - let query = " - UPDATE accounts - SET credits = credits + $1 - WHERE id = $2 - RETURNING credits, name; - "; - - let result = tx - .query(query, &[&credits, &id])?; - - let row = result.iter().next() - .ok_or(format_err!("account not updated {:?}", id))?; - - println!("{:?}", row); - - let db_credits: i64 = row.get(0); - let total = u32::try_from(db_credits) - .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; - - let name: String = row.get(1); - - info!("account credited name={:?} credited={:?} total={:?}", name, credits, total); - - Ok(name) - } - - pub fn set_subscribed(tx: &mut Transaction, id: Uuid, subscribed: bool) -> Result { - let query = " - UPDATE accounts - SET subscribed = $1 - WHERE id = $2 - RETURNING name; - "; - - let result = tx - .query(query, &[&subscribed, &id])?; - - let row = result.iter().next() - .ok_or(format_err!("account not updated {:?}", id))?; - - let name: String = row.get(0); - - info!("account subscription status updated name={:?} subscribed={:?}", name, subscribed); - - Ok(name) - } + let subscribed: bool = row.get(3); + Ok(Account { id, name: row.get(1), credits, subscribed }) } -pub fn account_create(name: &String, password: &String, code: &String, tx: &mut Transaction) -> Result { +pub fn from_token(tx: &mut Transaction, token: String) -> Result { + let query = " + SELECT id, name, subscribed, credits + FROM accounts + WHERE token = $1 + AND token_expiry > now(); + "; + + let result = tx + .query(query, &[&token])?; + + let row = result.iter().next() + .ok_or(err_msg("invalid token"))?; + + let id: Uuid = row.get(0); + let name: String = row.get(1); + let subscribed: bool = row.get(2); + let db_credits: i64 = row.get(3); + + let credits = u32::try_from(db_credits) + .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; + + Ok(Account { id, name, credits, subscribed }) +} + +pub fn login(tx: &mut Transaction, name: &String, password: &String) -> Result { + let query = " + SELECT id, password, name, credits, subscribed + FROM accounts + WHERE name = $1 + "; + + let result = tx + .query(query, &[&name])?; + + let row = match result.iter().next() { + Some(row) => row, + None => { + let mut rng = thread_rng(); + let garbage: String = iter::repeat(()) + .map(|()| rng.sample(Alphanumeric)) + .take(64) + .collect(); + + // verify garbage to prevent timing attacks + verify(garbage.clone(), &garbage).ok(); + return Err(err_msg("account not found")); + }, + }; + + let id: Uuid = row.get(0); + let hash: String = row.get(1); + let name: String = row.get(2); + let db_credits: i64 = row.get(3); + let subscribed: bool = row.get(4); + + if !verify(password, &hash)? { + return Err(err_msg("password does not match")); + } + + let credits = u32::try_from(db_credits) + .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; + + Ok(Account { id, name, credits, subscribed }) +} + +pub fn new_token(tx: &mut Transaction, id: Uuid) -> Result { + let mut rng = thread_rng(); + let token: String = iter::repeat(()) + .map(|()| rng.sample(Alphanumeric)) + .take(64) + .collect(); + + // update token + let query = " + UPDATE accounts + SET token = $1, updated_at = now(), token_expiry = now() + interval '1 week' + WHERE id = $2 + RETURNING id, name; + "; + + let result = tx + .query(query, &[&token, &id])?; + + let row = result.iter().next() + .ok_or(format_err!("account not updated {:?}", id))?; + + let name: String = row.get(1); + + info!("login account={:?}", name); + + Ok(token) +} + +pub fn credit(tx: &mut Transaction, id: Uuid, credits: i64) -> Result { + let query = " + UPDATE accounts + SET credits = credits + $1 + WHERE id = $2 + RETURNING credits, name; + "; + + let result = tx + .query(query, &[&credits, &id])?; + + let row = result.iter().next() + .ok_or(format_err!("account not updated {:?}", id))?; + + println!("{:?}", row); + + let db_credits: i64 = row.get(0); + let total = u32::try_from(db_credits) + .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; + + let name: String = row.get(1); + + info!("account credited name={:?} credited={:?} total={:?}", name, credits, total); + + Ok(name) +} + +pub fn debit(tx: &mut Transaction, id: Uuid, credits: i64) -> Result { + let query = " + UPDATE accounts + SET credits = credits - $1 + WHERE id = $2 + RETURNING id, name, credits, subscribed + "; + + let result = tx + .query(query, &[&credits, &id])?; + + let row = result.iter().next() + .ok_or(format_err!("account not found {:?}", id))?; + + let db_credits: i64 = row.get(2); + let credits = u32::try_from(db_credits) + .or(Err(format_err!("user {:?} has unparsable balance {:?}", id, db_credits)))?; + + let subscribed: bool = row.get(3); + + Ok(Account { id, name: row.get(1), credits, subscribed }) +} + +pub fn set_subscribed(tx: &mut Transaction, id: Uuid, subscribed: bool) -> Result { + let query = " + UPDATE accounts + SET subscribed = $1 + WHERE id = $2 + RETURNING name; + "; + + let result = tx + .query(query, &[&subscribed, &id])?; + + let row = result.iter().next() + .ok_or(format_err!("account not updated {:?}", id))?; + + let name: String = row.get(0); + + info!("account subscription status updated name={:?} subscribed={:?}", name, subscribed); + + Ok(name) +} + +pub fn create(name: &String, password: &String, code: &String, tx: &mut Transaction) -> Result { if password.len() < PASSWORD_MIN_LEN { return Err(err_msg("password must be at least 12 characters")); } diff --git a/server/src/construct.rs b/server/src/construct.rs index 3f2b04c0..61951553 100644 --- a/server/src/construct.rs +++ b/server/src/construct.rs @@ -12,7 +12,7 @@ use skill::{Skill, Cast, Immunity, Disable, Event}; use effect::{Cooldown, Effect, Colour}; use spec::{Spec}; use item::{Item}; -use img::{img_molecular_create}; +use img::{img_molecular_write}; #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Colours { @@ -247,6 +247,11 @@ impl Construct { self } + pub fn new_img(mut self) -> Construct { + self.img = Uuid::new_v4(); + self + } + pub fn learn(mut self, s: Skill) -> Construct { self.skills.push(ConstructSkill::new(s)); self.colours = Colours::from_construct(&self); @@ -835,7 +840,28 @@ pub fn construct_get(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result let result = result.iter().next().ok_or(format_err!("construct {:} not found", id))?; let construct_bytes: Vec = result.get(0); - let construct = from_slice::(&construct_bytes).or_else(|_| construct_recover(construct_bytes, tx))?; + let construct = from_slice::(&construct_bytes) + .or_else(|_| construct_recover(construct_bytes, tx))?; + + return Ok(construct); +} + +pub fn construct_select(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result { + let query = " + SELECT data + FROM constructs + WHERE id = $1 + AND account = $2 + FOR UPDATE; + "; + + let result = tx + .query(query, &[&id, &account_id])?; + + let result = result.iter().next().ok_or(format_err!("construct {:} not found", id))?; + let construct_bytes: Vec = result.get(0); + let construct = from_slice::(&construct_bytes) + .or_else(|_| construct_recover(construct_bytes, tx))?; return Ok(construct); } @@ -858,13 +884,13 @@ pub fn construct_spawn(tx: &mut Transaction, params: ConstructSpawnParams, accou let _returned = result.iter().next().ok_or(err_msg("no row returned"))?; - img_molecular_create(construct.img)?; + img_molecular_write(construct.img)?; info!("spawned construct account={:} construct={:?}", account, construct); return Ok(construct); } -pub fn construct_write(construct: Construct, tx: &mut Transaction) -> Result { +pub fn construct_write(tx: &mut Transaction, construct: Construct) -> Result { let construct_bytes = to_vec(&construct)?; let query = " @@ -895,7 +921,7 @@ pub fn construct_recover(construct_bytes: Vec, tx: &mut Transaction) -> Resu info!("recovered construct {:?}", c.name); - return construct_write(construct, tx); + return construct_write(tx, construct); } #[cfg(test)] diff --git a/server/src/game.rs b/server/src/game.rs index 3a5e3835..da93c867 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -1319,13 +1319,12 @@ mod tests { let x_construct = x_player.constructs[0].clone(); let y_construct = x_player.constructs[1].clone(); - game.add_skill(i_player.id, i_construct.id, Some(x_construct.id), Skill::Attack).unwrap(); - game.add_skill(i_player.id, j_construct.id, Some(x_construct.id), Skill::Attack).unwrap(); - game.add_skill(x_player.id, x_construct.id, Some(i_construct.id), Skill::Attack).unwrap(); - game.add_skill(x_player.id, y_construct.id, Some(i_construct.id), Skill::Attack).unwrap(); - - game.player_ready(i_player.id).unwrap(); - game.player_ready(x_player.id).unwrap(); + game.add_skill(i_player.id, i_construct.id, Some(x_construct.id), Skill::Attack).unwrap() + .add_skill(i_player.id, j_construct.id, Some(x_construct.id), Skill::Attack).unwrap() + .add_skill(x_player.id, x_construct.id, Some(i_construct.id), Skill::Attack).unwrap() + .add_skill(x_player.id, y_construct.id, Some(i_construct.id), Skill::Attack).unwrap() + .player_ready(i_player.id).unwrap() + .player_ready(x_player.id).unwrap(); assert!(game.skill_phase_finished()); game = game.resolve_phase_start(); diff --git a/server/src/img.rs b/server/src/img.rs index 3db5aba8..ce1b8ab4 100644 --- a/server/src/img.rs +++ b/server/src/img.rs @@ -5,7 +5,7 @@ use std::fs::copy; use failure::Error; use failure::err_msg; -pub fn img_molecular_create(id: Uuid) -> Result { +pub fn img_molecular_write(id: Uuid) -> Result { let mut rng = thread_rng(); for _i in 0..100 { diff --git a/server/src/instance.rs b/server/src/instance.rs index 3927a42b..9d30d29f 100644 --- a/server/src/instance.rs +++ b/server/src/instance.rs @@ -22,7 +22,7 @@ use game::{Game, Phase, game_get, game_write}; use item::{Item}; use rpc::{RpcResult}; use names::{name}; -use img::{img_molecular_create}; +use img::{img_molecular_write}; #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] enum InstancePhase { @@ -708,7 +708,7 @@ pub fn instance_new(params: InstanceLobbyParams, tx: &mut Transaction, account: // generate bot imgs only in the real world for c in bot.constructs.iter() { - img_molecular_create(c.img)?; + img_molecular_write(c.img)?; } let mut instance = Instance::new() diff --git a/server/src/mtx.rs b/server/src/mtx.rs index d938efc0..bc76ddd0 100644 --- a/server/src/mtx.rs +++ b/server/src/mtx.rs @@ -1,3 +1,4 @@ +use std::convert::TryFrom; use uuid::Uuid; // use rand::prelude::*; @@ -7,6 +8,12 @@ use postgres::transaction::Transaction; use failure::Error; use failure::err_msg; +use account; +use account::Account; + +use construct::{Construct, construct_select, construct_write}; +use img::{img_molecular_write}; + pub const FREE_MTX: [MtxVariant; 2] = [ MtxVariant::Rename, MtxVariant::Reimage, @@ -20,6 +27,25 @@ pub enum MtxVariant { ArchitectureInvader, } +impl MtxVariant { + fn to_sql(&self) -> String { + format!("{:?}", *self) + } +} + +impl TryFrom for MtxVariant { + type Error = Error; + fn try_from(v: String) -> Result { + match v.as_ref() { + "Rename" => Ok(MtxVariant::Rename), + "Reimage" => Ok(MtxVariant::Reimage), + "ArchitectureMolecular" => Ok(MtxVariant::ArchitectureMolecular), + "ArchitectureInvader" => Ok(MtxVariant::ArchitectureInvader), + _ => Err(format_err!("mtx variant not found variant={:?}", v)), + } + } +} + #[derive(Debug,Copy,Clone,Serialize,Deserialize)] pub struct Mtx { id: Uuid, @@ -27,6 +53,52 @@ pub struct Mtx { variant: MtxVariant, } +pub fn apply(tx: &mut Transaction, variant: MtxVariant, construct_id: Uuid, account: Uuid) -> Result { + let mtx = select(tx, variant, account)?; + let construct = construct_select(tx, construct_id, account)?; + + match mtx.variant { + MtxVariant::Reimage => reimage(tx, construct)?, + _ => unimplemented!(), + }; + + return account::debit(tx, account, 1); +} + +pub fn reimage(tx: &mut Transaction, mut construct: Construct) -> Result { + construct = construct.new_img(); + + img_molecular_write(construct.img)?; + + construct = construct_write(tx, construct)?; + + Ok(construct) +} + +pub fn select(tx: &mut Transaction, variant: MtxVariant, account: Uuid) -> Result { + let query = " + SELECT id, account, variant + FROM mtx + WHERE account = $1 + AND variant = $2 + FOR UPDATE; + "; + + let result = tx + .query(query, &[&account, &variant.to_sql()])?; + + if let Some(row) = result.iter().next() { + let id: Uuid = row.get(0); + let account: Uuid = row.get(1); + let v_str: String = row.get(2); + let variant = MtxVariant::try_from(v_str)?; + + Ok(Mtx { id, account, variant }) + } else { + Err(format_err!("mtx not found account={:?} variant={:?}", account, variant)) + } +} + impl Mtx { pub fn new(variant: MtxVariant, account: Uuid) -> Mtx { match variant { @@ -89,7 +161,7 @@ impl Mtx { "; let result = tx - .query(query, &[&self.id, &self.account, &format!("{:?}", self.variant)])?; + .query(query, &[&self.id, &self.account, &self.variant.to_sql()])?; result.iter().next().ok_or(err_msg("mtx not written"))?; @@ -117,26 +189,4 @@ impl Mtx { // return Ok(self); // } - - pub fn select(tx: &mut Transaction, id: Uuid, account: Uuid) -> Result, Error> { - let query = " - SELECT data, id - FROM mtx - WHERE account = $1 - AND id = $2 - FOR UPDATE; - "; - - let result = tx - .query(query, &[&account, &id])?; - - if let Some(row) = result.iter().next() { - let bytes: Vec = row.get(0); - Ok(Some(from_slice::(&bytes)?)) - } else { - Err(format_err!("mtx not found {:?}", id)) - } - } - - // actual impl } diff --git a/server/src/net.rs b/server/src/net.rs index f737c849..87952602 100644 --- a/server/src/net.rs +++ b/server/src/net.rs @@ -16,7 +16,7 @@ use rpc::{AccountLoginParams, AccountCreateParams}; use warden::{warden}; use pubsub::{pg_listen}; use ws::{connect}; -use account::{Account, account_create}; +use account; use payments::{post_stripe_event}; pub type Db = PooledConnection; @@ -102,9 +102,9 @@ fn login(state: web::Data, params: web::Json::) -> Re let db = state.pool.get().or(Err(MnmlHttpError::ServerError))?; let mut tx = db.transaction().or(Err(MnmlHttpError::ServerError))?; - match Account::login(&mut tx, ¶ms.name, ¶ms.password) { + match account::login(&mut tx, ¶ms.name, ¶ms.password) { Ok(a) => { - let token = Account::new_token(&mut tx, a.id).or(Err(MnmlHttpError::ServerError))?; + let token = account::new_token(&mut tx, a.id).or(Err(MnmlHttpError::ServerError))?; tx.commit().or(Err(MnmlHttpError::ServerError))?; Ok(login_res(token)) }, @@ -120,9 +120,9 @@ fn logout(r: HttpRequest, state: web::Data) -> Result { let db = state.pool.get().or(Err(MnmlHttpError::ServerError))?; let mut tx = db.transaction().or(Err(MnmlHttpError::ServerError))?; - match Account::from_token(&mut tx, t.value().to_string()) { + match account::from_token(&mut tx, t.value().to_string()) { Ok(a) => { - Account::new_token(&mut tx, a.id).or(Err(MnmlHttpError::Unauthorized))?; + account::new_token(&mut tx, a.id).or(Err(MnmlHttpError::Unauthorized))?; tx.commit().or(Err(MnmlHttpError::ServerError))?; return Ok(logout_res()); }, @@ -137,7 +137,7 @@ fn register(state: web::Data, params: web::Json::) - let db = state.pool.get().or(Err(MnmlHttpError::ServerError))?; let mut tx = db.transaction().or(Err(MnmlHttpError::ServerError))?; - match account_create(¶ms.name, ¶ms.password, ¶ms.code, &mut tx) { + match account::create(¶ms.name, ¶ms.password, ¶ms.code, &mut tx) { Ok(token) => { tx.commit().or(Err(MnmlHttpError::ServerError))?; Ok(login_res(token)) diff --git a/server/src/payments.rs b/server/src/payments.rs index 8c52b754..fe8066e1 100644 --- a/server/src/payments.rs +++ b/server/src/payments.rs @@ -8,7 +8,7 @@ use failure::err_msg; use stripe::{Event, EventObject, CheckoutSession, SubscriptionStatus}; use net::{State, PgPool, MnmlHttpError}; -use account::{Account}; +use account; pub fn subscription_account(tx: &mut Transaction, sub: String) -> Result { let query = " @@ -86,8 +86,8 @@ impl StripeData { // update webhooks will tell us when the subscription changes // see EventObject::Subscription handler below StripeData::Subscription { subscription: _, account, customer: _, checkout: _ } => { - Account::add_credits(tx, *account, CREDITS_SUB_BONUS)?; - Account::set_subscribed(tx, *account, true)?; + account::credit(tx, *account, CREDITS_SUB_BONUS)?; + account::set_subscribed(tx, *account, true)?; Ok(self) }, StripeData::Purchase { account, customer: _, amount, checkout: _ } => { @@ -95,7 +95,7 @@ impl StripeData { .checked_div(CREDITS_COST_CENTS) .expect("credits cost 0"); - Account::add_credits(tx, *account, credits)?; + account::credit(tx, *account, credits)?; Ok(self) }, @@ -153,8 +153,8 @@ fn process_stripe_event(event: Event, pool: &PgPool) -> Result { }; for item in data.iter() { - item.insert(&mut tx)?; - item.side_effects(&mut tx)?; + item.insert(&mut tx)? + .side_effects(&mut tx)?; } }, @@ -171,7 +171,7 @@ fn process_stripe_event(event: Event, pool: &PgPool) -> Result { _ => false, }; - Account::set_subscribed(&mut tx, account, subbed)?; + account::set_subscribed(&mut tx, account, subbed)?; } _ => { error!("unhandled stripe event {:?}", event); diff --git a/server/src/rpc.rs b/server/src/rpc.rs index be22a991..bd0efa78 100644 --- a/server/src/rpc.rs +++ b/server/src/rpc.rs @@ -18,9 +18,11 @@ use instance::{Instance, instance_state, instance_list, instance_new, instance_r use vbox::{vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip}; use item::{Item, ItemInfoCtr, item_info}; +use mtx; + type MnmlWs = ws::WebsocketContext; -pub fn receive(data: Vec, db: &Db, _client: &mut MnmlWs, begin: Instant, account: Option<&Account>) -> Result { +pub fn receive(data: Vec, db: &Db, client: &mut MnmlWs, begin: Instant, account: Option<&Account>) -> Result { // cast the msg to this type to receive method name match from_slice::(&data) { Ok(v) => { @@ -68,6 +70,8 @@ pub fn receive(data: Vec, db: &Db, _client: &mut MnmlWs, begin: Instant, acc "instance_new" => handle_instance_new(data, &mut tx, account), "instance_state" => handle_instance_state(data, &mut tx, account), + "mtx_apply" => handle_mtx_apply(data, &mut tx, client, account), + "vbox_accept" => handle_vbox_accept(data, &mut tx, account), "vbox_apply" => handle_vbox_apply(data, &mut tx, account), "vbox_combine" => handle_vbox_combine(data, &mut tx, account), @@ -129,9 +133,9 @@ fn handle_construct_delete(data: Vec, tx: &mut Transaction, account: &Accoun Ok(RpcResult::AccountConstructs(account_constructs(tx, &account)?)) } -// fn handle_account_create(data: Vec, tx: &mut Transaction) -> Result { +// fn handle_account::create(data: Vec, tx: &mut Transaction) -> Result { // let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; -// let account = account_create(msg.params, tx)?; +// let account = account::create(msg.params, tx)?; // Ok(RpcResult::Account(account)) // } @@ -177,6 +181,13 @@ fn handle_instance_state(data: Vec, tx: &mut Transaction, account: &Account) } } +fn handle_mtx_apply(data: Vec, tx: &mut Transaction, client: &mut MnmlWs, account: &Account) -> Result { + let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; + mtx::apply(tx, msg.params.mtx, msg.params.construct_id, account.id)?; + + Ok(RpcResult::AccountConstructs(account_constructs(tx, &account)?)) +} + fn handle_vbox_accept(data: Vec, tx: &mut Transaction, account: &Account) -> Result { let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; Ok(RpcResult::InstanceState(vbox_accept(msg.params, tx, &account)?)) @@ -361,6 +372,18 @@ pub struct InstanceStateParams { pub instance_id: Uuid, } +#[derive(Debug,Clone,Serialize,Deserialize)] +struct MtxApplyMsg { + method: String, + params: MtxApplyParams, +} + +#[derive(Debug,Clone,Serialize,Deserialize)] +pub struct MtxApplyParams { + pub construct_id: Uuid, + pub mtx: mtx::MtxVariant, +} + #[derive(Debug,Clone,Serialize,Deserialize)] struct VboxAcceptMsg { method: String, diff --git a/server/src/ws.rs b/server/src/ws.rs index faaba91d..c3cc58c6 100644 --- a/server/src/ws.rs +++ b/server/src/ws.rs @@ -9,6 +9,7 @@ use serde_cbor::{to_vec}; use net::{PgPool, State, MnmlHttpError, JsonError}; use rpc::{receive, RpcResult}; +use account; const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); @@ -119,7 +120,7 @@ pub fn connect(r: HttpRequest, state: web::Data, stream: web::Payload) -> Some(t) => { let db = state.pool.get().or(Err(MnmlHttpError::ServerError))?; let mut tx = db.transaction().or(Err(MnmlHttpError::ServerError))?; - match Account::from_token(&mut tx, t.value().to_string()) { + match account::from_token(&mut tx, t.value().to_string()) { Ok(a) => Some(a), Err(_) => None, }