Remove old architecture
This commit is contained in:
parent
703338ad2b
commit
5e097274bc
989
Cargo.lock
generated
989
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
10
Cargo.toml
@ -9,18 +9,18 @@ members = [
|
|||||||
# actors
|
# actors
|
||||||
"crates/account_manager",
|
"crates/account_manager",
|
||||||
"crates/cart_manager",
|
"crates/cart_manager",
|
||||||
"crates/database_manager",
|
# "crates/database_manager",
|
||||||
"crates/email_manager",
|
"crates/email_manager",
|
||||||
"crates/order_manager",
|
# "crates/order_manager",
|
||||||
"crates/payment_manager",
|
# "crates/payment_manager",
|
||||||
"crates/search_manager",
|
"crates/search_manager",
|
||||||
"crates/stock_manager",
|
"crates/stock_manager",
|
||||||
"crates/token_manager",
|
"crates/token_manager",
|
||||||
"crates/fs_manager",
|
"crates/fs_manager",
|
||||||
"crates/lang_provider",
|
"crates/lang_provider",
|
||||||
# artifacts
|
# artifacts
|
||||||
"crates/db-seed",
|
# "crates/db-seed",
|
||||||
"crates/api",
|
# "crates/api",
|
||||||
"crates/web",
|
"crates/web",
|
||||||
# vendor
|
# vendor
|
||||||
"vendor/t_pay",
|
"vendor/t_pay",
|
||||||
|
@ -1,43 +1,73 @@
|
|||||||
use channels::accounts::{me, register};
|
use channels::accounts::{all, find_by_identity, me, register};
|
||||||
use config::SharedAppConfig;
|
use config::SharedAppConfig;
|
||||||
use model::{Encrypt, FullAccount};
|
use model::{Encrypt, FullAccount, Ranged};
|
||||||
|
|
||||||
use crate::db::{AccountAddresses, Database, FindAccount};
|
use crate::db::{AccountAddresses, Database, FindAccount};
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
|
||||||
#[allow(unused)]
|
macro_rules! ok_or_rollback {
|
||||||
|
($res: expr, $t: expr, $err: expr) => {
|
||||||
|
match $res {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("{}", e);
|
||||||
|
$t.rollback().await.ok();
|
||||||
|
|
||||||
|
return Err($err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! begin_t {
|
||||||
|
($db: expr, $err: expr) => {
|
||||||
|
match $db.pool.begin().await {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("{}", e);
|
||||||
|
return Err($err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn all(input: all::Input, db: Database) -> all::Output {
|
||||||
|
use channels::accounts::Error;
|
||||||
|
|
||||||
|
let mut t = begin_t!(db, Error::DbCritical);
|
||||||
|
|
||||||
|
let dbm = crate::db::AllAccounts {
|
||||||
|
limit: input.limit.into_raw(),
|
||||||
|
offset: input.offset.into_raw(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = dbm.run(&mut t).await;
|
||||||
|
|
||||||
|
let accounts = ok_or_rollback!(res, t, Error::All);
|
||||||
|
|
||||||
|
t.commit().await.map_err(|e| {
|
||||||
|
tracing::error!("{}", e);
|
||||||
|
Error::DbCritical
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(all::Details { accounts })
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn me(account_id: model::AccountId, db: Database) -> me::Output {
|
pub async fn me(account_id: model::AccountId, db: Database) -> me::Output {
|
||||||
use channels::accounts::Error;
|
use channels::accounts::Error;
|
||||||
|
|
||||||
let mut t = match db.pool.begin().await {
|
let mut t = begin_t!(db, Error::Account);
|
||||||
Ok(t) => t,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("{}", e);
|
|
||||||
return Err(Error::Account);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let res = FindAccount { account_id }.run(&mut t).await;
|
let res = FindAccount { account_id }.run(&mut t).await;
|
||||||
let account: model::FullAccount = match res {
|
let account: FullAccount = ok_or_rollback!(res, t, Error::Account);
|
||||||
Ok(account) => account,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("{}", e);
|
|
||||||
t.rollback().await.ok();
|
|
||||||
|
|
||||||
return Err(Error::Account);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let res = AccountAddresses { account_id }.run(&mut t).await;
|
let res = AccountAddresses { account_id }.run(&mut t).await;
|
||||||
let addresses = match res {
|
let addresses = ok_or_rollback!(res, t, Error::Addresses);
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("{}", e);
|
|
||||||
t.rollback().await.ok();
|
|
||||||
|
|
||||||
return Err(Error::Addresses);
|
t.commit().await.map_err(|e| {
|
||||||
}
|
tracing::error!("{}", e);
|
||||||
};
|
Error::DbCritical
|
||||||
t.commit().await.ok();
|
})?;
|
||||||
|
|
||||||
Ok(me::Details { account, addresses })
|
Ok(me::Details { account, addresses })
|
||||||
}
|
}
|
||||||
@ -55,10 +85,8 @@ pub async fn create_account(
|
|||||||
Error::Hashing
|
Error::Hashing
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut t = db.pool.begin().await.map_err(|e| {
|
let mut t = begin_t!(db, Error::DbCritical);
|
||||||
tracing::error!("{}", e);
|
|
||||||
Error::DbCritical
|
|
||||||
})?;
|
|
||||||
let res = crate::db::CreateAccount {
|
let res = crate::db::CreateAccount {
|
||||||
email: msg.email,
|
email: msg.email,
|
||||||
login: msg.login,
|
login: msg.login,
|
||||||
@ -68,14 +96,8 @@ pub async fn create_account(
|
|||||||
.run(&mut t)
|
.run(&mut t)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let account: FullAccount = match res {
|
let account: FullAccount = ok_or_rollback!(res, t, Error::Saving);
|
||||||
Ok(r) => r,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("{}", e);
|
|
||||||
t.rollback().await.ok();
|
|
||||||
return Err(Error::Saving);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
t.commit().await.map_err(|e| {
|
t.commit().await.map_err(|e| {
|
||||||
tracing::error!("{}", e);
|
tracing::error!("{}", e);
|
||||||
Error::DbCritical
|
Error::DbCritical
|
||||||
@ -83,3 +105,22 @@ pub async fn create_account(
|
|||||||
|
|
||||||
Ok(account)
|
Ok(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn find_by_identity(
|
||||||
|
input: find_by_identity::Input,
|
||||||
|
db: Database,
|
||||||
|
) -> find_by_identity::Output {
|
||||||
|
use channels::accounts::Error;
|
||||||
|
|
||||||
|
let mut t = begin_t!(db, Error::DbCritical);
|
||||||
|
let dbm = crate::db::AccountByIdentity {
|
||||||
|
login: input.login,
|
||||||
|
email: input.email,
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = dbm.run(&mut t).await;
|
||||||
|
|
||||||
|
let account: FullAccount = ok_or_rollback!(res, t, Error::InvalidIdentity);
|
||||||
|
|
||||||
|
Ok(find_by_identity::Details { account })
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use channels::accounts::rpc::Accounts;
|
use channels::accounts::rpc::Accounts;
|
||||||
use channels::accounts::{me, register};
|
use channels::accounts::{all, find_by_identity, me, register};
|
||||||
use channels::AsyncClient;
|
use channels::AsyncClient;
|
||||||
use config::SharedAppConfig;
|
use config::SharedAppConfig;
|
||||||
use tarpc::context;
|
use tarpc::context;
|
||||||
@ -54,6 +54,22 @@ impl Accounts for AccountsServer {
|
|||||||
Err(_e) => Err(Error::Account),
|
Err(_e) => Err(Error::Account),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn all(self, _: context::Context, input: all::Input) -> all::Output {
|
||||||
|
let res = actions::all(input, self.db).await;
|
||||||
|
tracing::info!("ME result: {:?}", res);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_by_identity(
|
||||||
|
self,
|
||||||
|
_: context::Context,
|
||||||
|
input: find_by_identity::Input,
|
||||||
|
) -> find_by_identity::Output {
|
||||||
|
let res = actions::find_by_identity(input, self.db).await;
|
||||||
|
tracing::info!("ME result: {:?}", res);
|
||||||
|
res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(config: SharedAppConfig, db: Database, mqtt_client: AsyncClient) {
|
pub async fn start(config: SharedAppConfig, db: Database, mqtt_client: AsyncClient) {
|
||||||
|
@ -21,7 +21,7 @@ bytes = { version = "1.1.0" }
|
|||||||
channels = { path = "../channels", features = ['accounts', 'carts', 'emails', 'search'] }
|
channels = { path = "../channels", features = ['accounts', 'carts', 'emails', 'search'] }
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
database_manager = { path = "../database_manager" }
|
#database_manager = { path = "../database_manager" }
|
||||||
derive_more = { version = "0.99", features = [] }
|
derive_more = { version = "0.99", features = [] }
|
||||||
dotenv = { version = "0.15", features = [] }
|
dotenv = { version = "0.15", features = [] }
|
||||||
fs_manager = { path = "../fs_manager" }
|
fs_manager = { path = "../fs_manager" }
|
||||||
|
@ -36,8 +36,6 @@ pub enum Error {
|
|||||||
PassFile(std::io::Error),
|
PassFile(std::io::Error),
|
||||||
#[error("Unable to read password from STDIN. {0:?}")]
|
#[error("Unable to read password from STDIN. {0:?}")]
|
||||||
ReadPass(std::io::Error),
|
ReadPass(std::io::Error),
|
||||||
#[error("{0}")]
|
|
||||||
Database(#[from] database_manager::Error),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
@ -3,8 +3,9 @@ use actix_web::web::{Data, Json, ServiceConfig};
|
|||||||
use actix_web::{get, patch, post, HttpResponse};
|
use actix_web::{get, patch, post, HttpResponse};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use config::SharedAppConfig;
|
use config::SharedAppConfig;
|
||||||
use database_manager::Database;
|
use model::{
|
||||||
use model::{AccountAddress, AccountId, AccountState, Encrypt, PasswordConfirmation};
|
AccountAddress, AccountId, AccountState, Encrypt, Limit, Offset, PasswordConfirmation,
|
||||||
|
};
|
||||||
use token_manager::TokenManager;
|
use token_manager::TokenManager;
|
||||||
|
|
||||||
use crate::routes::admin::Error;
|
use crate::routes::admin::Error;
|
||||||
@ -15,11 +16,23 @@ use crate::{admin_send_db, routes, Email, Login, PassHash, Password, Role};
|
|||||||
pub async fn accounts(
|
pub async fn accounts(
|
||||||
credentials: BearerAuth,
|
credentials: BearerAuth,
|
||||||
tm: Data<Addr<TokenManager>>,
|
tm: Data<Addr<TokenManager>>,
|
||||||
db: Data<Addr<Database>>,
|
am: Data<AccountsClient>,
|
||||||
) -> routes::Result<HttpResponse> {
|
) -> routes::Result<HttpResponse> {
|
||||||
|
use channels::accounts::rpc::Accounts;
|
||||||
|
|
||||||
credentials.require_admin(tm.into_inner()).await?;
|
credentials.require_admin(tm.into_inner()).await?;
|
||||||
|
|
||||||
let accounts = admin_send_db!(db, database_manager::AllAccounts);
|
let res = am
|
||||||
|
.all(
|
||||||
|
tarpc::context::current(),
|
||||||
|
channels::accounts::all::Input {
|
||||||
|
limit: Limit::default(),
|
||||||
|
offset: Offset::from_u32(0),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let accounts = res.unwrap_or_default();
|
||||||
Ok(HttpResponse::Ok().json(accounts))
|
Ok(HttpResponse::Ok().json(accounts))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +51,7 @@ pub struct UpdateAccountInput {
|
|||||||
pub async fn update_account(
|
pub async fn update_account(
|
||||||
credentials: BearerAuth,
|
credentials: BearerAuth,
|
||||||
tm: Data<Addr<TokenManager>>,
|
tm: Data<Addr<TokenManager>>,
|
||||||
|
am: Data<AccountsClient>,
|
||||||
db: Data<Addr<Database>>,
|
db: Data<Addr<Database>>,
|
||||||
Json(payload): Json<UpdateAccountInput>,
|
Json(payload): Json<UpdateAccountInput>,
|
||||||
config: Data<SharedAppConfig>,
|
config: Data<SharedAppConfig>,
|
||||||
@ -87,6 +101,7 @@ pub async fn create_account(
|
|||||||
credentials: BearerAuth,
|
credentials: BearerAuth,
|
||||||
tm: Data<Addr<TokenManager>>,
|
tm: Data<Addr<TokenManager>>,
|
||||||
db: Data<Addr<Database>>,
|
db: Data<Addr<Database>>,
|
||||||
|
am: Data<AccountsClient>,
|
||||||
Json(payload): Json<model::api::admin::RegisterInput>,
|
Json(payload): Json<model::api::admin::RegisterInput>,
|
||||||
config: Data<SharedAppConfig>,
|
config: Data<SharedAppConfig>,
|
||||||
) -> routes::Result<Json<model::api::admin::RegisterResponse>> {
|
) -> routes::Result<Json<model::api::admin::RegisterResponse>> {
|
||||||
|
@ -8,7 +8,6 @@ use actix::Addr;
|
|||||||
use actix_web::web::{scope, Data, Json, ServiceConfig};
|
use actix_web::web::{scope, Data, Json, ServiceConfig};
|
||||||
use actix_web::{delete, post};
|
use actix_web::{delete, post};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use database_manager::{query_db, Database};
|
|
||||||
use model::Encrypt;
|
use model::Encrypt;
|
||||||
use token_manager::TokenManager;
|
use token_manager::TokenManager;
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ use actix::Addr;
|
|||||||
use actix_web::get;
|
use actix_web::get;
|
||||||
use actix_web::web::{Data, Json, ServiceConfig};
|
use actix_web::web::{Data, Json, ServiceConfig};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use database_manager::Database;
|
|
||||||
use model::api::Orders;
|
use model::api::Orders;
|
||||||
use token_manager::TokenManager;
|
use token_manager::TokenManager;
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ use actix_web::web::{Data, Json, ServiceConfig};
|
|||||||
use actix_web::{delete, get, patch, post, HttpResponse};
|
use actix_web::{delete, get, patch, post, HttpResponse};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use config::SharedAppConfig;
|
use config::SharedAppConfig;
|
||||||
use database_manager::Database;
|
|
||||||
use model::{
|
use model::{
|
||||||
api, Days, Price, ProductCategory, ProductId, ProductLongDesc, ProductName, ProductShortDesc,
|
api, Days, Price, ProductCategory, ProductId, ProductLongDesc, ProductName, ProductShortDesc,
|
||||||
Quantity, QuantityUnit,
|
Quantity, QuantityUnit,
|
||||||
|
@ -2,7 +2,6 @@ use actix::Addr;
|
|||||||
use actix_web::web::{Data, Json, ServiceConfig};
|
use actix_web::web::{Data, Json, ServiceConfig};
|
||||||
use actix_web::{delete, get, patch, post, HttpResponse};
|
use actix_web::{delete, get, patch, post, HttpResponse};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use database_manager::Database;
|
|
||||||
use model::{ProductId, Quantity, QuantityUnit, StockId};
|
use model::{ProductId, Quantity, QuantityUnit, StockId};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use token_manager::TokenManager;
|
use token_manager::TokenManager;
|
||||||
|
@ -3,7 +3,6 @@ use actix_multipart::Multipart;
|
|||||||
use actix_web::web::{Data, ServiceConfig};
|
use actix_web::web::{Data, ServiceConfig};
|
||||||
use actix_web::{post, HttpResponse};
|
use actix_web::{post, HttpResponse};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use database_manager::{query_db, Database};
|
|
||||||
use fs_manager::FsManager;
|
use fs_manager::FsManager;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use token_manager::TokenManager;
|
use token_manager::TokenManager;
|
||||||
|
@ -2,7 +2,6 @@ use actix::Addr;
|
|||||||
use actix_web::web::{scope, Data, Json, ServiceConfig};
|
use actix_web::web::{scope, Data, Json, ServiceConfig};
|
||||||
use actix_web::{delete, get, post, put, HttpRequest, HttpResponse};
|
use actix_web::{delete, get, post, put, HttpRequest, HttpResponse};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use database_manager::{query_db, Database};
|
|
||||||
use model::api;
|
use model::api;
|
||||||
use order_manager::{query_order, OrderManager};
|
use order_manager::{query_order, OrderManager};
|
||||||
use payment_manager::{query_pay, PaymentManager};
|
use payment_manager::{query_pay, PaymentManager};
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
use actix_web::web::{Data, Json, Path, Query, ServiceConfig};
|
use actix_web::web::{Data, Json, Path, Query, ServiceConfig};
|
||||||
use actix_web::{get, post, HttpResponse};
|
use actix_web::{get, post, HttpResponse};
|
||||||
|
use channels::accounts::rpc::{Accounts, AccountsClient};
|
||||||
|
use channels::stocks::rpc::{Stocks, StocksClient};
|
||||||
use config::SharedAppConfig;
|
use config::SharedAppConfig;
|
||||||
use database_manager::{query_db, Database};
|
|
||||||
use model::Encrypt;
|
use model::Encrypt;
|
||||||
use payment_manager::{PaymentManager, PaymentNotification};
|
use payment_manager::{PaymentManager, PaymentNotification};
|
||||||
use token_manager::TokenManager;
|
use token_manager::TokenManager;
|
||||||
@ -13,7 +14,7 @@ use crate::routes::{self};
|
|||||||
|
|
||||||
#[get("/search")]
|
#[get("/search")]
|
||||||
async fn search(
|
async fn search(
|
||||||
db: Data<Addr<Database>>,
|
am: Data<AccountsClient>,
|
||||||
_config: Data<SharedAppConfig>,
|
_config: Data<SharedAppConfig>,
|
||||||
search: Data<channels::search::rpc::SearchClient>,
|
search: Data<channels::search::rpc::SearchClient>,
|
||||||
query: Query<model::api::SearchRequest>,
|
query: Query<model::api::SearchRequest>,
|
||||||
@ -56,7 +57,7 @@ async fn search(
|
|||||||
|
|
||||||
#[get("/products")]
|
#[get("/products")]
|
||||||
async fn products(
|
async fn products(
|
||||||
db: Data<Addr<Database>>,
|
am: Data<AccountsClient>,
|
||||||
config: Data<SharedAppConfig>,
|
config: Data<SharedAppConfig>,
|
||||||
) -> routes::Result<Json<model::api::Products>> {
|
) -> routes::Result<Json<model::api::Products>> {
|
||||||
let db = db.into_inner();
|
let db = db.into_inner();
|
||||||
@ -85,7 +86,7 @@ async fn products(
|
|||||||
#[get("/product/{id}")]
|
#[get("/product/{id}")]
|
||||||
async fn product(
|
async fn product(
|
||||||
path: Path<model::RecordId>,
|
path: Path<model::RecordId>,
|
||||||
db: Data<Addr<Database>>,
|
am: Data<AccountsClient>,
|
||||||
config: Data<SharedAppConfig>,
|
config: Data<SharedAppConfig>,
|
||||||
) -> routes::Result<Json<model::api::Product>> {
|
) -> routes::Result<Json<model::api::Product>> {
|
||||||
let product_id: model::ProductId = path.into_inner().into();
|
let product_id: model::ProductId = path.into_inner().into();
|
||||||
@ -123,14 +124,14 @@ async fn product(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/stocks")]
|
#[get("/stocks")]
|
||||||
async fn stocks(db: Data<Addr<Database>>) -> routes::Result<Json<Vec<model::Stock>>> {
|
async fn stocks(sc: Data<StocksClient>) -> routes::Result<Json<Vec<model::Stock>>> {
|
||||||
let stocks = public_send_db!(owned, db.into_inner(), database_manager::AllStocks);
|
let stocks = public_send_db!(owned, db.into_inner(), database_manager::AllStocks);
|
||||||
Ok(Json(stocks))
|
Ok(Json(stocks))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/register")]
|
#[post("/register")]
|
||||||
pub async fn create_account(
|
pub async fn create_account(
|
||||||
db: Data<Addr<Database>>,
|
am: Data<AccountsClient>,
|
||||||
Json(payload): Json<model::api::CreateAccountInput>,
|
Json(payload): Json<model::api::CreateAccountInput>,
|
||||||
config: Data<SharedAppConfig>,
|
config: Data<SharedAppConfig>,
|
||||||
tm: Data<Addr<TokenManager>>,
|
tm: Data<Addr<TokenManager>>,
|
||||||
@ -180,7 +181,7 @@ pub async fn create_account(
|
|||||||
#[post("/sign-in")]
|
#[post("/sign-in")]
|
||||||
async fn sign_in(
|
async fn sign_in(
|
||||||
Json(payload): Json<model::api::SignInInput>,
|
Json(payload): Json<model::api::SignInInput>,
|
||||||
db: Data<Addr<Database>>,
|
am: Data<AccountsClient>,
|
||||||
tm: Data<Addr<TokenManager>>,
|
tm: Data<Addr<TokenManager>>,
|
||||||
) -> routes::Result<Json<model::api::SessionOutput>> {
|
) -> routes::Result<Json<model::api::SessionOutput>> {
|
||||||
let db = db.into_inner();
|
let db = db.into_inner();
|
||||||
|
@ -6,14 +6,20 @@ use crate::{AsyncClient, DeserializePayload};
|
|||||||
|
|
||||||
#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
#[error("Unable to connect to database")]
|
||||||
|
DbCritical,
|
||||||
#[error("mqtt payload has invalid create account data")]
|
#[error("mqtt payload has invalid create account data")]
|
||||||
InvalidCreateAccount,
|
InvalidCreateAccount,
|
||||||
#[error("mqtt payload has invalid account failure data")]
|
#[error("mqtt payload has invalid account failure data")]
|
||||||
InvalidAccountFailure,
|
InvalidAccountFailure,
|
||||||
|
#[error("All accounts can't be loaded")]
|
||||||
|
All,
|
||||||
#[error("Account does not exists")]
|
#[error("Account does not exists")]
|
||||||
Account,
|
Account,
|
||||||
#[error("Account does have any addresses")]
|
#[error("Account does have any addresses")]
|
||||||
Addresses,
|
Addresses,
|
||||||
|
#[error("No account for identity found")]
|
||||||
|
InvalidIdentity,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static CLIENT_NAME: &str = "account-manager";
|
pub static CLIENT_NAME: &str = "account-manager";
|
||||||
@ -106,6 +112,44 @@ pub mod me {
|
|||||||
pub type Output = Result<Details, Error>;
|
pub type Output = Result<Details, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod all {
|
||||||
|
use model::{Limit, Offset};
|
||||||
|
|
||||||
|
use crate::accounts::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct Input {
|
||||||
|
pub limit: Limit,
|
||||||
|
pub offset: Offset,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct Details {
|
||||||
|
pub accounts: Vec<model::FullAccount>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Output = Result<Details, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod find_by_identity {
|
||||||
|
use model::{Email, Login};
|
||||||
|
|
||||||
|
use crate::accounts::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct Input {
|
||||||
|
pub login: Option<Login>,
|
||||||
|
pub email: Option<Email>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct Details {
|
||||||
|
pub account: model::FullAccount,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Output = Result<Details, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
impl AsyncClient {
|
impl AsyncClient {
|
||||||
pub async fn emit_account_created(&self, account: &model::FullAccount) {
|
pub async fn emit_account_created(&self, account: &model::FullAccount) {
|
||||||
self.publish_or_log(Topic::AccountCreated, QoS::AtLeastOnce, true, account)
|
self.publish_or_log(Topic::AccountCreated, QoS::AtLeastOnce, true, account)
|
||||||
@ -116,7 +160,7 @@ impl AsyncClient {
|
|||||||
pub mod rpc {
|
pub mod rpc {
|
||||||
use config::SharedAppConfig;
|
use config::SharedAppConfig;
|
||||||
|
|
||||||
use crate::accounts::{me, register};
|
use crate::accounts::{all, find_by_identity, me, register};
|
||||||
|
|
||||||
#[tarpc::service]
|
#[tarpc::service]
|
||||||
pub trait Accounts {
|
pub trait Accounts {
|
||||||
@ -125,6 +169,12 @@ pub mod rpc {
|
|||||||
|
|
||||||
/// Creates new user account.
|
/// Creates new user account.
|
||||||
async fn register_account(input: register::Input) -> register::Output;
|
async fn register_account(input: register::Input) -> register::Output;
|
||||||
|
|
||||||
|
/// Load full data about all accounts
|
||||||
|
async fn all(input: all::Input) -> all::Output;
|
||||||
|
|
||||||
|
/// Find account for email and/or login
|
||||||
|
async fn find_by_identity(input: find_by_identity::Input) -> find_by_identity::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_client(config: SharedAppConfig) -> AccountsClient {
|
pub async fn create_client(config: SharedAppConfig) -> AccountsClient {
|
||||||
|
@ -48,7 +48,6 @@ FROM accounts
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
|
||||||
#[derive(actix::Message, Debug)]
|
#[derive(actix::Message, Debug)]
|
||||||
#[rtype(result = "Result<FullAccount>")]
|
#[rtype(result = "Result<FullAccount>")]
|
||||||
pub struct CreateAccount {
|
pub struct CreateAccount {
|
||||||
@ -88,7 +87,6 @@ RETURNING id, email, login, pass_hash, role, customer_id, state
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
|
||||||
#[derive(actix::Message)]
|
#[derive(actix::Message)]
|
||||||
#[rtype(result = "Result<FullAccount>")]
|
#[rtype(result = "Result<FullAccount>")]
|
||||||
pub struct UpdateAccount {
|
pub struct UpdateAccount {
|
||||||
|
@ -3,17 +3,17 @@ use config::SharedAppConfig;
|
|||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use sqlx_core::arguments::Arguments;
|
use sqlx_core::arguments::Arguments;
|
||||||
|
|
||||||
pub use crate::account_addresses::*;
|
// pub use crate::account_addresses::*;
|
||||||
pub use crate::accounts::*;
|
// pub use crate::accounts::*;
|
||||||
pub use crate::order_addresses::*;
|
pub use crate::order_addresses::*;
|
||||||
pub use crate::order_items::*;
|
pub use crate::order_items::*;
|
||||||
pub use crate::orders::*;
|
pub use crate::orders::*;
|
||||||
pub use crate::photos::*;
|
// pub use crate::photos::*;
|
||||||
pub use crate::product_photos::*;
|
// pub use crate::product_photos::*;
|
||||||
pub use crate::products::*;
|
// pub use crate::products::*;
|
||||||
pub use crate::shopping_cart_items::*;
|
pub use crate::shopping_cart_items::*;
|
||||||
pub use crate::shopping_carts::*;
|
pub use crate::shopping_carts::*;
|
||||||
pub use crate::stocks::*;
|
// pub use crate::stocks::*;
|
||||||
pub use crate::tokens::*;
|
pub use crate::tokens::*;
|
||||||
|
|
||||||
pub mod account_addresses;
|
pub mod account_addresses;
|
||||||
|
@ -49,7 +49,6 @@ ORDER BY id DESC
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
|
||||||
#[derive(actix::Message)]
|
#[derive(actix::Message)]
|
||||||
#[rtype(result = "Result<OrderItem>")]
|
#[rtype(result = "Result<OrderItem>")]
|
||||||
pub struct CreateOrderItem {
|
pub struct CreateOrderItem {
|
||||||
|
@ -92,7 +92,6 @@ WHERE id = $1
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
|
||||||
#[derive(Message, Debug)]
|
#[derive(Message, Debug)]
|
||||||
#[rtype(result = "Result<model::Product>")]
|
#[rtype(result = "Result<model::Product>")]
|
||||||
pub struct CreateProduct {
|
pub struct CreateProduct {
|
||||||
|
@ -4,14 +4,10 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = { version = "0.13", features = [] }
|
|
||||||
actix-rt = { version = "2.7", features = [] }
|
|
||||||
actix-web = { version = "4.0", features = [] }
|
|
||||||
bytes = { version = "1.1.0" }
|
bytes = { version = "1.1.0" }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
database_manager = { path = "../database_manager", features = ["dummy"] }
|
|
||||||
dotenv = { version = "0.15", features = [] }
|
dotenv = { version = "0.15", features = [] }
|
||||||
fake = { version = "2.4.3", features = ["derive", "chrono", "http"] }
|
fakeit = { version = "1.1.1", features = [] }
|
||||||
fs_manager = { path = "../fs_manager", features = [] }
|
fs_manager = { path = "../fs_manager", features = [] }
|
||||||
human-panic = { version = "1.0.3" }
|
human-panic = { version = "1.0.3" }
|
||||||
model = { path = "../model", version = "0.1", features = ["db", "dummy"] }
|
model = { path = "../model", version = "0.1", features = ["db", "dummy"] }
|
||||||
@ -21,3 +17,6 @@ thiserror = { version = "1.0.31" }
|
|||||||
tokio = { version = "1.18.1", features = ["full"] }
|
tokio = { version = "1.18.1", features = ["full"] }
|
||||||
tracing = { version = "0.1.34" }
|
tracing = { version = "0.1.34" }
|
||||||
tracing-subscriber = { version = "0.3.11" }
|
tracing-subscriber = { version = "0.3.11" }
|
||||||
|
account-manager = { path = '../account_manager' }
|
||||||
|
stock-manager = { path = "../stock_manager" }
|
||||||
|
channels = { path = '../channels' }
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
use actix::Addr;
|
|
||||||
use config::SharedAppConfig;
|
use config::SharedAppConfig;
|
||||||
use database_manager::{query_db, Database};
|
|
||||||
use fake::{Fake, Faker};
|
|
||||||
|
|
||||||
use crate::{Result, SharedState};
|
use crate::{Result, SharedState};
|
||||||
|
|
||||||
pub(crate) async fn create_accounts(
|
pub(crate) async fn create_accounts(
|
||||||
db: Addr<Database>,
|
ac: AccountsClient,
|
||||||
seed: SharedState,
|
seed: SharedState,
|
||||||
_config: SharedAppConfig,
|
_config: SharedAppConfig,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@ -19,7 +16,7 @@ pub(crate) async fn create_accounts(
|
|||||||
|
|
||||||
let mut accounts = Vec::with_capacity(10);
|
let mut accounts = Vec::with_capacity(10);
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let msg: database_manager::CreateAccount = Faker.fake::<database_manager::CreateAccount>();
|
let msg: database_manager::CreateAccount = CreateA;
|
||||||
|
|
||||||
match db.send(msg).await {
|
match db.send(msg).await {
|
||||||
Ok(Ok(account)) => accounts.push(account),
|
Ok(Ok(account)) => accounts.push(account),
|
||||||
|
@ -38,7 +38,7 @@ pub(crate) struct DbSeed {
|
|||||||
|
|
||||||
pub(crate) type SharedState = Arc<Mutex<DbSeed>>;
|
pub(crate) type SharedState = Arc<Mutex<DbSeed>>;
|
||||||
|
|
||||||
#[actix_web::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
human_panic::setup_panic!();
|
human_panic::setup_panic!();
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use derive_more::Deref;
|
use derive_more::Deref;
|
||||||
#[cfg(feature = "dummy")]
|
|
||||||
use fake::Fake;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
@ -10,10 +10,6 @@ use std::ops::{BitOr, Range};
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use derive_more::{Deref, DerefMut, Display, From};
|
use derive_more::{Deref, DerefMut, Display, From};
|
||||||
#[cfg(feature = "dummy")]
|
|
||||||
use fake::Fake;
|
|
||||||
#[cfg(feature = "dummy")]
|
|
||||||
use rand::Rng;
|
|
||||||
use serde::de::{Error, Visitor};
|
use serde::de::{Error, Visitor};
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
|
|
||||||
@ -314,22 +310,17 @@ pub trait Ranged: Sized + From<u32> + Copy {
|
|||||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||||
#[derive(
|
#[derive(
|
||||||
Default,
|
Debug, Copy, Clone, Hash, PartialOrd, PartialEq, Eq, Serialize, Deserialize, Deref, From,
|
||||||
Debug,
|
|
||||||
Copy,
|
|
||||||
Clone,
|
|
||||||
Hash,
|
|
||||||
PartialOrd,
|
|
||||||
PartialEq,
|
|
||||||
Eq,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
Deref,
|
|
||||||
From,
|
|
||||||
)]
|
)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct Limit(NonNegative);
|
pub struct Limit(NonNegative);
|
||||||
|
|
||||||
|
impl Default for Limit {
|
||||||
|
fn default() -> Self {
|
||||||
|
200.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<u32> for Limit {
|
impl From<u32> for Limit {
|
||||||
fn from(value: u32) -> Self {
|
fn from(value: u32) -> Self {
|
||||||
Self::from_u32(value)
|
Self::from_u32(value)
|
||||||
@ -965,8 +956,6 @@ impl ProductCategory {
|
|||||||
|
|
||||||
pub mod v2 {
|
pub mod v2 {
|
||||||
use derive_more::{Deref, Display, From};
|
use derive_more::{Deref, Display, From};
|
||||||
#[cfg(feature = "dummy")]
|
|
||||||
use fake::Fake;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
@ -23,7 +23,7 @@ CREATE TABLE products (
|
|||||||
|
|
||||||
CREATE TABLE product_variants (
|
CREATE TABLE product_variants (
|
||||||
id serial NOT NULL PRIMARY KEY,
|
id serial NOT NULL PRIMARY KEY,
|
||||||
product_id integer REFERENCES products (id) NOT NULL,
|
product_id integer REFERENCES products (id) ON DELETE CASCADE NOT NULL,
|
||||||
"name" character varying NOT NULL,
|
"name" character varying NOT NULL,
|
||||||
short_description character varying NOT NULL,
|
short_description character varying NOT NULL,
|
||||||
long_description character varying NOT NULL,
|
long_description character varying NOT NULL,
|
||||||
@ -33,7 +33,7 @@ CREATE TABLE product_variants (
|
|||||||
|
|
||||||
CREATE TABLE stocks (
|
CREATE TABLE stocks (
|
||||||
id serial NOT NULL PRIMARY KEY,
|
id serial NOT NULL PRIMARY KEY,
|
||||||
product_variant_id integer REFERENCES product_variants(id) NOT NULL,
|
product_variant_id integer REFERENCES product_variants(id) ON DELETE CASCADE NOT NULL,
|
||||||
quantity integer DEFAULT 0 NOT NULL,
|
quantity integer DEFAULT 0 NOT NULL,
|
||||||
quantity_unit "QuantityUnit" NOT NULL,
|
quantity_unit "QuantityUnit" NOT NULL,
|
||||||
CONSTRAINT positive_quantity CHECK ((quantity >= 0))
|
CONSTRAINT positive_quantity CHECK ((quantity >= 0))
|
||||||
@ -41,6 +41,6 @@ CREATE TABLE stocks (
|
|||||||
|
|
||||||
CREATE TABLE product_photos (
|
CREATE TABLE product_photos (
|
||||||
id serial NOT NULL PRIMARY KEY,
|
id serial NOT NULL PRIMARY KEY,
|
||||||
product_variant_id integer REFERENCES product_variants(id) NOT NULL,
|
product_variant_id integer REFERENCES product_variants(id) ON DELETE CASCADE NOT NULL,
|
||||||
photo_id integer REFERENCES photos(id) NOT NULL
|
photo_id integer REFERENCES photos(id) NOT NULL
|
||||||
);
|
);
|
||||||
|
@ -283,4 +283,24 @@ mod tests {
|
|||||||
assert_eq!(new_product.id, product.id);
|
assert_eq!(new_product.id, product.id);
|
||||||
assert_eq!(new_product.name, new_name);
|
assert_eq!(new_product.name, new_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn delete_product() {
|
||||||
|
testx::db_t_ref!(t);
|
||||||
|
|
||||||
|
let product = test_product_with_variant(&mut t).await;
|
||||||
|
|
||||||
|
let res = inner_delete_product(
|
||||||
|
delete_product::Input {
|
||||||
|
product_id: product.id,
|
||||||
|
},
|
||||||
|
&mut t,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
testx::db_rollback!(t);
|
||||||
|
|
||||||
|
let (id, _new_product) = res.unwrap();
|
||||||
|
assert_eq!(id, product.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,12 @@ impl DeleteProductVariant {
|
|||||||
r#"
|
r#"
|
||||||
DELETE FROM product_variants
|
DELETE FROM product_variants
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
|
RETURNING id,
|
||||||
|
product_id,
|
||||||
|
name,
|
||||||
|
short_description,
|
||||||
|
long_description,
|
||||||
|
price
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(self.product_variant_id)
|
.bind(self.product_variant_id)
|
||||||
|
@ -185,6 +185,7 @@ RETURNING id,
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
tracing::error!("{e:?}");
|
tracing::error!("{e:?}");
|
||||||
|
eprintln!("{e:?}");
|
||||||
Error::Delete(self.product_id)
|
Error::Delete(self.product_id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ pub enum Error {
|
|||||||
Update(StockId),
|
Update(StockId),
|
||||||
#[error("Unable to delete stock {0:?}")]
|
#[error("Unable to delete stock {0:?}")]
|
||||||
Delete(StockId),
|
Delete(StockId),
|
||||||
|
#[error("Unable to delete all stock for variant {0:?}")]
|
||||||
|
DeleteAllProductStocks(ProductId),
|
||||||
#[error("Unable find stock for product")]
|
#[error("Unable find stock for product")]
|
||||||
ProductVariantStock,
|
ProductVariantStock,
|
||||||
#[error("Stock {0:?} does not exists")]
|
#[error("Stock {0:?} does not exists")]
|
||||||
@ -138,7 +140,10 @@ pub struct DeleteStock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DeleteStock {
|
impl DeleteStock {
|
||||||
async fn run(self, pool: &mut sqlx::Transaction<'_, sqlx::Postgres>) -> Result<Option<Stock>> {
|
pub async fn run(
|
||||||
|
self,
|
||||||
|
pool: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||||
|
) -> Result<Option<Stock>> {
|
||||||
sqlx::query_as(
|
sqlx::query_as(
|
||||||
r#"
|
r#"
|
||||||
DELETE FROM stocks
|
DELETE FROM stocks
|
||||||
|
Loading…
Reference in New Issue
Block a user