Skip to content

Commit

Permalink
convert server to use warp
Browse files Browse the repository at this point in the history
  • Loading branch information
jaemk committed Jan 2, 2019
1 parent 5fc03e4 commit e4933ef
Show file tree
Hide file tree
Showing 14 changed files with 1,627 additions and 838 deletions.
972 changes: 744 additions & 228 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
[package]
name = "transfer"
version = "0.4.6"
version = "0.5.0"
authors = ["James Kominick <james@kominick.com>"]

[dependencies]
clap = "2"
log = "0.4"
env_logger = "0.6"
error-chain = "0.12"
ron = "0.4"
lazy_static = "1"

Expand All @@ -28,5 +27,11 @@ r2d2_postgres = "0.14"
xdg = "2"
migrant_lib = { version = "0.21", features = ["d-postgres"] }

rouille = "2"
warp = "0.1"
hyper = "0.12"

futures = "0.1"
futures-cpupool = "0.1"
futures-fs = "0.0.5"
num_cpus = "1"
tokio = "0.1"
4 changes: 2 additions & 2 deletions src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ General Admin commands
*/
use sweep;
use models::CONFIG;
use errors::*;
use error::{self, Result};


/// Cleanup files that no longer have an associated record in the database
Expand All @@ -13,7 +13,7 @@ pub fn sweep_files() -> Result<()> {
let n = sweep::sweep_fs(&upload_dir)?;
info!("** Cleaned up {} orphaned files **", n);
} else {
bail!("Provided upload dir is invalid: {:?}", upload_dir);
return Err(error::helpers::internal(format!("Provided upload dir is invalid: {:?}", upload_dir)));
}
Ok(())
}
Expand Down
19 changes: 11 additions & 8 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
Authorization/crypto things
*/
use errors::*;
use error;
use ring::rand::{self, SecureRandom};
use ring::{digest, constant_time};
use crypto::bcrypt;


/// Generate a new 16-byte salt for use with `bcrypt`
pub fn new_salt() -> Result<Vec<u8>> {
pub fn new_salt() -> error::Result<Vec<u8>> {
const SALT_SIZE: usize = 16;
let mut salt = vec![0u8; SALT_SIZE];
let rng = rand::SystemRandom::new();
Expand All @@ -27,13 +27,16 @@ pub fn sha256(bytes: &[u8]) -> Vec<u8> {


/// Calculate the `bcrypt` hash of `bytes` and `salt`
pub fn bcrypt_hash(bytes: &[u8], salt: &[u8]) -> Result<Vec<u8>> {
pub fn bcrypt_hash(bytes: &[u8], salt: &[u8]) -> error::Result<Vec<u8>> {
let slen = salt.len();
let blen = bytes.len();
if !(slen == 16 && (0 < blen && blen <= 72)) {
bail_fmt!(ErrorKind::InvalidHashArgs,
"Expected salt size (16) and bytes size (1-72), got: salt({}), bytes({})",
salt.len(), bytes.len())
return Err(error::helpers::internal(
format!(
"Expected salt size (16) and bytes size (1-72), got: salt({}), bytes({})",
salt.len(), bytes.len(),
)
));
}
const COST: u32 = 10;
const OUTPUT_SIZE: usize = 24;
Expand All @@ -44,9 +47,9 @@ pub fn bcrypt_hash(bytes: &[u8], salt: &[u8]) -> Result<Vec<u8>> {


/// Constant time slice equality comparison
pub fn eq(a: &[u8], b: &[u8]) -> Result<()> {
pub fn eq(a: &[u8], b: &[u8]) -> error::Result<()> {
constant_time::verify_slices_are_equal(a, b)
.map_err(|_| format_err!(ErrorKind::UnequalBytes, "Bytes differ"))?;
.map_err(|_| "Bytes differ")?;
debug!("Auth OK");
Ok(())
}
Expand Down
12 changes: 6 additions & 6 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use postgres;
use migrant_lib;
use {config_dir};

use super::errors::*;
use error::Result;


/// Postgres r2d2 pool
Expand All @@ -22,21 +22,21 @@ pub type DbConn = r2d2::PooledConnection<PostgresConnectionManager>;
pub fn connect_str() -> Result<String> {
let config_dir_ = config_dir()?;
let config_path = migrant_lib::search_for_settings_file(&config_dir_)
.chain_err(|| "Unable to find `Migrant.toml` config file")?;
.ok_or_else(|| "Unable to find `Migrant.toml` config file")?;
let config = migrant_lib::Config::from_settings_file(&config_path)
.chain_err(|| "Failed loading `Migrant.toml`")?;
Ok(config.connect_string().chain_err(|| "Failed creating a connection string")?)
.map_err(|_| "Failed loading `Migrant.toml`")?;
Ok(config.connect_string().map_err(|_| "Failed creating a connection string")?)
}


/// Initialize a new r2d2 postgres connection pool
pub fn init_pool() -> Pool {
pub fn init_pool(n: u32) -> Pool {
// let config = r2d2::Config::default();
let conn_str = connect_str().expect("Failed to build connection string");
let manager = PostgresConnectionManager::new(conn_str, TlsMode::None)
.expect("Failed to connect to db");
r2d2::Pool::builder()
.min_idle(Some(3))
.min_idle(Some(n))
.build(manager)
.expect("Failed to create db pool")
}
Expand Down
226 changes: 226 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
use std::io;
use std::net;
use warp;
use hex;
use uuid;
use serde_json;
use postgres;
use r2d2;
use ring;
use xdg;


pub mod helpers {
use super::*;

pub fn reject<T: Into<Error>>(e: T) -> warp::Rejection {
warp::reject::custom(e.into())
}

pub fn internal<T: AsRef<str>>(s: T) -> self::Error {
Error::from_kind(ErrorKind::Internal(s.as_ref().to_string()))
}

pub fn bad_request<T: AsRef<str>>(s: T) -> self::Error {
Error::from_kind(ErrorKind::BadRequest(s.as_ref().to_string()))
}

pub fn invalid_auth<T: AsRef<str>>(s: T) -> self::Error {
Error::from_kind(ErrorKind::InvalidAuth(s.as_ref().to_string()))
}

pub fn too_large<T: AsRef<str>>(s: T) -> self::Error {
Error::from_kind(ErrorKind::UploadTooLarge(s.as_ref().to_string()))
}

pub fn out_of_space<T: AsRef<str>>(s: T) -> self::Error {
Error::from_kind(ErrorKind::OutOfSpace(s.as_ref().to_string()))
}

pub fn does_not_exist<T: AsRef<str>>(s: T) -> self::Error {
Error::from_kind(ErrorKind::DoesNotExist(s.as_ref().to_string()))
}

pub fn multiple_records<T: AsRef<str>>(s: T) -> self::Error {
Error::from_kind(ErrorKind::MultipleRecords(s.as_ref().to_string()))
}
}


pub type Result<T> = std::result::Result<T, self::Error>;


pub trait Rejectable<T, E> {
fn reject(self) -> std::result::Result<T, warp::Rejection>;
fn reject_with(self, impl Fn(E) -> warp::Rejection) -> std::result::Result<T, warp::Rejection>;
}

impl<T, E: Into<Error>> Rejectable<T, E> for std::result::Result<T, E> {
fn reject(self) -> std::result::Result<T, warp::Rejection> {
self.map_err(|e| warp::reject::custom(e.into()))
}

fn reject_with(self, convert: impl Fn(E) -> warp::Rejection) -> std::result::Result<T, warp::Rejection> {
self.map_err(convert)
}
}


#[derive(Debug)]
pub struct Error {
kind: Box<ErrorKind>,
}
impl Error {
pub fn kind(&self) -> &ErrorKind {
self.kind.as_ref()
}

pub fn from_kind(kind: ErrorKind) -> Self {
Self { kind: Box::new(kind) }
}

pub fn is_does_not_exist(&self) -> bool {
if let self::ErrorKind::DoesNotExist(_) = self.kind() { true } else { false }
}
}

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use self::ErrorKind::*;
match *self.kind() {
S(ref s) => write!(f, "{}", s),
Internal(ref s) => write!(f, "InternalError: {}", s),
BadRequest(ref s) => write!(f, "BadRequest: {}", s),
UploadTooLarge(ref s) => write!(f, "UploadTooLarge: {}", s),
OutOfSpace(ref s) => write!(f, "OutOfSpace: {}", s),
DoesNotExist(ref s) => write!(f, "DoesNotExist: {}", s),
MultipleRecords(ref s) => write!(f, "MultipleRecords: {}", s),
InvalidAuth(ref s) => write!(f, "InvalidAuth: {}", s),

Io(ref e) => write!(f, "IoError: {}", e),
Warp(ref e) => write!(f, "WarpError: {}", e),
Json(ref e) => write!(f, "JsonError: {}", e),
Uuid(ref e) => write!(f, "UuidError: {}", e),
Hex(ref e) => write!(f, "HexError: {}", e),
Postgres(ref e) => write!(f, "PostgresError: {}", e),
ConnError(ref e) => write!(f, "ConnError: {}", e),
RingUnspecified(ref e) => write!(f, "RingUnspecified: {}", e),
Xdg(ref e) => write!(f, "Xdg: {}", e),
ParseAddr(ref e) => write!(f, "ParseAddr: {}", e),
}
}
}

impl std::error::Error for Error {
fn description(&self) -> &str {
"transfer error"
}

fn cause(&self) -> Option<&std::error::Error> {
use self::ErrorKind::*;
Some(match *self.kind() {
Warp(ref e) => e,
Json(ref e) => e,
Io(ref e) => e,
Uuid(ref e) => e,
Hex(ref e) => e,
Postgres(ref e) => e,
ConnError(ref e) => e,
RingUnspecified(ref e) => e,
Xdg(ref e) => e,
ParseAddr(ref e) => e,
_ => return None,
})
}
}


#[derive(Debug)]
pub enum ErrorKind {
S(String),
Internal(String),
BadRequest(String),
UploadTooLarge(String),
OutOfSpace(String),
DoesNotExist(String),
MultipleRecords(String),
InvalidAuth(String),

Io(io::Error),
Warp(warp::Error),
Json(serde_json::Error),
Uuid(uuid::ParseError),
Hex(hex::FromHexError),
Postgres(postgres::error::Error),
ConnError(r2d2::Error),
RingUnspecified(ring::error::Unspecified),
Xdg(xdg::BaseDirectoriesError),
ParseAddr(net::AddrParseError),
}

impl From<&str> for Error {
fn from(s: &str) -> Error {
Error { kind: Box::new(ErrorKind::S(s.into())) }
}
}

impl From<io::Error> for Error {
fn from(e: io::Error) -> Error {
Error { kind: Box::new(ErrorKind::Io(e)) }
}
}


impl From<warp::Error> for Error {
fn from(e: warp::Error) -> Error {
Error { kind: Box::new(ErrorKind::Warp(e)) }
}
}

impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Error {
Error { kind: Box::new(ErrorKind::Json(e)) }
}
}

impl From<uuid::ParseError> for Error {
fn from(e: uuid::ParseError) -> Error {
Error { kind: Box::new(ErrorKind::Uuid(e)) }
}
}

impl From<hex::FromHexError> for Error {
fn from(e: hex::FromHexError) -> Error {
Error { kind: Box::new(ErrorKind::Hex(e)) }
}
}

impl From<postgres::error::Error> for Error {
fn from(e: postgres::error::Error) -> Error {
Error { kind: Box::new(ErrorKind::Postgres(e)) }
}
}

impl From<r2d2::Error> for Error {
fn from(e: r2d2::Error) -> Error {
Error { kind: Box::new(ErrorKind::ConnError(e)) }
}
}

impl From<ring::error::Unspecified> for Error {
fn from(e: ring::error::Unspecified) -> Error {
Error { kind: Box::new(ErrorKind::RingUnspecified(e)) }
}
}

impl From<xdg::BaseDirectoriesError> for Error {
fn from(e: xdg::BaseDirectoriesError) -> Error {
Error { kind: Box::new(ErrorKind::Xdg(e)) }
}
}

impl From<net::AddrParseError> for Error {
fn from(e: net::AddrParseError) -> Error {
Error { kind: Box::new(ErrorKind::ParseAddr(e)) }
}
}
Loading

0 comments on commit e4933ef

Please sign in to comment.