client now runs correctly

- server now handles basic operations correctly
- client now creates random username, email, password
This commit is contained in:
ayham 2021-05-30 21:31:01 +03:00
parent bf6a475ced
commit d32140ceb7
Signed by: ayham
GPG Key ID: EAB7F5A9DF503678
21 changed files with 197 additions and 98 deletions

View File

@ -19,7 +19,9 @@ fn main() {
// Spawn server
rt.block_on(async move {
libtrader_init_server().await.expect("failed running server");
libtrader_init_server()
.await
.expect("failed running server");
});
}

View File

@ -99,7 +99,6 @@ pub async fn acc_create(
false,
0,
) && response.instruction == 1
&& response.data.len() != 0
{
/* created successfully */
return Ok(());

View File

@ -1,7 +1,6 @@
use std::io;
use std::net::ToSocketAddrs;
use tokio::net::TcpStream;
use tokio_rustls::webpki::DNSNameRef;
use tokio_rustls::TlsConnector;
@ -9,8 +8,8 @@ use tokio_rustls::TlsConnector;
use crate::common::misc::gen_tls_client_config::gen_tls_client_config;
use crate::common::misc::path_exists::path_exists;
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
/// Initializes global logger.
///
@ -107,14 +106,14 @@ pub async fn libtrader_init_client() -> std::io::Result<()> {
.collect();
use crate::client::account::creation::acc_create;
match acc_create(&mut socket, "test", "email", "password").await {
match acc_create(&mut socket, &username, &email, &password).await {
Ok(_) => println!("we created it"),
Err(err) => panic!("panik! {}", err),
}
use crate::client::account::authorization::acc_auth;
let mut jwt: String = String::new();
match acc_auth(&mut socket, "test", "email", "password").await {
match acc_auth(&mut socket, &username, &email, &password).await {
Ok(auth) => {
jwt = auth;
println!("we accessed it, the token: {}", jwt);

View File

@ -1,4 +1,4 @@
use postgres_types::{ToSql, FromSql};
use postgres_types::{FromSql, ToSql};
use serde::{Deserialize, Serialize};
#[derive(Default, PartialEq, Debug, ToSql, FromSql, Serialize, Deserialize)]

View File

@ -41,20 +41,40 @@ pub async fn acc_auth(
* Get server salts
* */
let email_salt = HEXUPPER
.decode(get_user_salt(sql_conn, username, true, true).await.unwrap().as_bytes())
.decode(
get_user_salt(sql_conn, username, true, true)
.await
.unwrap()
.as_bytes(),
)
.unwrap();
let password_salt = HEXUPPER
.decode(get_user_salt(sql_conn, username, false, true).await.unwrap().as_bytes())
.decode(
get_user_salt(sql_conn, username, false, true)
.await
.unwrap()
.as_bytes(),
)
.unwrap();
/*
* Get server hashes
* */
let email_db = HEXUPPER
.decode(get_user_hash(sql_conn, username, true).await.unwrap().as_bytes())
.decode(
get_user_hash(sql_conn, username, true)
.await
.unwrap()
.as_bytes(),
)
.unwrap();
let password_db = HEXUPPER
.decode(get_user_hash(sql_conn, username, false).await.unwrap().as_bytes())
.decode(
get_user_hash(sql_conn, username, false)
.await
.unwrap()
.as_bytes(),
)
.unwrap();
/*

View File

@ -8,7 +8,10 @@ use crate::server::account::hash_email::hash_email;
use crate::server::account::hash_pwd::hash_pwd;
use crate::server::ds::account::Account;
pub async fn acc_create(sql_conn: &tokio_postgres::Client, message: &Message) -> Result<(), ReturnFlags> {
pub async fn acc_create(
sql_conn: &tokio_postgres::Client,
message: &Message,
) -> Result<(), ReturnFlags> {
/*
* Parse account data
* */
@ -77,7 +80,8 @@ pub async fn acc_create(sql_conn: &tokio_postgres::Client, message: &Message) ->
"SELECT username FROM accounts_schema.accounts WHERE username LIKE $1",
&[&account.username],
)
.await.unwrap()
.await
.unwrap()
{
return Err(ReturnFlags::ServerAccUserExists);
}

View File

@ -1,3 +1,5 @@
use std::io;
use crate::common::account::portfolio::Portfolio;
use crate::common::account::position::Position;
use crate::common::message::message::Message;
@ -6,13 +8,14 @@ use crate::common::message::message_type::MessageType;
use crate::common::misc::return_flags::ReturnFlags;
use crate::server::network::jwt_wrapper::verify_jwt_token;
use crate::server::db::config::{DB_PORTFOLIO_USER, DB_PORTFOLIO_PASS};
use crate::server::db::initializer::db_connect;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tokio_rustls::server::TlsStream;
pub async fn acc_retrieve_portfolio(
sql_conn: &tokio_postgres::Client,
tls_connection: &mut TlsStream<TcpStream>,
message: &Message,
) -> Result<(), ReturnFlags> {
@ -26,6 +29,10 @@ pub async fn acc_retrieve_portfolio(
}
};
/* connect to SQL database using user ```postfolio_schema_user``` */
let sql_conn = db_connect(DB_PORTFOLIO_USER, DB_PORTFOLIO_PASS)
.await
.map_err(|_| {ReturnFlags::ServerRetrievePortfolioFailed})?;
/* get userId's portfolio positions */
let mut portfolio: Portfolio = Portfolio::default();
@ -34,7 +41,8 @@ pub async fn acc_retrieve_portfolio(
.query(
"SELECT * FROM portfolio_schema.positions WHERE user_id = $1",
&[&token.user_id],
).await
)
.await
.unwrap()
{
let mut pos: Position = Position::default();

View File

@ -12,7 +12,7 @@ use tokio_rustls::server::TlsStream;
pub async fn acc_retrieve_transaction(
sql_conn: &tokio_postgres::Client,
tls_connection: &mut TlsStream<TcpStream>,
socket: &mut TlsStream<TcpStream>,
message: &Message,
) -> Result<(), ReturnFlags> {
/* verify JWT token */
@ -20,7 +20,7 @@ pub async fn acc_retrieve_transaction(
Ok(token) => token,
Err(_) => {
warn!("ACC_RETRIEVE_TRANSACTION_UNAUTH_TOKEN");
tls_connection.shutdown().await.unwrap();
socket.shutdown().await.unwrap();
return Err(ReturnFlags::ServerAccUnauthorized);
}
};
@ -53,7 +53,9 @@ pub async fn acc_retrieve_transaction(
0,
bincode::serialize(&transactions).unwrap(),
);
let _ = tls_connection.write(&bincode::serialize(&message).unwrap());
socket.write_all(&bincode::serialize(&message).unwrap())
.await
.map_err(|_| {ReturnFlags::ServerRetrieveTransactionFailed})?;
Ok(())
}

View File

@ -17,26 +17,32 @@ use crate::common::misc::return_flags::ReturnFlags;
/// Err(err) => error!("Failed to create company with error: {}", err),
/// }
/// ```
pub async fn create_company(sql_conn: &mut tokio_postgres::Client, company: Company) -> Result<Company, ReturnFlags> {
pub async fn create_company(
sql_conn: &mut tokio_postgres::Client,
company: Company,
) -> Result<Company, ReturnFlags> {
/*
* Creates a company entry in database in public.companies.
*/
// Insert argument company into public.companies database table.
match sql_conn.execute(
"INSERT INTO public.companies VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
&[
&company.id,
&company.symbol,
&company.isin,
&company.company_name,
&company.primary_exchange,
&company.sector,
&company.industry,
&company.primary_sic_code,
&company.employees,
],
).await {
match sql_conn
.execute(
"INSERT INTO public.companies VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
&[
&company.id,
&company.symbol,
&company.isin,
&company.company_name,
&company.primary_exchange,
&company.sector,
&company.industry,
&company.primary_sic_code,
&company.employees,
],
)
.await
{
Ok(_row) => Ok(company),
Err(_) => Err(ReturnFlags::ServerDbCreateCompanyFailed),
}

View File

@ -16,7 +16,11 @@ use crate::common::misc::return_flags::ReturnFlags;
/// Err(err) => panic!("TEST_CMD_CREATE_PORTFOLIO_FAILED: {}", err)
/// }
/// ```
pub async fn create_position(sql_conn: &mut tokio_postgres::Client, user_id: i64, position: Position) -> Result<(), ReturnFlags> {
pub async fn create_position(
sql_conn: &mut tokio_postgres::Client,
user_id: i64,
position: Position,
) -> Result<(), ReturnFlags> {
/*
* Creates a position entry in database in portfolio_schema.positions.
* */

View File

@ -16,15 +16,19 @@ use crate::common::misc::return_flags::ReturnFlags;
/// Err(err) => error!("failed to create stock table {}", err),
/// }
/// ```
pub async fn create_stock(sql_conn: &mut tokio_postgres::Client, stock_name: &str) -> Result<(), ReturnFlags> {
pub async fn create_stock(
sql_conn: &mut tokio_postgres::Client,
stock_name: &str,
) -> Result<(), ReturnFlags> {
/*
* Creates a stock table in database in assets schema.
*/
// Create the table.
match sql_conn.execute(
format!(
"CREATE TABLE asset_schema.{} ( \
match sql_conn
.execute(
format!(
"CREATE TABLE asset_schema.{} ( \
id BIGSERIAL PRIMARY KEY, \
isin TEXT NOT NULL, \
time_epoch BIGINT NOT NULL, \
@ -32,11 +36,13 @@ pub async fn create_stock(sql_conn: &mut tokio_postgres::Client, stock_name: &st
bid_price DOUBLE PRECISION NOT NULL, \
volume BIGINT NOT NULL \
)",
stock_name
stock_name
)
.as_str(),
&[],
)
.as_str(),
&[],
).await {
.await
{
Ok(_rows) => Ok(()),
Err(_) => Err(ReturnFlags::ServerDbCreateStockFailed),
}

View File

@ -16,24 +16,31 @@ use crate::common::misc::return_flags::ReturnFlags;
/// Err(err) => panic!("TEST_CMD_CREATE_TRANSACTION_FAILED: {}", err)
/// }
/// ```
pub async fn create_transaction(sql_conn: &mut tokio_postgres::Client, user_id: i64, transaction: &Transaction) -> Result<(), ReturnFlags> {
pub async fn create_transaction(
sql_conn: &mut tokio_postgres::Client,
user_id: i64,
transaction: &Transaction,
) -> Result<(), ReturnFlags> {
/*
* Creates a transaction entry in database in accounts_schema.transactions.
* */
/* insert position */
match sql_conn.execute(
"INSERT INTO accounts_schema.transactions
match sql_conn
.execute(
"INSERT INTO accounts_schema.transactions
(user_id, stock_symbol, shares_size, shares_cost, is_buy)
VALUES ($1, $2, $3, $4, $5)",
&[
&user_id,
&transaction.stock_symbol,
&transaction.shares_size,
&transaction.shares_cost,
&transaction.is_buy,
],
).await {
&[
&user_id,
&transaction.stock_symbol,
&transaction.shares_size,
&transaction.shares_cost,
&transaction.is_buy,
],
)
.await
{
Ok(_rows) => Ok(()),
Err(_) => Err(ReturnFlags::ServerDbCreateTransactionFailed),
}

View File

@ -18,15 +18,21 @@ use crate::common::misc::return_flags::ReturnFlags;
/// Err(err) => error!("we must found the sacred company! err: {}", err),
/// }
/// ```
pub async fn get_company_from_db(sql_conn: &mut tokio_postgres::Client, searched_symbol: &str) -> Result<Company, ReturnFlags> {
pub async fn get_company_from_db(
sql_conn: &mut tokio_postgres::Client,
searched_symbol: &str,
) -> Result<Company, ReturnFlags> {
/*
* Returns company entry from database
*/
// Connect to database.
match sql_conn.query(
"SELECT * FROM public.companies WHERE symbol=$1",
&[&searched_symbol],
).await {
match sql_conn
.query(
"SELECT * FROM public.companies WHERE symbol=$1",
&[&searched_symbol],
)
.await
{
Ok(row) => {
let mut found_company: Company = Company::default();
found_company.id = row[0].get(0);

View File

@ -19,17 +19,23 @@ use crate::common::misc::return_flags::ReturnFlags;
/// Err(err) => panic!("failed to get the stock value, reason: {}", err)
/// };
/// ```
pub async fn get_stock_from_db(sql_conn: &mut tokio_postgres::Client, searched_symbol: &str) -> Result<Vec<StockVal>, ReturnFlags> {
pub async fn get_stock_from_db(
sql_conn: &mut tokio_postgres::Client,
searched_symbol: &str,
) -> Result<Vec<StockVal>, ReturnFlags> {
/*
* Returns all stock values from database.
*/
// Query database for table.
let mut stocks: Vec<StockVal> = Vec::new();
match sql_conn.query(
format!("SELECT * FROM asset_schema.{}", searched_symbol).as_str(),
&[],
).await {
match sql_conn
.query(
format!("SELECT * FROM asset_schema.{}", searched_symbol).as_str(),
&[],
)
.await
{
Ok(all_rows) => {
for row in all_rows {
let mut val: StockVal = StockVal::default();
@ -77,14 +83,17 @@ pub async fn get_stock_from_db_since_epoch(
// Query database for table.
let mut stocks: Vec<StockVal> = Vec::new();
match sql_conn.query(
format!(
"SELECT * FROM asset_schema.{} WHERE time_epoch >= {}",
searched_symbol, time_epoch
match sql_conn
.query(
format!(
"SELECT * FROM asset_schema.{} WHERE time_epoch >= {}",
searched_symbol, time_epoch
)
.as_str(),
&[],
)
.as_str(),
&[],
).await {
.await
{
Ok(all_rows) => {
for row in all_rows {
let mut val: StockVal = StockVal::default();
@ -135,14 +144,17 @@ pub async fn get_stock_from_db_between_epochs(
// Query database for table.
let mut stocks: Vec<StockVal> = Vec::new();
match sql_conn.query(
format!(
"SELECT * FROM asset_schema.{} WHERE time_epoch >= {} AND time_epoch <= {}",
searched_symbol, first_time_epoch, second_time_epoch
match sql_conn
.query(
format!(
"SELECT * FROM asset_schema.{} WHERE time_epoch >= {} AND time_epoch <= {}",
searched_symbol, first_time_epoch, second_time_epoch
)
.as_str(),
&[],
)
.as_str(),
&[],
).await {
.await
{
Ok(all_rows) => {
for row in all_rows {
let mut val: StockVal = StockVal::default();

View File

@ -2,7 +2,11 @@ use crate::common::misc::return_flags::ReturnFlags;
use crate::server::db::cmd::user_exists::user_exists;
pub async fn get_user_hash(sql_conn: &tokio_postgres::Client, username: &str, is_email: bool) -> Result<String, ReturnFlags> {
pub async fn get_user_hash(
sql_conn: &tokio_postgres::Client,
username: &str,
is_email: bool,
) -> Result<String, ReturnFlags> {
/* check that user exists*/
if user_exists(sql_conn, username).await {
if is_email {

View File

@ -2,7 +2,10 @@ use crate::server::db::cmd::user_exists::user_exists;
use crate::common::misc::return_flags::ReturnFlags;
pub async fn get_user_id(sql_conn: &tokio_postgres::Client, username: &str) -> Result<i64, ReturnFlags> {
pub async fn get_user_id(
sql_conn: &tokio_postgres::Client,
username: &str,
) -> Result<i64, ReturnFlags> {
/* check that user exists */
if user_exists(sql_conn, username).await {
for row in sql_conn

View File

@ -1,8 +1,11 @@
pub async fn user_exists(sql_conn: &tokio_postgres::Client, username: &str) -> bool {
for _ in &sql_conn.query(
"SELECT username FROM accounts_schema.accounts WHERE username LIKE $1",
&[&username],
).await {
for _ in &sql_conn
.query(
"SELECT username FROM accounts_schema.accounts WHERE username LIKE $1",
&[&username],
)
.await
{
return true;
}
false

View File

@ -15,13 +15,17 @@ use crate::server::db::config::{DB_HOST, DB_HOST_PORT, DB_NAME};
/// ```rust
/// let mut client = db_connect(DB_USER, DB_PASS)?;
/// ```
pub async fn db_connect(user: &'static str, pass: &'static str) -> Result<tokio_postgres::Client, tokio_postgres::Error> {
pub async fn db_connect(
user: &'static str,
pass: &'static str,
) -> Result<tokio_postgres::Client, tokio_postgres::Error> {
/* Generate the requested string */
let db_connect_str = format!(
"host={} port={} dbname={} user={} password={}",
DB_HOST, DB_HOST_PORT, DB_NAME, user, pass
);
let (client, connection) = tokio_postgres::connect(db_connect_str.as_str(), tokio_postgres::NoTls).await?;
let (client, connection) =
tokio_postgres::connect(db_connect_str.as_str(), tokio_postgres::NoTls).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("SQL connection error: {}", e);

View File

@ -1,7 +1,7 @@
use std::io;
use std::sync::Arc;
use argh::FromArgs;
use std::io;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::io::AsyncReadExt;
use tokio::net::TcpListener;
use tokio_rustls::TlsAcceptor;
@ -12,9 +12,9 @@ use crate::common::misc::gen_tls_server_config::gen_tls_server_config;
use crate::common::misc::path_exists::path_exists;
use crate::common::misc::return_flags::ReturnFlags;
use crate::server::db::config::{DB_ACC_USER, DB_ACC_PASS};
use crate::server::network::handle_data::handle_data;
use crate::server::db::config::{DB_ACC_PASS, DB_ACC_USER};
use crate::server::db::initializer::db_connect;
use crate::server::network::handle_data::handle_data;
/// Server Options
#[derive(FromArgs)]
@ -103,9 +103,12 @@ pub async fn libtrader_init_server() -> std::io::Result<()> {
};
// Initialize SQL connection
let sql_shared_conn = Arc::new(db_connect(DB_ACC_USER, DB_ACC_PASS)
.await
.map_err(|err| io::Error::new(io::ErrorKind::ConnectionAborted, format!("SQL_CONNECTION_FAILED: {}", err)))?);
let sql_shared_conn = Arc::new(db_connect(DB_ACC_USER, DB_ACC_PASS).await.map_err(|err| {
io::Error::new(
io::ErrorKind::ConnectionAborted,
format!("SQL_CONNECTION_FAILED: {}", err),
)
})?);
// Initialize arguments
let options: Options = argh::from_env();
@ -133,7 +136,7 @@ pub async fn libtrader_init_server() -> std::io::Result<()> {
let mut buf = Vec::with_capacity(4096);
socket.read_buf(&mut buf).await?;
match handle_data(&sql_conn, &mut socket, buf.as_slice()).await {
Ok(()) => {},
Ok(()) => {}
Err(err) => {
warn!("{}", format!("Failed running handle_data: {:#?}", err));
break;

View File

@ -34,7 +34,7 @@ pub async fn retrieve_portfolio(
}
/* call acc_retrieve_portfolio() server version */
match acc_retrieve_portfolio(sql_conn, tls_connection, message).await {
match acc_retrieve_portfolio(tls_connection, message).await {
Ok(_) => Ok(()),
Err(err) => {
warn!("RETRIEVE_PORTFOLIO_FAILED: {}", err);

View File

@ -15,8 +15,11 @@ use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tokio_rustls::server::TlsStream;
pub async fn handle_data(sql_conn: &tokio_postgres::Client,
socket: &mut TlsStream<TcpStream>, buf: &[u8]) -> std::io::Result<()> {
pub async fn handle_data(
sql_conn: &tokio_postgres::Client,
socket: &mut TlsStream<TcpStream>,
buf: &[u8],
) -> std::io::Result<()> {
/* decode incoming message */
let client_msg: Message = bincode::deserialize(&buf).map_err(|err| {
std::io::Error::new(
@ -54,7 +57,9 @@ pub async fn handle_data(sql_conn: &tokio_postgres::Client,
String::from_utf8(client_msg.data).unwrap().as_str(),
true,
false,
).await {
)
.await
{
Ok(salt) => {
let server_response: Message = message_builder(
MessageType::DataTransfer,
@ -84,7 +89,9 @@ pub async fn handle_data(sql_conn: &tokio_postgres::Client,
String::from_utf8(client_msg.data).unwrap().as_str(),
false,
false,
).await {
)
.await
{
Ok(salt) => {
let server_response: Message = message_builder(
MessageType::DataTransfer,