acp routing

This commit is contained in:
ntr
2019-08-14 11:31:12 +10:00
parent 99c575ac69
commit f68a12eab8
9 changed files with 193 additions and 49 deletions
+24 -1
View File
@@ -8,7 +8,7 @@ use serde_cbor::{from_slice};
use postgres::transaction::Transaction;
use net::MnmlHttpError;
use http::MnmlHttpError;
use names::{name as generate_name};
use construct::{Construct, construct_recover, construct_spawn};
use instance::{Instance, instance_delete};
@@ -51,6 +51,29 @@ pub fn select(db: &Db, id: Uuid) -> Result<Account, Error> {
Ok(Account { id, name: row.get(1), balance, subscribed })
}
pub fn select_name(db: &Db, name: &String) -> Result<Account, Error> {
let query = "
SELECT id, name, balance, subscribed
FROM accounts
WHERE name = $1;
";
let result = db
.query(query, &[&name])?;
let row = result.iter().next()
.ok_or(format_err!("account not found name={:?}", name))?;
let id: Uuid = row.get(0);
let db_balance: i64 = row.get(2);
let balance = u32::try_from(db_balance)
.or(Err(format_err!("user {:?} has unparsable balance {:?}", name, db_balance)))?;
let subscribed: bool = row.get(3);
Ok(Account { id, name: row.get(1), balance, subscribed })
}
pub fn from_token(db: &Db, token: String) -> Result<Account, Error> {
let query = "
SELECT id, name, subscribed, balance
+84 -9
View File
@@ -9,7 +9,9 @@ use iron::mime::Mime;
use iron::{typemap, BeforeMiddleware,AfterMiddleware};
use persistent::Read;
use router::Router;
use mount::{Mount};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use account;
use pg::PgPool;
@@ -30,6 +32,8 @@ pub enum MnmlHttpError {
Unauthorized,
#[fail(display="bad request")]
BadRequest,
#[fail(display="not found")]
NotFound,
#[fail(display="account name taken or invalid")]
AccountNameNotProvided,
#[fail(display="account name not provided")]
@@ -107,6 +111,8 @@ impl From<MnmlHttpError> for IronError {
MnmlHttpError::InvalidCode |
MnmlHttpError::TokenDoesNotMatch |
MnmlHttpError::Unauthorized => (m_err.compat(), status::Unauthorized),
MnmlHttpError::NotFound => (m_err.compat(), status::NotFound),
};
IronError { error: Box::new(err), response: iron_response(res, m_err.to_string()) }
}
@@ -289,20 +295,89 @@ pub struct State {
impl Key for State { type Value = State; }
pub fn start(pool: PgPool) {
fn account_mount() -> Router {
let mut router = Router::new();
// auth
router.post("/api/account/login", login, "login");
router.post("/api/account/logout", logout, "logout");
router.post("/api/account/register", register, "register");
router.post("/api/account/password", set_password, "set_password");
router.post("/api/account/email", logout, "email");
router.post("login", login, "login");
router.post("logout", logout, "logout");
router.post("register", register, "register");
router.post("password", set_password, "set_password");
router.post("email", logout, "email");
// payments
router.post("/api/payments/stripe", stripe, "stripe");
router
}
fn payment_mount() -> Router {
let mut router = Router::new();
router.post("stripe", stripe, "stripe");
router
}
struct AcpMiddleware;
impl BeforeMiddleware for AcpMiddleware {
fn before(&self, req: &mut Request) -> IronResult<()> {
match req.extensions.get::<account::Account>() {
Some(a) => {
if ["ntr", "mashy"].contains(&a.name.to_ascii_lowercase().as_ref()) {
return Ok(());
}
return Err(IronError::from(MnmlHttpError::Unauthorized));
},
None => Err(IronError::from(MnmlHttpError::Unauthorized)),
}
}
}
#[derive(Debug,Clone,Deserialize)]
struct GetUser {
name: Option<String>,
id: Option<Uuid>,
}
fn acp_user(req: &mut Request) -> IronResult<Response> {
let state = req.get::<Read<State>>().unwrap();
let params = match req.get::<bodyparser::Struct<GetUser>>() {
Ok(Some(b)) => b,
_ => return Err(IronError::from(MnmlHttpError::BadRequest)),
};
let db = state.pool.get().or(Err(MnmlHttpError::DbError))?;
println!("{:?}", params);
let user = match params.id {
Some(id) => account::select(&db, id)
.or(Err(MnmlHttpError::NotFound))?,
None => match params.name {
Some(n) => account::select_name(&db, &n)
.or(Err(MnmlHttpError::NotFound))?,
None => return Err(IronError::from(MnmlHttpError::BadRequest)),
}
};
Ok(iron_response(status::Ok, serde_json::to_string(&user).unwrap()))
}
fn acp_mount() -> Chain {
let mut router = Router::new();
router.post("user", acp_user, "acp_user");
let mut chain = Chain::new(router);
chain.link_before(AcpMiddleware);
chain
}
pub fn start(pool: PgPool) {
let mut mounts = Mount::new();
mounts.mount("/api/account/", account_mount());
mounts.mount("/api/payments/", payment_mount());
mounts.mount("/api/acp/", acp_mount());
let mut chain = Chain::new(mounts);
chain.link(Read::<State>::both(State { pool }));
chain.link_before(Read::<bodyparser::MaxBodyLength>::one(MAX_BODY_LENGTH));
chain.link_before(AuthMiddleware);
+3 -2
View File
@@ -23,6 +23,7 @@ extern crate iron;
extern crate bodyparser;
extern crate persistent;
extern crate router;
extern crate mount;
extern crate cookie;
extern crate ws;
@@ -38,7 +39,7 @@ mod img;
mod mob;
mod mtx;
mod names;
mod net;
mod http;
mod payments;
mod pg;
mod player;
@@ -98,7 +99,7 @@ fn main() {
let pg_pool = pool.clone();
spawn(move || net::start(http_pool));
spawn(move || http::start(http_pool));
spawn(move || warden.listen());
spawn(move || warden::upkeep_tick(warden_tick_tx));
spawn(move || pg::listen(pg_pool, pg_events_tx));
+2 -2
View File
@@ -1,6 +1,6 @@
use std::io::Read;
use net::State;
use http::State;
use iron::prelude::*;
use iron::response::HttpResponse;
use iron::status;
@@ -14,7 +14,7 @@ use failure::err_msg;
use stripe::{Event, EventObject, CheckoutSession, SubscriptionStatus};
use net::{MnmlHttpError};
use http::{MnmlHttpError};
use pg::{PgPool};
use account;
+1 -1
View File
@@ -26,7 +26,7 @@ use pg::{Db};
use pg::{PgPool};
use skill::{Skill, dev_resolve, Resolutions};
use vbox::{vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip};
use net::{AUTH_CLEAR, TOKEN_HEADER};
use http::{AUTH_CLEAR, TOKEN_HEADER};
#[derive(Debug,Clone,Serialize,Deserialize)]
pub enum RpcMessage {