Merge branch 'develop' of ssh://mnml.gg:40022/~/mnml into develop
This commit is contained in:
commit
5e5cb1a7b0
@ -12,11 +12,10 @@ const addState = connect(
|
|||||||
} = state;
|
} = state;
|
||||||
function submitLogin(name, password) {
|
function submitLogin(name, password) {
|
||||||
postData('/login', { name, password })
|
postData('/login', { name, password })
|
||||||
.then(res => {
|
.then(res => res.json())
|
||||||
if (!res.ok) return errorToast(res);
|
.then(data => {
|
||||||
res.text()
|
if (!data.success) return errorToast(data.error_message);
|
||||||
})
|
console.log(data.response);
|
||||||
.then(res => {
|
|
||||||
ws.connect();
|
ws.connect();
|
||||||
})
|
})
|
||||||
.catch(error => errorToast(error));
|
.catch(error => errorToast(error));
|
||||||
@ -24,11 +23,10 @@ const addState = connect(
|
|||||||
|
|
||||||
function submitRegister(name, password, code) {
|
function submitRegister(name, password, code) {
|
||||||
postData('/register', { name, password, code })
|
postData('/register', { name, password, code })
|
||||||
.then(res => {
|
.then(res => res.json())
|
||||||
if (!res.ok) return errorToast(res);
|
.then(data => {
|
||||||
res.text()
|
if (!data.success) return errorToast(data.error_message);
|
||||||
})
|
console.log(data.response);
|
||||||
.then(res => {
|
|
||||||
ws.connect();
|
ws.connect();
|
||||||
})
|
})
|
||||||
.catch(error => errorToast(error));
|
.catch(error => errorToast(error));
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use serde_cbor::{from_slice};
|
|||||||
|
|
||||||
use postgres::transaction::Transaction;
|
use postgres::transaction::Transaction;
|
||||||
|
|
||||||
|
use net::MnmlHttpError;
|
||||||
use names::{name as generate_name};
|
use names::{name as generate_name};
|
||||||
use construct::{Construct, construct_recover, construct_spawn};
|
use construct::{Construct, construct_recover, construct_spawn};
|
||||||
use instance::{Instance, instance_delete};
|
use instance::{Instance, instance_delete};
|
||||||
@ -75,7 +76,7 @@ pub fn from_token(db: &Db, token: String) -> Result<Account, Error> {
|
|||||||
Ok(Account { id, name, balance, subscribed })
|
Ok(Account { id, name, balance, subscribed })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn login(tx: &mut Transaction, name: &String, password: &String) -> Result<Account, Error> {
|
pub fn login(tx: &mut Transaction, name: &String, password: &String) -> Result<Account, MnmlHttpError> {
|
||||||
let query = "
|
let query = "
|
||||||
SELECT id, password, name, balance, subscribed
|
SELECT id, password, name, balance, subscribed
|
||||||
FROM accounts
|
FROM accounts
|
||||||
@ -96,7 +97,7 @@ pub fn login(tx: &mut Transaction, name: &String, password: &String) -> Result<A
|
|||||||
|
|
||||||
// verify garbage to prevent timing attacks
|
// verify garbage to prevent timing attacks
|
||||||
verify(garbage.clone(), &garbage).ok();
|
verify(garbage.clone(), &garbage).ok();
|
||||||
return Err(err_msg("account not found"));
|
return Err(MnmlHttpError::AccountNotFound);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ pub fn login(tx: &mut Transaction, name: &String, password: &String) -> Result<A
|
|||||||
let subscribed: bool = row.get(4);
|
let subscribed: bool = row.get(4);
|
||||||
|
|
||||||
if !verify(password, &hash)? {
|
if !verify(password, &hash)? {
|
||||||
return Err(err_msg("password does not match"));
|
return Err(MnmlHttpError::PasswordNotMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
let balance = u32::try_from(db_balance)
|
let balance = u32::try_from(db_balance)
|
||||||
@ -212,17 +213,17 @@ pub fn set_subscribed(tx: &mut Transaction, id: Uuid, subscribed: bool) -> Resul
|
|||||||
Ok(name)
|
Ok(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(name: &String, password: &String, code: &String, tx: &mut Transaction) -> Result<String, Error> {
|
pub fn create(name: &String, password: &String, code: &String, tx: &mut Transaction) -> Result<String, MnmlHttpError> {
|
||||||
if password.len() < PASSWORD_MIN_LEN {
|
if password.len() < PASSWORD_MIN_LEN {
|
||||||
return Err(err_msg("password must be at least 12 characters"));
|
return Err(MnmlHttpError::PasswordUnacceptable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if code.to_lowercase() != "grep842" {
|
if code.to_lowercase() != "grep842" {
|
||||||
return Err(err_msg("https://discord.gg/YJJgurM"));
|
return Err(MnmlHttpError::InvalidCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if name.len() == 0 {
|
if name.len() == 0 {
|
||||||
return Err(err_msg("account name not supplied"));
|
return Err(MnmlHttpError::AccountNameNotProvided);
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = Uuid::new_v4();
|
let id = Uuid::new_v4();
|
||||||
@ -246,7 +247,7 @@ pub fn create(name: &String, password: &String, code: &String, tx: &mut Transact
|
|||||||
|
|
||||||
match result.iter().next() {
|
match result.iter().next() {
|
||||||
Some(row) => row,
|
Some(row) => row,
|
||||||
None => return Err(err_msg("account not created")),
|
None => return Err(MnmlHttpError::DbError),
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3 constructs for a team and 1 to swap
|
// 3 constructs for a team and 1 to swap
|
||||||
|
|||||||
@ -5,9 +5,11 @@ use iron::headers::{Cookie as CookieHdr, SetCookie};
|
|||||||
use iron::prelude::*;
|
use iron::prelude::*;
|
||||||
use iron::status;
|
use iron::status;
|
||||||
use iron::typemap::Key;
|
use iron::typemap::Key;
|
||||||
|
use iron::mime::Mime;
|
||||||
use iron::{typemap, BeforeMiddleware,AfterMiddleware};
|
use iron::{typemap, BeforeMiddleware,AfterMiddleware};
|
||||||
use persistent::Read;
|
use persistent::Read;
|
||||||
use router::Router;
|
use router::Router;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
// use warden::{warden};
|
// use warden::{warden};
|
||||||
// use pubsub::{pg_listen};
|
// use pubsub::{pg_listen};
|
||||||
@ -18,7 +20,7 @@ use payments::{stripe};
|
|||||||
|
|
||||||
pub const TOKEN_HEADER: &str = "x-auth-token";
|
pub const TOKEN_HEADER: &str = "x-auth-token";
|
||||||
|
|
||||||
#[derive(Fail, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Fail, Debug, Serialize, Deserialize)]
|
||||||
pub enum MnmlHttpError {
|
pub enum MnmlHttpError {
|
||||||
// User Facing Errors
|
// User Facing Errors
|
||||||
#[fail(display="internal server error")]
|
#[fail(display="internal server error")]
|
||||||
@ -30,26 +32,84 @@ pub enum MnmlHttpError {
|
|||||||
#[fail(display="bad request")]
|
#[fail(display="bad request")]
|
||||||
BadRequest,
|
BadRequest,
|
||||||
#[fail(display="account name taken or invalid")]
|
#[fail(display="account name taken or invalid")]
|
||||||
|
AccountNameNotProvided,
|
||||||
|
#[fail(display="account name not provided")]
|
||||||
|
AccountNotFound,
|
||||||
|
#[fail(display="account not found")]
|
||||||
AccountNameTaken,
|
AccountNameTaken,
|
||||||
|
#[fail(display="password does not match")]
|
||||||
|
PasswordNotMatch,
|
||||||
#[fail(display="password unacceptable. must be > 11 characters")]
|
#[fail(display="password unacceptable. must be > 11 characters")]
|
||||||
PasswordUnacceptable,
|
PasswordUnacceptable,
|
||||||
|
#[fail(display="incorrect token. refresh or logout of existing sessions")]
|
||||||
|
TokenDoesNotMatch,
|
||||||
#[fail(display="invalid code. https://discord.gg/YJJgurM")]
|
#[fail(display="invalid code. https://discord.gg/YJJgurM")]
|
||||||
InvalidCode,
|
InvalidCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<bcrypt::BcryptError> for MnmlHttpError {
|
||||||
|
fn from(_err: bcrypt::BcryptError) -> Self {
|
||||||
|
MnmlHttpError::ServerError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<postgres::Error> for MnmlHttpError {
|
||||||
|
fn from(_err: postgres::Error) -> Self {
|
||||||
|
MnmlHttpError::DbError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<failure::Error> for MnmlHttpError {
|
||||||
|
fn from(_err: failure::Error) -> Self {
|
||||||
|
MnmlHttpError::ServerError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct JsonResponse {
|
||||||
|
response: Option<String>,
|
||||||
|
success: bool,
|
||||||
|
error_message: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JsonResponse {
|
||||||
|
fn success(response: String) -> Self {
|
||||||
|
JsonResponse { response: Some(response), success: true, error_message: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error(msg: String) -> Self {
|
||||||
|
JsonResponse { response: None, success: false, error_message: Some(msg) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iron_response (status: status::Status, message: String) -> Response {
|
||||||
|
let content_type = "application/json".parse::<Mime>().unwrap();
|
||||||
|
let msg = match status {
|
||||||
|
status::Ok => JsonResponse::success(message),
|
||||||
|
_ => JsonResponse::error(message)
|
||||||
|
};
|
||||||
|
let msg_out = serde_json::to_string(&msg).unwrap();
|
||||||
|
return Response::with((content_type, status, msg_out));
|
||||||
|
}
|
||||||
|
|
||||||
impl From<MnmlHttpError> for IronError {
|
impl From<MnmlHttpError> for IronError {
|
||||||
fn from(m_err: MnmlHttpError) -> Self {
|
fn from(m_err: MnmlHttpError) -> Self {
|
||||||
let (err, res) = match m_err {
|
let (err, res) = match m_err {
|
||||||
MnmlHttpError::ServerError => (m_err.compat(), status::InternalServerError),
|
MnmlHttpError::ServerError |
|
||||||
MnmlHttpError::DbError => (m_err.compat(), status::InternalServerError),
|
MnmlHttpError::DbError => (m_err.compat(), status::InternalServerError),
|
||||||
MnmlHttpError::Unauthorized => (m_err.compat(), status::Unauthorized),
|
|
||||||
MnmlHttpError::BadRequest => (m_err.compat(), status::BadRequest),
|
|
||||||
MnmlHttpError::AccountNameTaken => (m_err.compat(), status::BadRequest),
|
|
||||||
MnmlHttpError::PasswordUnacceptable => (m_err.compat(), status::BadRequest),
|
|
||||||
MnmlHttpError::InvalidCode => (m_err.compat(), status::Unauthorized),
|
|
||||||
};
|
|
||||||
|
|
||||||
IronError::new(err, res)
|
MnmlHttpError::AccountNameNotProvided |
|
||||||
|
MnmlHttpError::AccountNameTaken |
|
||||||
|
MnmlHttpError::AccountNotFound |
|
||||||
|
MnmlHttpError::BadRequest |
|
||||||
|
MnmlHttpError::PasswordUnacceptable => (m_err.compat(), status::BadRequest),
|
||||||
|
|
||||||
|
MnmlHttpError::PasswordNotMatch |
|
||||||
|
MnmlHttpError::InvalidCode |
|
||||||
|
MnmlHttpError::TokenDoesNotMatch |
|
||||||
|
MnmlHttpError::Unauthorized => (m_err.compat(), status::Unauthorized),
|
||||||
|
};
|
||||||
|
IronError { error: Box::new(err), response: iron_response(res, m_err.to_string()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +130,7 @@ impl BeforeMiddleware for AuthMiddleware {
|
|||||||
if cookie.name() == TOKEN_HEADER {
|
if cookie.name() == TOKEN_HEADER {
|
||||||
match account::from_token(&db, cookie.value().to_string()) {
|
match account::from_token(&db, cookie.value().to_string()) {
|
||||||
Ok(a) => req.extensions.insert::<account::Account>(a),
|
Ok(a) => req.extensions.insert::<account::Account>(a),
|
||||||
Err(_) => return Err(IronError::from(MnmlHttpError::Unauthorized)),
|
Err(_) => return Err(IronError::from(MnmlHttpError::TokenDoesNotMatch)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,8 +170,8 @@ fn token_res(token: String) -> Response {
|
|||||||
.max_age(Duration::weeks(1)) // 1 week aligns with db set
|
.max_age(Duration::weeks(1)) // 1 week aligns with db set
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
let mut res = Response::with(status::Ok);
|
let mut res = iron_response(status::Ok, "token_res".to_string());
|
||||||
res.headers.set(SetCookie(vec![v.to_string()]));
|
res.headers.set(SetCookie(vec![v.to_string()]));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -141,7 +201,7 @@ fn register(req: &mut Request) -> IronResult<Response> {
|
|||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("{:?}", e);
|
warn!("{:?}", e);
|
||||||
Err(IronError::from(MnmlHttpError::BadRequest))
|
Err(IronError::from(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +230,7 @@ fn login(req: &mut Request) -> IronResult<Response> {
|
|||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("{:?}", e);
|
warn!("{:?}", e);
|
||||||
Err(IronError::from(MnmlHttpError::Unauthorized))
|
Err(IronError::from(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +246,7 @@ fn logout(req: &mut Request) -> IronResult<Response> {
|
|||||||
|
|
||||||
tx.commit().or(Err(MnmlHttpError::ServerError))?;
|
tx.commit().or(Err(MnmlHttpError::ServerError))?;
|
||||||
|
|
||||||
let mut res = Response::with(status::Ok);
|
let mut res = iron_response(status::Ok, "token_res".to_string());
|
||||||
res.headers.set(SetCookie(vec![AUTH_CLEAR.to_string()]));
|
res.headers.set(SetCookie(vec![AUTH_CLEAR.to_string()]));
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user