From 292b2cbdb71827d25bd1b60c15568c9f28d75d57 Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Mon, 11 Dec 2023 15:55:40 +0530 Subject: [PATCH 1/8] Stagting the Datatable --- api/src/route/app/datatable.rs | 94 +++++++++++++++++++-- api/src/server/middleware/request.rs | 13 ++- api/src/utils/config.rs | 13 ++- api/src/utils/mod.rs | 14 ++++ engine/src/controller/action.rs | 111 ++++++++++++++++++++----- entity/src/common/attachment.rs | 2 +- entity/src/test/ui/action/datatable.rs | 26 ++++-- entity/src/test/ui/action/field.rs | 27 ++++-- migration/src/migration001.rs | 18 ++-- migration/src/migration003.rs | 2 +- 10 files changed, 268 insertions(+), 52 deletions(-) diff --git a/api/src/route/app/datatable.rs b/api/src/route/app/datatable.rs index 155efdd..46d5c8c 100644 --- a/api/src/route/app/datatable.rs +++ b/api/src/route/app/datatable.rs @@ -1,13 +1,19 @@ +use std::fmt::format; +use std::time::SystemTime; use actix_web::{HttpResponse, web}; use actix_web::web::Path; -use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, ModelTrait, QueryFilter, QueryOrder}; +use chrono::Utc; +use log::{debug, info, log}; +use sea_orm::{ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseBackend, DbBackend, EntityTrait, ExecResult, IntoActiveModel, JsonValue, ModelTrait, NotSet, QueryFilter, QueryOrder, QueryResult, Statement, TryGetableMany}; use sea_orm::ActiveValue::Set; use sea_orm::prelude::Uuid; use cerium::error::web::OrcaError; -use entity::test::ui::action::{action, datatable}; +use entity::test::ui::action::{action, datatable, field}; +use migration::Table; use crate::utils::config::CONFIG; +use crate::utils::replace_special_chars; /// datatable_config - this will register all the endpoint in Datatable route pub fn datatable_config(cfg: &mut web::ServiceConfig) { @@ -17,11 +23,68 @@ pub fn datatable_config(cfg: &mut web::ServiceConfig) { .route("/", web::post().to(create_datatable)) .route("/{table_id}/", web::put().to(update_action)) .route("/{table_id}/", web::delete().to(delete_action)) + .route("/{table_id}/field", web::post().to(create_new_field)) + .route("/{table_id}/data", web::get().to(get_dt_data)) + .route("/{table_id}/meta", web::get().to(get_datatable_meta)) ); } + +async fn get_dt_meta(app_id: Uuid, dt_id: i32) -> Option { + let db = &CONFIG.get().await.db_client; + let table = datatable::Entity::find() + .filter(datatable::Column::AppId.eq(app_id)).filter(datatable::Column::Id.eq(dt_id)) + .one(db).await.expect("TODO: panic message"); + if table.is_none() { + return None; + } + let mut _table: datatable::Model = table.unwrap(); + let fields = _table.find_related(field::Entity) + .all(&CONFIG.get().await.db_client).await + .expect("TODO: panic message"); + _table.fields = Some(fields); + Some(_table) +} + +async fn create_new_field(path: Path<(Uuid, i32)>, mut body: web::Json) -> Result { + let (app_id, table_id) = path.into_inner(); + let db = &CONFIG.get().await.db_client; + body.table_id = table_id; + let mut field = body.clone().into_active_model(); + field.field_id = Set(replace_special_chars(field.name.clone().unwrap().as_str(), '_')); + let result = field.insert(db).await.expect("TODO: panic message"); + let tables = field::Entity::find().filter(datatable::Column::AppId.eq(app_id)) + .order_by_asc(datatable::Column::Name).all(&CONFIG.get().await.db_client).await + .expect("TODO: panic message"); + Ok(HttpResponse::Ok().json(tables)) +} + +async fn get_dt_data(path: Path<(Uuid, i32)>) -> Result { + let (app_id, table_id) = path.into_inner(); + let db = &CONFIG.get().await.db_client; + let _table_meta = get_dt_meta(app_id, table_id).await; + if _table_meta.is_none() { + return Ok(HttpResponse::NotFound().finish()); + } + let _table = _table_meta.unwrap(); + // let query_res_vec: Vec = db + // .query_all(Statement::from_string(db.get_database_backend(), + // format!("SELECT * FROM `{}`;", _table.table_name.clone()).parse().unwrap(), + // )) + // .await.expect("TODO: panic message"); + // let unique: Vec = JsonValue::find_by_statement(Statement::from_string( + // DbBackend::Postgres, + // format!("SELECT * FROM `{}`;", _table.table_name.clone()) + // )) + // .all(db) + // .await.expect("TODO: panic message"); + Ok(HttpResponse::Ok().finish()) + // .json(unique)) +} + + /// get_datatable - list all the DataTable in Specific Application in the Orca async fn get_datatables(path: Path<(Uuid)>) -> Result { let app_id = path.into_inner(); @@ -35,11 +98,19 @@ async fn get_datatables(path: Path<(Uuid)>) -> Result { /// create_datatable - this will create new DataTable in Application in Orca async fn create_datatable(path: Path<(Uuid)>, mut body: web::Json) -> Result { let app_id = path.into_inner(); - body.id = Uuid::new_v4(); + let db = &CONFIG.get().await.db_client; body.app_id = app_id; - let table = body.clone().into_active_model(); - let result = table.insert(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); - Ok(HttpResponse::Ok().json(result)) + let mut table = body.clone().into_active_model(); + table.id = NotSet; + table.table_name = Set(format!("table_{:?}", Utc::now().timestamp_micros())); + let result = table.insert(db).await.expect("TODO: panic message"); + // TODO: this code need to revamp since this is only work on postgres + let stm = format!(r#"CREATE TABLE IF NOT EXISTS {} (id SERIAL NOT NULL PRIMARY KEY )"#, result.table_name); + let exec_res: ExecResult = db.execute( + Statement::from_string(DatabaseBackend::Postgres, stm) + ).await.expect("TODO: panic message"); + info!("{:?}", exec_res.rows_affected()); + Ok(HttpResponse::Created().json(result)) } /// update_action - this will create new Application in Orca @@ -88,3 +159,14 @@ async fn delete_action(path: Path<(Uuid, Uuid, Uuid)>) -> Result) -> Result { + let (app_id, table_id) = path.into_inner(); + let dtable = get_dt_meta(app_id, table_id).await; + if dtable.is_none(){ + return Ok(HttpResponse::NotFound().finish()); + } + Ok(HttpResponse::Ok().json(dtable.unwrap())) +} + + diff --git a/api/src/server/middleware/request.rs b/api/src/server/middleware/request.rs index c128cca..dcbeb1a 100644 --- a/api/src/server/middleware/request.rs +++ b/api/src/server/middleware/request.rs @@ -1,13 +1,16 @@ use std::future::{ready, Ready}; +use std::sync::Arc; use std::time::Instant; use actix_http::HttpMessage; use actix_web::{dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error}; use futures::future::LocalBoxFuture; use log::info; +use sea_orm::TransactionTrait; use cerium::error::web::OrcaError; use cerium::utils::uuid::request_uuid; +use migration::async_trait::async_trait; use crate::server::context::request::RequestContext; use crate::utils::config::CONFIG; @@ -43,6 +46,7 @@ pub struct RequestHandlerMiddleware { service: S, } +#[async_trait] impl Service for RequestHandlerMiddleware where S: Service, Error = Error>, @@ -55,10 +59,11 @@ where forward_ready!(service); - fn call(&self, mut req: ServiceRequest) -> Self::Future { + fn call(&self, req: ServiceRequest) -> Self::Future { let request_id = request_uuid(); let start_time = Instant::now(); info!("Starting the Request {}", &request_id.clone()); + // let authorization = req.headers().get(header::AUTHORIZATION); // if authorization.is_none() { // return Box::pin(async { Err(ErrorUnauthorized("err")) }); @@ -68,10 +73,14 @@ where req.extensions_mut().insert(rc); let fut = self.service.call(req); Box::pin(async move { - let trx = &CONFIG.get().await.db_client; + let db = &CONFIG.get().await.db_client; + let trx = db.begin().await.expect("Error form trx"); + // ext.insert(trx); + // req.extensions_mut().insert(trx); let mut _response = fut.await; // res.headers_mut().insert(HeaderName::from_static(REQUEST_ID_HEADER), // HeaderValue::from_str(&request_id).unwrap()); + // trx.commit().await.expect("error"); info!("Completed Request after - {:?}", start_time.elapsed()); // rc.end_request(); _response diff --git a/api/src/utils/config.rs b/api/src/utils/config.rs index 8515a51..7d0bc07 100644 --- a/api/src/utils/config.rs +++ b/api/src/utils/config.rs @@ -1,9 +1,10 @@ //! config module will have all configuration //! +use std::time::Duration; use async_once::AsyncOnce; use lazy_static::lazy_static; -use sea_orm::{Database, DatabaseConnection}; +use sea_orm::{ConnectOptions, Database, DatabaseConnection}; lazy_static! { pub(crate) static ref CONFIG: AsyncOnce = AsyncOnce::new(async { @@ -40,6 +41,16 @@ impl Config { uri = Some(std::env::var("DATABASE_URL").expect("DATABASE_URL must be set.")); } + // let mut opt = ConnectOptions::new(uri.unwrap()); + // opt.max_connections(100) + // .min_connections(5) + // .connect_timeout(Duration::from_secs(8)) + // .acquire_timeout(Duration::from_secs(8)) + // .idle_timeout(Duration::from_secs(8)) + // .max_lifetime(Duration::from_secs(8)) + // .sqlx_logging(true) + // .sqlx_logging_level(log::LevelFilter::Info); + // Database::connect(opt).await.expect("Error unable to connect DB") Database::connect(uri.unwrap()).await.expect("Error unable to connect DB") } } \ No newline at end of file diff --git a/api/src/utils/mod.rs b/api/src/utils/mod.rs index 78a2cdb..34ed7c5 100644 --- a/api/src/utils/mod.rs +++ b/api/src/utils/mod.rs @@ -4,3 +4,17 @@ pub(crate) mod client; pub(crate) mod config; + + +pub fn replace_special_chars(input: &str, replace_with: char) -> String { + let mut result = String::with_capacity(input.len()); + + for c in input.chars() { + if c.is_ascii_alphanumeric() || c == replace_with { + result.push(c); + } else { + result.push(replace_with); + } + } + result +} \ No newline at end of file diff --git a/engine/src/controller/action.rs b/engine/src/controller/action.rs index cb02f7b..811483a 100644 --- a/engine/src/controller/action.rs +++ b/engine/src/controller/action.rs @@ -12,66 +12,139 @@ use crate::server::driver::UIHelper; pub struct ActionController<'ccl>{ db: &'ccl DatabaseConnection, - drive: &'ccl UIHelper + driver: &'ccl UIHelper } impl<'ccl> ActionController<'ccl> { /// new - this will create new Action Controller for the application - pub fn new(db: &'ccl DatabaseConnection, drive: &'ccl UIHelper) -> ActionController<'ccl> { - Self{db, drive} + /// Creates a new instance of `ActionController` with the provided `db` and `drive` references. + /// + /// # Arguments + /// + /// * `db` - A reference to a `DatabaseConnection` object. + /// * `drive` - A reference to a `UIHelper` object. + /// + /// # Example + /// + /// ``` + /// let db = DatabaseConnection::new(); + /// let driver = UIHelper::new(); + /// let controller = ActionController::new(&db, &driver); + /// ``` + pub fn new(db: &'ccl DatabaseConnection, driver: &'ccl UIHelper) -> ActionController<'ccl> { + Self{db, driver} } + /// Asynchronous method that handles the logic for executing the "Open" action in a test case. + /// + /// # Arguments + /// + /// * `self` - A reference to the `ActionController` struct. + /// * `action` - A reference to an `action::Model` object representing the action to be executed. + /// + /// # Example + /// + /// ```rust + /// let action = action::Model::new(); + /// let controller = ActionController::new(&db, &driver); + /// controller.command_open(&action).await; + /// ``` + /// + /// # Returns + /// + /// * `Result<(), EngineError>` - If the `data_value` field is `None`, it returns an `Err` with an `EngineError::Forbidden` variant. If the `data_value` field is not `None`, it opens the URL using the `drive` object and returns `Ok(())`. async fn command_open(&self, action: &action::Model) -> EngineResult<()> { - let a = match action.to_owned().data_value { + let _action = match action.to_owned().data_value { None => Err(EngineError::Forbidden), - Some(url) => self.drive.open(url.as_str()).await + Some(url) => self.driver.open(url.as_str()).await }; Ok(()) } + /// Asynchronously enters data into a target element on a web page using a WebDriver. + /// + /// # Arguments + /// + /// * `action` - An `action::Model` object that contains the necessary information for the action, including the data value to be entered, the target value of the element, and the target kind (CSS, ID, or XPath). + /// + /// # Example + /// + /// ```rust + /// let action = action::Model { + /// data_value: Some("example data".to_string()), + /// target_value: Some("example target".to_string()), + /// target_kind: Some(ActionTargetKind::Css), + /// }; + /// ui_helper.command_enter(&action).await; + /// ``` + /// + /// # Errors + /// + /// Returns an `EngineError` if any of the required parameters (`action.data_value`, `action.target_value`, `action.target_kind`) are missing. + /// + /// # Returns + /// + /// Returns `Ok(())` if the action of entering data into the target element is successful. async fn command_enter(&self, action: &action::Model) -> EngineResult<()> { - let data_value = action.to_owned().data_value - .ok_or_else(|| EngineError::MissingParameter("action.data_value".to_string(), "".to_string()))?; - let target_value = action.to_owned().target_value - .ok_or_else(|| EngineError::MissingParameter("action.target_value".to_string(), "".to_string()))?; - let target_kind = action.to_owned().target_kind - .ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; + let data_value = action.data_value.clone().ok_or_else(|| EngineError::MissingParameter("action.data_value".to_string(), "".to_string()))?; + let target_value = action.target_value.clone().ok_or_else(|| EngineError::MissingParameter("action.target_value".to_string(), "".to_string()))?; + let target_kind = action.target_kind.clone().ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; let by_kind = match target_kind { ActionTargetKind::Css => By::Css(target_value.as_str()), ActionTargetKind::Id => By::Id(target_value.as_str()), ActionTargetKind::Xpath => By::XPath(target_value.as_str()) }; - self.drive.find(by_kind).await?.send_keys(data_value).await?; + self.driver.find(by_kind).await?.send_keys(data_value).await?; Ok(()) } + /// Performs a click action on a web element based on the provided target value and target kind. + /// + /// # Arguments + /// + /// * `action` - An instance of the `action::Model` struct that contains the target value and target kind. + /// + /// # Example + /// + /// ```rust + /// let action = action::Model { + /// data_value: Some("button".to_string()), + /// target_kind: Some(ActionTargetKind::Css), + /// }; + /// + /// ui_helper.command_click(&action); + /// ``` + /// + /// # Returns + /// + /// Returns `Ok(())` if the click action is performed successfully. async fn command_click(&self, action: &action::Model) -> EngineResult<()> { - let target_value = action.to_owned().target_value + let target_value = action.data_value.clone() .ok_or_else(|| EngineError::MissingParameter("action.target_value".to_string(), "".to_string()))?; - let target_kind = action.to_owned().target_kind + let target_kind = action.target_kind.clone() .ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; let by_kind = match target_kind { ActionTargetKind::Css => By::Css(target_value.as_str()), ActionTargetKind::Id => By::Id(target_value.as_str()), ActionTargetKind::Xpath => By::XPath(target_value.as_str()) }; - self.drive.find(by_kind).await?.click().await?; + self.driver.find(by_kind).await?.click().await?; Ok(()) } async fn command_verify_text(&self, action: &action::Model) -> EngineResult<()> { - let data_value = action.to_owned().data_value + let data_value = action.data_value.clone() .ok_or_else(|| EngineError::MissingParameter("action.data_value".to_string(), "".to_string()))?; - let target_value = action.to_owned().target_value + let target_value = action.target_value.clone() .ok_or_else(|| EngineError::MissingParameter("action.target_value".to_string(), "".to_string()))?; - let target_kind = action.to_owned().target_kind + let target_kind = action.target_kind.clone() .ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; let by_kind = match target_kind { ActionTargetKind::Css => By::Css(target_value.as_str()), ActionTargetKind::Id => By::Id(target_value.as_str()), ActionTargetKind::Xpath => By::XPath(target_value.as_str()) }; - let text = self.drive.find(by_kind).await?.inner_html().await?; + let text = self.driver.find(by_kind).await?.inner_html().await?; if text != data_value { info!("Verify text is failed {}", data_value); return Err(EngineError::MissingParameter("action.data_value".to_string(), data_value)); diff --git a/entity/src/common/attachment.rs b/entity/src/common/attachment.rs index 38f20f0..a224017 100644 --- a/entity/src/common/attachment.rs +++ b/entity/src/common/attachment.rs @@ -31,7 +31,7 @@ pub enum StorageCategory { #[sea_orm(table_name = "attachment")] pub struct Model { #[sea_orm(primary_key)] - pub id: Uuid, + pub id: i32, pub category: StorageCategory, pub reference_id: Option, pub path: String, diff --git a/entity/src/test/ui/action/datatable.rs b/entity/src/test/ui/action/datatable.rs index 6cce3fe..193c704 100644 --- a/entity/src/test/ui/action/datatable.rs +++ b/entity/src/test/ui/action/datatable.rs @@ -9,11 +9,16 @@ use serde::{Deserialize, Serialize}; pub struct Model { #[serde(skip_deserializing)] #[sea_orm(primary_key)] - pub id: Uuid, + pub id: i32, pub name: String, + #[serde(skip_deserializing)] + pub table_name: String, pub description: Option, #[serde(skip_deserializing)] - pub app_id: Uuid + pub app_id: Uuid, + + #[sea_orm(ignore)] + pub fields: Option> } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -26,14 +31,9 @@ pub enum Relation { to = "crate::app::app::Column::Id" )] App, + #[sea_orm(has_many = "super::field::Entity")] + Field, } -// -// // `Related` trait has to be implemented by hand -// impl Related for Entity { -// fn to() -> RelationDef { -// Relation::Action.def() -// } -// } impl Related for Entity { fn to() -> RelationDef { @@ -41,4 +41,12 @@ impl Related for Entity { } } + +// `Related` trait has to be implemented by hand +impl Related for Entity { + fn to() -> RelationDef { + Relation::Field.def() + } +} + impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/test/ui/action/field.rs b/entity/src/test/ui/action/field.rs index 80b4142..2ce5f0a 100644 --- a/entity/src/test/ui/action/field.rs +++ b/entity/src/test/ui/action/field.rs @@ -5,13 +5,13 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "table_kind")] +#[sea_orm(rs_type = "String", db_type = "String(Some(5))", enum_name = "table_kind")] pub enum ActionDataKind { - #[sea_orm(string_value = "String")] + #[sea_orm(string_value = "S")] String, - #[sea_orm(string_value = "Int")] + #[sea_orm(string_value = "I")] Int, - #[sea_orm(string_value = "Bool")] + #[sea_orm(string_value = "B")] Bool } @@ -20,12 +20,23 @@ pub enum ActionDataKind { pub struct Model { #[serde(skip_deserializing)] #[sea_orm(primary_key)] - pub id: Uuid, + pub field_id: String, + #[sea_orm(primary_key)] + #[serde(skip_deserializing)] + pub table_id: i32, pub name: String, pub kind: ActionDataKind, - pub option: Option, - #[serde(skip_deserializing)] - pub table_id: Uuid + pub option: Option + // #[serde(skip_deserializing)] + // #[sea_orm(primary_key)] + // pub id: i32, + // pub name: String, + // #[serde(skip_deserializing)] + // pub field_id: String, + // pub kind: ActionDataKind, + // pub option: Option, + // #[serde(skip_deserializing)] + // pub table_id: i32 } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/migration/src/migration001.rs b/migration/src/migration001.rs index b3823c2..73a4cec 100644 --- a/migration/src/migration001.rs +++ b/migration/src/migration001.rs @@ -6,6 +6,7 @@ use entity::prelude::{case, case_block, data_binding}; use entity::test::ui::action::{action, data, datatable, field, group as action_group, target}; use entity::test::ui::profile::{data as profile_data, profile}; use entity::test::ui::suit::{suite, suite_block}; +use crate::sea_orm::{ConnectionTrait, Statement}; #[derive(DeriveMigrationName)] pub struct Migration; @@ -134,9 +135,10 @@ impl MigrationTrait for Migration { manager.create_table(Table::create() .table(datatable::Entity) .if_not_exists() - .col(ColumnDef::new(datatable::Column::Id).uuid().not_null().primary_key()) + .col(ColumnDef::new(datatable::Column::Id).integer().not_null().primary_key().auto_increment()) .col(ColumnDef::new(datatable::Column::Name).string().not_null()) - .col(ColumnDef::new(datatable::Column::Description).string().not_null()) + .col(ColumnDef::new(datatable::Column::TableName).string().not_null()) + .col(ColumnDef::new(datatable::Column::Description).string()) .col(ColumnDef::new(datatable::Column::AppId).uuid().not_null()) .foreign_key( ForeignKey::create() @@ -152,11 +154,11 @@ impl MigrationTrait for Migration { manager.create_table(Table::create() .table(field::Entity) .if_not_exists() - .col(ColumnDef::new(field::Column::Id).uuid().not_null().primary_key()) + .col(ColumnDef::new(field::Column::FieldId).string().not_null()) + .col(ColumnDef::new(field::Column::TableId).integer().not_null()) .col(ColumnDef::new(field::Column::Name).string().not_null()) .col(ColumnDef::new(field::Column::Kind).string().not_null()) - .col(ColumnDef::new(field::Column::Option).string()) - .col(ColumnDef::new(field::Column::TableId).uuid().not_null()) + .col(ColumnDef::new(field::Column::Option).json()) .foreign_key( ForeignKey::create() .from(field::Entity, field::Column::TableId) @@ -166,6 +168,12 @@ impl MigrationTrait for Migration { ) .to_owned(), ).await?; + manager.get_connection().execute( + Statement::from_string( + manager.get_database_backend(), + "alter table field add constraint com_key_id primary key (field_id, table_id)".parse().unwrap()) + ) + .await?; manager.create_table(Table::create() diff --git a/migration/src/migration003.rs b/migration/src/migration003.rs index c7dfcdb..aa74ac8 100644 --- a/migration/src/migration003.rs +++ b/migration/src/migration003.rs @@ -33,7 +33,7 @@ impl MigrationTrait for Migration { manager.create_table(Table::create() .table(attachment::Entity) .if_not_exists() - .col(ColumnDef::new(attachment::Column::Id).uuid().not_null().primary_key()) + .col(ColumnDef::new(attachment::Column::Id).integer().not_null().primary_key().auto_increment()) .col(ColumnDef::new(attachment::Column::Name).string()) .col(ColumnDef::new(attachment::Column::Desc).string().not_null()) .col(ColumnDef::new(attachment::Column::Category).string().not_null()) From 8cefe1117a467e9729b5bd2aa3774600d1f8f232 Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Thu, 28 Dec 2023 20:00:57 +0530 Subject: [PATCH 2/8] Reorganised the project with all the latest version --- .cargo/config.example.toml | 32 +++ .gitignore | 6 +- Cargo.toml | 70 +++++- cerium/src/client/mod.rs | 2 - cerium/src/config.rs | 41 --- cerium/src/error/mod.rs | 5 - cerium/src/error/web.rs | 95 ------- cerium/src/utils/uuid.rs | 10 - config/default.toml | 1 + {cerium => crates/libs/cerium}/Cargo.toml | 34 ++- .../libs/cerium}/src/client/cache.rs | 0 .../libs/cerium}/src/client/db/mod.rs | 0 crates/libs/cerium/src/client/mod.rs | 43 ++++ crates/libs/cerium/src/config.rs | 20 ++ {cerium => crates/libs/cerium}/src/env.rs | 4 +- .../libs/cerium}/src/error/cerium.rs | 0 crates/libs/cerium/src/error/mod.rs | 57 +++++ crates/libs/cerium/src/error/web.rs | 95 +++++++ {cerium => crates/libs/cerium}/src/lib.rs | 0 crates/libs/cerium/src/server/mod.rs | 94 +++++++ crates/libs/cerium/src/server/request_id.rs | 15 ++ crates/libs/cerium/src/server/utils.rs | 30 +++ .../libs/cerium}/src/utils/mod.rs | 0 crates/libs/cerium/src/utils/uuid.rs | 10 + .../libs/cerium}/tests/1_init.rs | 0 crates/libs/entity/Cargo.toml | 18 ++ .../libs/entity/src/admin/group.rs | 0 crates/libs/entity/src/admin/mod.rs | 1 + .../libs/entity/src/admin/user.rs | 18 +- {entity => crates/libs/entity}/src/app/app.rs | 0 {entity => crates/libs/entity}/src/app/mod.rs | 0 .../libs/entity/src/auth}/mod.rs | 0 {entity => crates/libs/entity}/src/command.rs | 0 .../libs/entity}/src/common/attachment.rs | 0 .../libs/entity}/src/common/config.rs | 0 .../libs/entity}/src/common/mod.rs | 0 .../libs/entity}/src/common/tag.rs | 0 .../libs/entity}/src/common/tag_entity.rs | 0 crates/libs/entity/src/core/mod.rs | 8 + {entity => crates/libs/entity}/src/lib.rs | 7 +- {entity => crates/libs/entity}/src/mod.rs | 0 {entity => crates/libs/entity}/src/prelude.rs | 9 - .../libs/entity/src/test}/datatable.rs | 0 .../libs/entity/src/test}/field.rs | 17 +- crates/libs/entity/src/test/mod.rs | 4 + .../libs/entity/src/test}/profile/data.rs | 0 .../libs/entity/src/test}/profile/mod.rs | 0 .../libs/entity/src/test}/profile/profile.rs | 0 .../libs/entity}/src/test/ui/action/action.rs | 0 .../libs/entity}/src/test/ui/action/data.rs | 0 .../libs/entity}/src/test/ui/action/group.rs | 0 .../libs/entity}/src/test/ui/action/mod.rs | 2 - .../libs/entity}/src/test/ui/action/target.rs | 0 .../libs/entity}/src/test/ui/case/case.rs | 0 .../entity}/src/test/ui/case/case_block.rs | 0 .../entity}/src/test/ui/case/data_binding.rs | 0 .../libs/entity}/src/test/ui/case/mod.rs | 0 .../libs/entity}/src/test/ui/elements.rs | 0 .../libs/entity}/src/test/ui/mod.rs | 1 - .../libs/entity}/src/test/ui/screen.rs | 0 .../libs/entity}/src/test/ui/suit/mod.rs | 0 .../libs/entity}/src/test/ui/suit/suite.rs | 0 .../entity}/src/test/ui/suit/suite_block.rs | 0 crates/libs/macroni/Cargo.toml | 20 ++ crates/libs/macroni/src/lib.rs | 74 ++++++ crates/libs/migration/Cargo.toml | 32 +++ .../libs/migration}/README.md | 0 .../libs/migration}/src/lib.rs | 0 .../libs/migration}/src/main.rs | 0 .../libs/migration}/src/migration001.rs | 22 +- .../libs/migration}/src/migration002.rs | 0 .../libs/migration}/src/migration003.rs | 2 +- {api => crates/services/api-old}/Cargo.toml | 19 +- .../services/api-old}/src/bootstrap.rs | 0 {api => crates/services/api-old}/src/error.rs | 0 {api => crates/services/api-old}/src/main.rs | 2 +- .../services/api-old}/src/route/app/action.rs | 0 .../services/api-old}/src/route/app/case.rs | 0 .../api-old}/src/route/app/datatable.rs | 0 .../services/api-old}/src/route/app/group.rs | 0 .../services/api-old}/src/route/app/mod.rs | 0 .../api-old/src/route/app/object_repo.rs | 0 .../api-old}/src/route/app/profile.rs | 0 .../services/api-old}/src/route/app/suit.rs | 0 .../services/api-old}/src/route/file.rs | 0 .../services/api-old}/src/route/mod.rs | 0 .../services/api-old}/src/route/ws.rs | 0 .../api-old}/src/server/context/mod.rs | 0 .../api-old}/src/server/context/request.rs | 0 .../api-old}/src/server/middleware/mod.rs | 0 .../api-old}/src/server/middleware/request.rs | 0 .../services/api-old}/src/server/mod.rs | 0 .../services/api-old}/src/utils/client/mod.rs | 0 .../services/api-old}/src/utils/config.rs | 0 .../services/api-old}/src/utils/mod.rs | 0 {api => crates/services/api-old}/tests/mod.rs | 0 .../services/api-old}/tests/seed_data.rs | 0 crates/services/api/Cargo.toml | 40 +++ crates/services/api/src/error.rs | 77 ++++++ crates/services/api/src/main.rs | 37 +++ crates/services/api/src/route/admin/mod.rs | 1 + crates/services/api/src/route/admin/user.rs | 63 +++++ crates/services/api/src/route/app/action.rs | 59 +++++ crates/services/api/src/route/app/case.rs | 89 +++++++ crates/services/api/src/route/app/case_old.rs | 215 ++++++++++++++++ .../services/api/src/route/app/datatable.rs | 110 ++++++++ crates/services/api/src/route/app/group.rs | 48 ++++ crates/services/api/src/route/app/mod.rs | 82 ++++++ .../services/api/src/route/app/object_repo.rs | 0 crates/services/api/src/route/app/profile.rs | 65 +++++ crates/services/api/src/route/app/suit.rs | 236 ++++++++++++++++++ crates/services/api/src/route/mod.rs | 47 ++++ crates/services/api/src/route/public.rs | 12 + .../services/api/src/server/middleware/mod.rs | 62 +++++ .../api/src/server/middleware/orca.rs | 0 crates/services/api/src/server/mod.rs | 2 + crates/services/api/src/server/session.rs | 16 ++ crates/services/api/src/service/admin/mod.rs | 1 + crates/services/api/src/service/admin/user.rs | 55 ++++ crates/services/api/src/service/app/action.rs | 86 +++++++ crates/services/api/src/service/app/case.rs | 177 +++++++++++++ .../services/api/src/service/app/datatable.rs | 184 ++++++++++++++ crates/services/api/src/service/app/group.rs | 67 +++++ crates/services/api/src/service/app/mod.rs | 51 ++++ .../api/src/service/app/object_repo.rs | 0 .../services/api/src/service/app/profile.rs | 85 +++++++ crates/services/api/src/service/app/suit.rs | 103 ++++++++ crates/services/api/src/service/mod.rs | 22 ++ crates/services/api/src/utils/mod.rs | 15 ++ {engine => crates/services/engine}/Cargo.toml | 14 +- .../services/engine}/src/controller/action.rs | 17 +- .../services/engine}/src/controller/case.rs | 0 .../services/engine}/src/controller/mod.rs | 0 .../services/engine/src/controller/suite.rs | 0 .../services/engine}/src/driver/api.rs | 0 .../services/engine}/src/driver/mod.rs | 0 .../services/engine}/src/driver/ui.rs | 0 crates/services/engine/src/error.rs | 23 ++ {engine => crates/services/engine}/src/lib.rs | 0 .../services/engine}/src/server/driver.rs | 6 +- .../services/engine}/src/server/mod.rs | 0 .../services/engine}/src/ui/mod.rs | 0 .../services/engine}/src/ui/step.rs | 0 .../services/engine}/tests/controller.rs | 0 crates/web/render/Cargo.toml | 17 ++ crates/web/render/Dioxus.toml | 11 + crates/web/render/src/main.rs | 18 ++ crates/web/tail-rs/Cargo.toml | 15 ++ crates/web/tail-rs/src/button/button.rs | 19 ++ crates/web/tail-rs/src/button/mod.rs | 0 crates/web/tail-rs/src/lib.rs | 14 ++ docs/setup/config.md | 0 engine/src/error.rs | 51 ---- entity/Cargo.toml | 12 - entity/src/backup/activity.rs | 19 -- entity/src/backup/audit_log.rs | 31 --- entity/src/backup/backup.rs | 151 ----------- entity/src/backup/profile.rs | 38 --- entity/src/backup/profile_data.rs | 46 ---- entity/src/backup/role.rs | 36 --- entity/src/backup/role_scope.rs | 35 --- entity/src/backup/test_action.rs | 54 ---- entity/src/backup/test_case.rs | 32 --- entity/src/backup/test_step.rs | 51 ---- entity/src/backup/user.rs | 91 ------- entity/src/backup/user_group.rs | 46 ---- entity/src/backup/user_role.rs | 46 ---- entity/src/backup/user_session.rs | 57 ----- entity/src/test/mod.rs | 1 - migration/Cargo.toml | 23 -- start.sh | 2 + 171 files changed, 2954 insertions(+), 1049 deletions(-) create mode 100644 .cargo/config.example.toml delete mode 100644 cerium/src/client/mod.rs delete mode 100644 cerium/src/config.rs delete mode 100644 cerium/src/error/mod.rs delete mode 100644 cerium/src/error/web.rs delete mode 100644 cerium/src/utils/uuid.rs rename {cerium => crates/libs/cerium}/Cargo.toml (50%) rename {cerium => crates/libs/cerium}/src/client/cache.rs (100%) rename {cerium => crates/libs/cerium}/src/client/db/mod.rs (100%) create mode 100644 crates/libs/cerium/src/client/mod.rs create mode 100644 crates/libs/cerium/src/config.rs rename {cerium => crates/libs/cerium}/src/env.rs (81%) rename {cerium => crates/libs/cerium}/src/error/cerium.rs (100%) create mode 100644 crates/libs/cerium/src/error/mod.rs create mode 100644 crates/libs/cerium/src/error/web.rs rename {cerium => crates/libs/cerium}/src/lib.rs (100%) create mode 100644 crates/libs/cerium/src/server/mod.rs create mode 100644 crates/libs/cerium/src/server/request_id.rs create mode 100644 crates/libs/cerium/src/server/utils.rs rename {cerium => crates/libs/cerium}/src/utils/mod.rs (100%) create mode 100644 crates/libs/cerium/src/utils/uuid.rs rename {cerium => crates/libs/cerium}/tests/1_init.rs (100%) create mode 100644 crates/libs/entity/Cargo.toml rename api/src/route/app/object_repo.rs => crates/libs/entity/src/admin/group.rs (100%) create mode 100644 crates/libs/entity/src/admin/mod.rs rename entity/src/backup/group.rs => crates/libs/entity/src/admin/user.rs (59%) rename {entity => crates/libs/entity}/src/app/app.rs (100%) rename {entity => crates/libs/entity}/src/app/mod.rs (100%) rename {cerium/src/server => crates/libs/entity/src/auth}/mod.rs (100%) rename {entity => crates/libs/entity}/src/command.rs (100%) rename {entity => crates/libs/entity}/src/common/attachment.rs (100%) rename {entity => crates/libs/entity}/src/common/config.rs (100%) rename {entity => crates/libs/entity}/src/common/mod.rs (100%) rename {entity => crates/libs/entity}/src/common/tag.rs (100%) rename {entity => crates/libs/entity}/src/common/tag_entity.rs (100%) create mode 100644 crates/libs/entity/src/core/mod.rs rename {entity => crates/libs/entity}/src/lib.rs (79%) rename {entity => crates/libs/entity}/src/mod.rs (100%) rename {entity => crates/libs/entity}/src/prelude.rs (57%) rename {entity/src/test/ui/action => crates/libs/entity/src/test}/datatable.rs (100%) rename {entity/src/test/ui/action => crates/libs/entity/src/test}/field.rs (77%) create mode 100644 crates/libs/entity/src/test/mod.rs rename {entity/src/test/ui => crates/libs/entity/src/test}/profile/data.rs (100%) rename {entity/src/test/ui => crates/libs/entity/src/test}/profile/mod.rs (100%) rename {entity/src/test/ui => crates/libs/entity/src/test}/profile/profile.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/action/action.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/action/data.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/action/group.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/action/mod.rs (64%) rename {entity => crates/libs/entity}/src/test/ui/action/target.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/case/case.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/case/case_block.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/case/data_binding.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/case/mod.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/elements.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/mod.rs (81%) rename {entity => crates/libs/entity}/src/test/ui/screen.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/suit/mod.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/suit/suite.rs (100%) rename {entity => crates/libs/entity}/src/test/ui/suit/suite_block.rs (100%) create mode 100644 crates/libs/macroni/Cargo.toml create mode 100644 crates/libs/macroni/src/lib.rs create mode 100644 crates/libs/migration/Cargo.toml rename {migration => crates/libs/migration}/README.md (100%) rename {migration => crates/libs/migration}/src/lib.rs (100%) rename {migration => crates/libs/migration}/src/main.rs (100%) rename {migration => crates/libs/migration}/src/migration001.rs (94%) rename {migration => crates/libs/migration}/src/migration002.rs (100%) rename {migration => crates/libs/migration}/src/migration003.rs (99%) rename {api => crates/services/api-old}/Cargo.toml (76%) rename {api => crates/services/api-old}/src/bootstrap.rs (100%) rename {api => crates/services/api-old}/src/error.rs (100%) rename {api => crates/services/api-old}/src/main.rs (90%) rename {api => crates/services/api-old}/src/route/app/action.rs (100%) rename {api => crates/services/api-old}/src/route/app/case.rs (100%) rename {api => crates/services/api-old}/src/route/app/datatable.rs (100%) rename {api => crates/services/api-old}/src/route/app/group.rs (100%) rename {api => crates/services/api-old}/src/route/app/mod.rs (100%) rename engine/src/controller/suite.rs => crates/services/api-old/src/route/app/object_repo.rs (100%) rename {api => crates/services/api-old}/src/route/app/profile.rs (100%) rename {api => crates/services/api-old}/src/route/app/suit.rs (100%) rename {api => crates/services/api-old}/src/route/file.rs (100%) rename {api => crates/services/api-old}/src/route/mod.rs (100%) rename {api => crates/services/api-old}/src/route/ws.rs (100%) rename {api => crates/services/api-old}/src/server/context/mod.rs (100%) rename {api => crates/services/api-old}/src/server/context/request.rs (100%) rename {api => crates/services/api-old}/src/server/middleware/mod.rs (100%) rename {api => crates/services/api-old}/src/server/middleware/request.rs (100%) rename {api => crates/services/api-old}/src/server/mod.rs (100%) rename {api => crates/services/api-old}/src/utils/client/mod.rs (100%) rename {api => crates/services/api-old}/src/utils/config.rs (100%) rename {api => crates/services/api-old}/src/utils/mod.rs (100%) rename {api => crates/services/api-old}/tests/mod.rs (100%) rename {api => crates/services/api-old}/tests/seed_data.rs (100%) create mode 100644 crates/services/api/Cargo.toml create mode 100644 crates/services/api/src/error.rs create mode 100644 crates/services/api/src/main.rs create mode 100644 crates/services/api/src/route/admin/mod.rs create mode 100644 crates/services/api/src/route/admin/user.rs create mode 100644 crates/services/api/src/route/app/action.rs create mode 100644 crates/services/api/src/route/app/case.rs create mode 100644 crates/services/api/src/route/app/case_old.rs create mode 100644 crates/services/api/src/route/app/datatable.rs create mode 100644 crates/services/api/src/route/app/group.rs create mode 100644 crates/services/api/src/route/app/mod.rs rename entity/src/auth/mod.rs => crates/services/api/src/route/app/object_repo.rs (100%) create mode 100644 crates/services/api/src/route/app/profile.rs create mode 100644 crates/services/api/src/route/app/suit.rs create mode 100644 crates/services/api/src/route/mod.rs create mode 100644 crates/services/api/src/route/public.rs create mode 100644 crates/services/api/src/server/middleware/mod.rs create mode 100644 crates/services/api/src/server/middleware/orca.rs create mode 100644 crates/services/api/src/server/mod.rs create mode 100644 crates/services/api/src/server/session.rs create mode 100644 crates/services/api/src/service/admin/mod.rs create mode 100644 crates/services/api/src/service/admin/user.rs create mode 100644 crates/services/api/src/service/app/action.rs create mode 100644 crates/services/api/src/service/app/case.rs create mode 100644 crates/services/api/src/service/app/datatable.rs create mode 100644 crates/services/api/src/service/app/group.rs create mode 100644 crates/services/api/src/service/app/mod.rs create mode 100644 crates/services/api/src/service/app/object_repo.rs create mode 100644 crates/services/api/src/service/app/profile.rs create mode 100644 crates/services/api/src/service/app/suit.rs create mode 100644 crates/services/api/src/service/mod.rs create mode 100644 crates/services/api/src/utils/mod.rs rename {engine => crates/services/engine}/Cargo.toml (72%) rename {engine => crates/services/engine}/src/controller/action.rs (92%) rename {engine => crates/services/engine}/src/controller/case.rs (100%) rename {engine => crates/services/engine}/src/controller/mod.rs (100%) create mode 100644 crates/services/engine/src/controller/suite.rs rename {engine => crates/services/engine}/src/driver/api.rs (100%) rename {engine => crates/services/engine}/src/driver/mod.rs (100%) rename {engine => crates/services/engine}/src/driver/ui.rs (100%) create mode 100644 crates/services/engine/src/error.rs rename {engine => crates/services/engine}/src/lib.rs (100%) rename {engine => crates/services/engine}/src/server/driver.rs (91%) rename {engine => crates/services/engine}/src/server/mod.rs (100%) rename {engine => crates/services/engine}/src/ui/mod.rs (100%) rename {engine => crates/services/engine}/src/ui/step.rs (100%) rename {engine => crates/services/engine}/tests/controller.rs (100%) create mode 100644 crates/web/render/Cargo.toml create mode 100644 crates/web/render/Dioxus.toml create mode 100644 crates/web/render/src/main.rs create mode 100644 crates/web/tail-rs/Cargo.toml create mode 100644 crates/web/tail-rs/src/button/button.rs create mode 100644 crates/web/tail-rs/src/button/mod.rs create mode 100644 crates/web/tail-rs/src/lib.rs create mode 100644 docs/setup/config.md delete mode 100644 engine/src/error.rs delete mode 100644 entity/Cargo.toml delete mode 100644 entity/src/backup/activity.rs delete mode 100644 entity/src/backup/audit_log.rs delete mode 100644 entity/src/backup/backup.rs delete mode 100644 entity/src/backup/profile.rs delete mode 100644 entity/src/backup/profile_data.rs delete mode 100644 entity/src/backup/role.rs delete mode 100644 entity/src/backup/role_scope.rs delete mode 100644 entity/src/backup/test_action.rs delete mode 100644 entity/src/backup/test_case.rs delete mode 100644 entity/src/backup/test_step.rs delete mode 100644 entity/src/backup/user.rs delete mode 100644 entity/src/backup/user_group.rs delete mode 100644 entity/src/backup/user_role.rs delete mode 100644 entity/src/backup/user_session.rs delete mode 100644 entity/src/test/mod.rs delete mode 100644 migration/Cargo.toml create mode 100644 start.sh diff --git a/.cargo/config.example.toml b/.cargo/config.example.toml new file mode 100644 index 0000000..ecb7a17 --- /dev/null +++ b/.cargo/config.example.toml @@ -0,0 +1,32 @@ +# Cargo config file. +# See: https://doc.rust-lang.org/cargo/reference/config.html + +# Environments variables set for all `cargo ...` commands. +[env] + +# Scope down tracing, to filter out external lib tracing. +RUST_LOG="web_server=debug,lib_core=debug,lib_auth=debug,lib_utils=debug" + +# -- Service Environment Variables +# IMPORTANT: +# For cargo commands only. +# For deployed env, should be managed by container +# (e.g., Kubernetes). + +## -- Secrets +# Keys and passwords below are for localhost dev ONLY. +# e.g., "welcome" type of passwords. +# i.e., Encryption not needed. + +SERVICE_DB_URL="postgres://app_user:dev_only_pwd@localhost/app_db" + +SERVICE_PWD_KEY="" + +SERVICE_TOKEN_KEY="" +SERVICE_TOKEN_DURATION_SEC="1800" # 30 minutes + +## -- ConfigMap + +# This will be relative to Cargo.toml +# In deployed images, probably use absolute path. +SERVICE_WEB_FOLDER="web-folder/" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 81b0bb6..60d0ea3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,8 @@ **.DS_Store **to/ **data -.vscode \ No newline at end of file +.vscode + +## Ignore File for backend service +.cargo/config.toml + diff --git a/Cargo.toml b/Cargo.toml index 53e6357..b4e9de3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,66 @@ -#[package] -#name = "orca" -#version = "0.1.0" -#edition = "2021" -# ## See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members=["cerium", "api", "engine", "entity", "migration"] -default-members=["cerium"] +name = "orca" +members=[ + "crates/libs/cerium", + "crates/libs/entity", + "crates/libs/migration", + "crates/services/engine", + "crates/services/api", + "crates/web/render" +] + +[workspace.package] +authors = [ "Vasanth Kumar " ] +edition = "2021" +version = "0.1.0" +license = "MIT OR Apache-2.0" +documentation = "https://docs.rs/orca/" +homepage = "https://github.com/orcaci/orca" +repository = "https://github.com/orcaci/orca" +rust-version = "1.74.1" +exclude = [".github/**"] + + +[workspace.dependencies] +cerium = { path = "crates/libs/cerium", default-features = true } +entity = { path = "crates/libs/entity", default-features = true } +migration = { path = "crates/libs/migration", default-features = true } +engine = { path = "crates/services/engine", default-features = true } +api = { path = "crates/services/api", default-features = true } + +thiserror = "1.0.31" +jsonwebtoken = "8" +serde = { version = "1.0.147"} +serde_json = "1.0.87" +chrono = { version = "0.4.31"} +tracing = "0.1.37" +tracing-subscriber = "0.3.16" +uuid = { version = "1.6.1", features = ["serde", "v4"] } + +sea-query = "0.30.5" +sea-orm = { version = "0.12.3", features = [ + "macros", + "debug-print", + "runtime-async-std-native-tls", + "sqlx-postgres", +] } +sea-orm-migration = {version = "0.12.3", features = ["sqlx-postgres"]} + +axum = "0.7.1" +axum-extra = "0.8.0" +tokio = { version = "1.34.0", features = ["full"] } +tower = "0.4.13" +tower-http = { version = "0.5.0", default-features = true, features = ["uuid", "cors", "trace", "compression-br", "catch-panic", "request-id"] } + +config = "0.13.3" + +dotenv = "0.15.0" +futures = "0.3.29" +futures-util = "0.3.29" +rust_decimal = "1.14.3" +cross-test = "0.1.6" + +[patch.crates-io] +sea-orm = { git="https://github.com/itsparser/sea-orm", branch = "master" } \ No newline at end of file diff --git a/cerium/src/client/mod.rs b/cerium/src/client/mod.rs deleted file mode 100644 index c2df151..0000000 --- a/cerium/src/client/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod cache; -pub mod db; \ No newline at end of file diff --git a/cerium/src/config.rs b/cerium/src/config.rs deleted file mode 100644 index 1060540..0000000 --- a/cerium/src/config.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::time::Duration; - -use sea_orm::{ConnectOptions, Database, DatabaseConnection}; - -use crate::env::Environment; - -#[derive(Debug)] -#[allow(unused)] -pub struct Config { - pub env: Environment, - pub db: Option -} - -impl Config { - pub fn new() -> Self { - let env = Environment::new(); - let config = Config{ env, db: None }; - config - } - - /// database - will give connection SeaOrm Database - pub async fn database(&mut self) -> DatabaseConnection { - if self.db.is_none() { - let uri = self.env.clone().connection.database; - log::info!("Got connection String {}", uri.clone()); - let mut opt = ConnectOptions::new(self.env.clone().connection.database); - opt.max_connections(100) - .min_connections(5) - .connect_timeout(Duration::from_secs(8)) - .acquire_timeout(Duration::from_secs(8)) - .idle_timeout(Duration::from_secs(8)) - .max_lifetime(Duration::from_secs(8)) - .sqlx_logging(true) - .sqlx_logging_level(log::LevelFilter::Info) - .set_schema_search_path("orca".into()); - - self.db = Some(Database::connect(opt).await.expect("Error on connection")) - } - self.db.clone().unwrap() - } -} diff --git a/cerium/src/error/mod.rs b/cerium/src/error/mod.rs deleted file mode 100644 index e065946..0000000 --- a/cerium/src/error/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub use cerium::{CeriumError, CeriumResult, ErrorResponse}; - -pub mod web; -pub mod cerium; - diff --git a/cerium/src/error/web.rs b/cerium/src/error/web.rs deleted file mode 100644 index 994eacf..0000000 --- a/cerium/src/error/web.rs +++ /dev/null @@ -1,95 +0,0 @@ -use std::fmt; -use std::fmt::Formatter; - -use actix_web::{HttpResponse, ResponseError}; -use http::StatusCode; -use jsonwebtoken::errors::Error; -use serde::Serialize; -use thiserror::Error; - -pub type OrcaResult = Result; - -pub type InternalResult = Result; - -#[derive(Clone)] -pub struct ErrorResponse { - code: StatusCode, - error: String, - message: String, -} - -#[derive(Serialize)] -struct Response { - code: u16, - error: String, - message: String, -} - -impl ErrorResponse { - pub fn new(code: StatusCode, error: &str, message: String) -> Self { - Self { code, error: error.to_string(), message } - } -} - -/// OrcaError - will have all the error raised from Orca system -#[derive(Error, Debug)] -pub enum OrcaError { - /// Internal Error Core Error - #[error("json error: {0}")] - JsonError(#[from] serde_json::Error), - #[error("io error: {0}")] - IoError(#[from] std::io::Error), - #[error("DB error: {0}")] - DBError(#[from] sea_orm::DbErr), - #[error("JWT error: {0}")] - JWTError(#[from] Error), - #[error("You are forbidden to access requested file.")] - Forbidden, - #[error("Header ({0}) is not available.")] - HeaderNotFound(String), - - #[error("User Not found")] - UserNotFound(i32), - - // #[error("Unknown Internal Error - {0}")] - // Unknown(#[from] String) -} - -impl OrcaError { - pub fn decode(&self) -> ErrorResponse { - match self { - Self::HeaderNotFound(ref _a) => ErrorResponse::new(StatusCode::NOT_FOUND, "HeaderNotFound", self.to_string()), - - Self::JsonError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "NotFound", self.to_string()), - // Self::NotFound => ErrorResponse::new(StatusCode::OK, "NotFound", self.to_string()), - Self::Forbidden => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Unknown", self.to_string()), - Self::IoError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Unknown", self.to_string()), - Self::DBError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "DBError", self.to_string()), - - Self::JWTError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "JWTError", self.to_string()), - - Self::UserNotFound(ref _a) => ErrorResponse::new(StatusCode::NOT_FOUND, "UserNotFound", self.to_string()), - _ => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Unknown", self.to_string()), - } - } - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!( - "An error occurred: \"{}\"", - self.to_string() - )) - } -} - -impl ResponseError for OrcaError { - - fn error_response(&self) -> HttpResponse { - let response = self.decode(); - let _status_code = response.clone().code; - let eresponse = Response{ - code: response.clone().code.as_u16(), - error: response.error, - message: response.message - }; - HttpResponse::build(_status_code).json(eresponse) - } -} diff --git a/cerium/src/utils/uuid.rs b/cerium/src/utils/uuid.rs deleted file mode 100644 index ddb082e..0000000 --- a/cerium/src/utils/uuid.rs +++ /dev/null @@ -1,10 +0,0 @@ -use rand::distributions::Alphanumeric; -use rand::distributions::DistString; - -pub fn short_uuid() -> String { - Alphanumeric.sample_string(&mut rand::thread_rng(), 8) -} - -pub fn request_uuid() -> String { - format!("Rid{}", Alphanumeric.sample_string(&mut rand::thread_rng(), 32)) -} \ No newline at end of file diff --git a/config/default.toml b/config/default.toml index 06806e0..9ad0f30 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,6 +1,7 @@ debug = false [connection] +db_backend = "Postgres" database="postgres://jukbbjhs:T16p5KyqgrrERxCaZRP_nlxgGOFXvRhM@otto.db.elephantsql.com:5432/jukbbjhs" selenium="http://34.72.113.188:4444/wd/hub" diff --git a/cerium/Cargo.toml b/crates/libs/cerium/Cargo.toml similarity index 50% rename from cerium/Cargo.toml rename to crates/libs/cerium/Cargo.toml index 5f575ec..48f89c7 100644 --- a/cerium/Cargo.toml +++ b/crates/libs/cerium/Cargo.toml @@ -1,9 +1,14 @@ [package] name = "cerium" version = "0.1.0" -edition = "2021" description = "Cerium - is core libirary for the orca application" -authors = ["Vasanth Kumar Kalaiselvan "] +authors = ["Vasanth Kumar "] +publish = false +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[test]] @@ -14,19 +19,38 @@ path = "tests" name = "cerium" crate-type = ["lib"] +[features] +default = [] +actix = ["dep:actix-web"] +axum = [] + [dependencies] +tracing.workspace=true +tracing-subscriber.workspace=true +tokio.workspace=true +axum.workspace=true +axum-extra.workspace=true +tower.workspace=true +tower-http.workspace=true +config.workspace=true +sea-orm.workspace=true +sea-query.workspace=true + +bytes = "1" +http-body-util = "0.1.0" + lazy_static = "1.4.0" async_once = "0.2.6" log = "0.4.16" env_logger = "0.10.0" -config = "0.13.3" chrono = "0.4.23" jsonwebtoken = "8" thiserror = "1.0.31" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.87" -actix-web = "4.2.1" http = "0.2.8" -sea-orm = {version = "0.11.0", default-features = true} rand = { version = "0.8.5", default-features = false, features = ["std"] } + +actix-web = { version = "4.2.1", optional = true } + diff --git a/cerium/src/client/cache.rs b/crates/libs/cerium/src/client/cache.rs similarity index 100% rename from cerium/src/client/cache.rs rename to crates/libs/cerium/src/client/cache.rs diff --git a/cerium/src/client/db/mod.rs b/crates/libs/cerium/src/client/db/mod.rs similarity index 100% rename from cerium/src/client/db/mod.rs rename to crates/libs/cerium/src/client/db/mod.rs diff --git a/crates/libs/cerium/src/client/mod.rs b/crates/libs/cerium/src/client/mod.rs new file mode 100644 index 0000000..82ac7ea --- /dev/null +++ b/crates/libs/cerium/src/client/mod.rs @@ -0,0 +1,43 @@ +use std::time::Duration; + +use sea_orm::{ConnectOptions, Database, DatabaseConnection}; + +pub mod cache; +pub mod db; + + +#[derive(Debug, Clone)] +pub struct Client { + pub db: DatabaseConnection +} + +impl Client { + pub async fn new(db_uri: Option, redis_uri: Option) -> Self { + Client{ + db: Self::db_client(db_uri).await, + } + } + + pub fn db(&self) -> &DatabaseConnection { + &self.db + } + + /// db_uri will give the default uri if there is not config setup + async fn db_client(mut uri: Option) -> DatabaseConnection { + if uri.is_none(){ + uri = Some(std::env::var("DATABASE_URL").expect("DATABASE_URL must be set.")); + + } + let mut opt = ConnectOptions::new(uri.unwrap()); + opt.max_connections(10) + .min_connections(5) + .connect_timeout(Duration::from_secs(8)) + .acquire_timeout(Duration::from_secs(8)) + .idle_timeout(Duration::from_secs(8)) + .max_lifetime(Duration::from_secs(8)) + .sqlx_logging(true) + .sqlx_logging_level(log::LevelFilter::Info); + Database::connect(opt).await.expect("Error unable to connect DB") + // Database::connect(uri.unwrap()).await.expect("Error unable to connect DB") + } +} \ No newline at end of file diff --git a/crates/libs/cerium/src/config.rs b/crates/libs/cerium/src/config.rs new file mode 100644 index 0000000..b9ae200 --- /dev/null +++ b/crates/libs/cerium/src/config.rs @@ -0,0 +1,20 @@ +use std::time::Duration; + +use sea_orm::{ConnectOptions, Database, DatabaseConnection}; + +use crate::env::Environment; + +#[derive(Debug)] +#[allow(unused)] +pub struct Config { + pub env: Environment, + pub db: Option +} + +impl Config { + pub fn new() -> Self { + let env = Environment::new(); + let config = Config{ env, db: None }; + config + } +} diff --git a/cerium/src/env.rs b/crates/libs/cerium/src/env.rs similarity index 81% rename from cerium/src/env.rs rename to crates/libs/cerium/src/env.rs index e667117..9ceb958 100644 --- a/cerium/src/env.rs +++ b/crates/libs/cerium/src/env.rs @@ -21,8 +21,8 @@ impl Environment { pub fn new() -> Self { let run_mode = env::var("RUN_MODE").unwrap_or_else(|_| "development".into()); let result_config = CConfig::builder() - .add_source(File::with_name("../config/default")) - .add_source(File::with_name(&format!("../config/{}", run_mode)).required(false)) + .add_source(File::with_name("./config/default")) + .add_source(File::with_name(&format!("./config/{}", run_mode)).required(false)) .build(); let _new = result_config.expect("Error from Environment"); _new.try_deserialize().expect("Error from Environment") diff --git a/cerium/src/error/cerium.rs b/crates/libs/cerium/src/error/cerium.rs similarity index 100% rename from cerium/src/error/cerium.rs rename to crates/libs/cerium/src/error/cerium.rs diff --git a/crates/libs/cerium/src/error/mod.rs b/crates/libs/cerium/src/error/mod.rs new file mode 100644 index 0000000..3b4465f --- /dev/null +++ b/crates/libs/cerium/src/error/mod.rs @@ -0,0 +1,57 @@ +use axum::http::StatusCode; +use axum::Json; +use axum::response::{IntoResponse, Response}; +use sea_orm::DbErr; +use serde_json::{Error as SerdeJsonError, json}; + +pub use cerium::{CeriumError as OtherCeriumError, CeriumResult, ErrorResponse}; + +pub mod web; +pub mod cerium; + +// pub type OrcaResult = InternalResult; + +pub type InternalResult = Result; + +/// Our app's top level error type. +pub enum CeriumError { + /// Something went wrong when calling the user repo. + DataBaseError(DbErr), + SerializerError(SerdeJsonError) +} + +/// This makes it possible to use `?` to automatically convert a `DbErr` +/// into an `CeriumError`. +impl From for CeriumError { + fn from(inner: DbErr) -> Self { + CeriumError::DataBaseError(inner) + } +} + +/// This makes it possible to use `?` to automatically convert a `DbErr` +/// into an `CeriumError`. +impl From for CeriumError { + fn from(inner: SerdeJsonError) -> Self { + CeriumError::SerializerError(inner) + } +} + +impl IntoResponse for CeriumError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + CeriumError::DataBaseError(err) =>{ + (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) + } + CeriumError::SerializerError(err) => { + (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) + } + _ => (StatusCode::INTERNAL_SERVER_ERROR, "Internal Error Not Specify".to_string()) + }; + + let body = Json(json!({ + "error": error_message, + })); + + (status, body).into_response() + } +} \ No newline at end of file diff --git a/crates/libs/cerium/src/error/web.rs b/crates/libs/cerium/src/error/web.rs new file mode 100644 index 0000000..57131ee --- /dev/null +++ b/crates/libs/cerium/src/error/web.rs @@ -0,0 +1,95 @@ +// use std::fmt; +// use std::fmt::Formatter; +// +// use actix_web::{HttpResponse, ResponseError}; +// use http::StatusCode; +// use jsonwebtoken::errors::Error; +// use serde::Serialize; +// use thiserror::Error; +// +// pub type OrcaResult = Result; +// +// pub type InternalResult = Result; +// +// #[derive(Clone)] +// pub struct ErrorResponse { +// code: StatusCode, +// error: String, +// message: String, +// } +// +// #[derive(Serialize)] +// struct Response { +// code: u16, +// error: String, +// message: String, +// } +// +// impl ErrorResponse { +// pub fn new(code: StatusCode, error: &str, message: String) -> Self { +// Self { code, error: error.to_string(), message } +// } +// } +// +// /// OrcaError - will have all the error raised from Orca system +// #[derive(Error, Debug)] +// pub enum OrcaError { +// /// Internal Error Core Error +// #[error("json error: {0}")] +// JsonError(#[from] serde_json::Error), +// #[error("io error: {0}")] +// IoError(#[from] std::io::Error), +// #[error("DB error: {0}")] +// DBError(#[from] sea_orm::DbErr), +// #[error("JWT error: {0}")] +// JWTError(#[from] Error), +// #[error("You are forbidden to access requested file.")] +// Forbidden, +// #[error("Header ({0}) is not available.")] +// HeaderNotFound(String), +// +// #[error("User Not found")] +// UserNotFound(i32), +// +// // #[error("Unknown Internal Error - {0}")] +// // Unknown(#[from] String) +// } +// +// impl OrcaError { +// pub fn decode(&self) -> ErrorResponse { +// match self { +// Self::HeaderNotFound(ref _a) => ErrorResponse::new(StatusCode::NOT_FOUND, "HeaderNotFound", self.to_string()), +// +// Self::JsonError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "NotFound", self.to_string()), +// // Self::NotFound => ErrorResponse::new(StatusCode::OK, "NotFound", self.to_string()), +// Self::Forbidden => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Unknown", self.to_string()), +// Self::IoError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Unknown", self.to_string()), +// Self::DBError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "DBError", self.to_string()), +// +// Self::JWTError(ref _a) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "JWTError", self.to_string()), +// +// Self::UserNotFound(ref _a) => ErrorResponse::new(StatusCode::NOT_FOUND, "UserNotFound", self.to_string()), +// _ => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Unknown", self.to_string()), +// } +// } +// fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { +// f.write_fmt(format_args!( +// "An error occurred: \"{}\"", +// self.to_string() +// )) +// } +// } +// +// impl ResponseError for OrcaError { +// +// fn error_response(&self) -> HttpResponse { +// let response = self.decode(); +// let _status_code = response.clone().code; +// let eresponse = Response{ +// code: response.clone().code.as_u16(), +// error: response.error, +// message: response.message +// }; +// HttpResponse::build(_status_code).json(eresponse) +// } +// } diff --git a/cerium/src/lib.rs b/crates/libs/cerium/src/lib.rs similarity index 100% rename from cerium/src/lib.rs rename to crates/libs/cerium/src/lib.rs diff --git a/crates/libs/cerium/src/server/mod.rs b/crates/libs/cerium/src/server/mod.rs new file mode 100644 index 0000000..d90ea60 --- /dev/null +++ b/crates/libs/cerium/src/server/mod.rs @@ -0,0 +1,94 @@ +use std::sync::{Arc, Mutex}; +use axum::{Router, serve}; +use axum::http::{HeaderName, Method}; +use chrono::Duration; +use sea_orm::DatabaseConnection; +use tokio::net::TcpListener; +use tower_http::{compression::CompressionLayer, cors::{Any, CorsLayer}}; +use tower_http::catch_panic::CatchPanicLayer; +use tower_http::classify::ServerErrorsFailureClass; +use tower_http::request_id::{PropagateRequestIdLayer, SetRequestIdLayer}; +use tower_http::trace::TraceLayer; +use tracing::{error, info, Level, Span}; +use tracing_subscriber::fmt; +use tracing_subscriber::layer::SubscriberExt; +use crate::client::Client; + +use crate::server::request_id::OrcaRequestId; + +mod utils; +mod request_id; + +#[derive(Clone)] +pub struct AppState { + pub db: Arc> +} + +pub struct App { + name: String, + port: i32, + log_level: Level, + router: Router, + cli: Client +} + +impl App { + pub fn new(name: &str, cli: Client) -> Self { + Self { + name: name.to_string(), + port: 80, + log_level: Level::INFO, + router: Default::default(), + cli + } + } + + pub fn set_logger(&self, filter: Level) { + + fmt() + // .with(tracing_subscriber::fmt::layer()) + // .with_target(true) + // .with_timer(tracing_subscriber::fmt::time::uptime()) + // .with_level(true) + .with_max_level(filter).init() + } + + pub fn set_port(&mut self, port: i32) { + self.port = port + } + + fn app_state(&mut self) -> AppState { + AppState { + db: Arc::new(Mutex::new(self.cli.clone().db)) + } + } + + + pub fn set_router(&mut self, router: Router) { + + let x_request_id = HeaderName::from_static("x-request-id"); + let cors = CorsLayer::new() + .allow_methods([Method::GET, Method::POST]) + .allow_origin(Any); + let router = router + // .with_state(self.app_state()) + .layer(SetRequestIdLayer::new( + x_request_id.clone(), + OrcaRequestId::default(), + )) + .layer(PropagateRequestIdLayer::new(x_request_id)) + .layer(cors) + .layer(CompressionLayer::new()) + .layer(CatchPanicLayer::new()) + .layer(TraceLayer::new_for_http()); + self.router = router + } + + pub async fn run(self) { + let listener = TcpListener::bind(format!("0.0.0.0:{:?}", self.port)).await.unwrap(); + info!("🚀 Starting Server "); + serve(listener, self.router).await.unwrap(); + } +} + + diff --git a/crates/libs/cerium/src/server/request_id.rs b/crates/libs/cerium/src/server/request_id.rs new file mode 100644 index 0000000..9eca5cf --- /dev/null +++ b/crates/libs/cerium/src/server/request_id.rs @@ -0,0 +1,15 @@ +use sea_orm::prelude::Uuid; +use tower_http::request_id::{MakeRequestId, RequestId}; +use tracing::info; + +// A `MakeRequestId` that increments an atomic counter +#[derive(Clone, Default)] +pub struct OrcaRequestId; + +impl MakeRequestId for OrcaRequestId { + fn make_request_id(&mut self, request: &axum::http::Request) -> Option { + let id = Uuid::new_v4(); + info!("Request ID - {:?}", id); + Some(RequestId::new(id.to_string().parse().unwrap())) + } +} \ No newline at end of file diff --git a/crates/libs/cerium/src/server/utils.rs b/crates/libs/cerium/src/server/utils.rs new file mode 100644 index 0000000..b4e8d01 --- /dev/null +++ b/crates/libs/cerium/src/server/utils.rs @@ -0,0 +1,30 @@ +use std::any::Any; + +use bytes::Bytes; +use http::{header::{self}, Response, StatusCode}; +use http_body_util::Full; + + +pub fn handle_panic(err: Box) -> Response> { + let details = if let Some(s) = err.downcast_ref::() { + s.clone() + } else if let Some(s) = err.downcast_ref::<&str>() { + s.to_string() + } else { + "Unknown panic message".to_string() + }; + + let body = serde_json::json!({ + "error": { + "kind": "panic", + "details": details, + } + }); + let body = serde_json::to_string(&body).unwrap(); + + Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .header(header::CONTENT_TYPE, "application/json") + .body(Full::from(body)) + .unwrap() +} \ No newline at end of file diff --git a/cerium/src/utils/mod.rs b/crates/libs/cerium/src/utils/mod.rs similarity index 100% rename from cerium/src/utils/mod.rs rename to crates/libs/cerium/src/utils/mod.rs diff --git a/crates/libs/cerium/src/utils/uuid.rs b/crates/libs/cerium/src/utils/uuid.rs new file mode 100644 index 0000000..2870229 --- /dev/null +++ b/crates/libs/cerium/src/utils/uuid.rs @@ -0,0 +1,10 @@ +// use rand::distributions::Alphanumeric; +// use rand::distributions::DistString; +// +// pub fn short_uuid() -> String { +// Alphanumeric.sample_string(rand::thread_rng(), 8) +// } +// +// pub fn request_uuid() -> String { +// format!("Rid{}", Alphanumeric.sample_string(&mut rand::thread_rng(), 32)) +// } \ No newline at end of file diff --git a/cerium/tests/1_init.rs b/crates/libs/cerium/tests/1_init.rs similarity index 100% rename from cerium/tests/1_init.rs rename to crates/libs/cerium/tests/1_init.rs diff --git a/crates/libs/entity/Cargo.toml b/crates/libs/entity/Cargo.toml new file mode 100644 index 0000000..1934289 --- /dev/null +++ b/crates/libs/entity/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "entity" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde.workspace = true +serde_json.workspace = true +sea-orm.workspace=true +sea-query.workspace=true \ No newline at end of file diff --git a/api/src/route/app/object_repo.rs b/crates/libs/entity/src/admin/group.rs similarity index 100% rename from api/src/route/app/object_repo.rs rename to crates/libs/entity/src/admin/group.rs diff --git a/crates/libs/entity/src/admin/mod.rs b/crates/libs/entity/src/admin/mod.rs new file mode 100644 index 0000000..018ff2e --- /dev/null +++ b/crates/libs/entity/src/admin/mod.rs @@ -0,0 +1 @@ +pub mod user; \ No newline at end of file diff --git a/entity/src/backup/group.rs b/crates/libs/entity/src/admin/user.rs similarity index 59% rename from entity/src/backup/group.rs rename to crates/libs/entity/src/admin/user.rs index 3a96c73..6a03b19 100644 --- a/entity/src/backup/group.rs +++ b/crates/libs/entity/src/admin/user.rs @@ -5,24 +5,20 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "group")] +#[sea_orm(table_name = "user")] pub struct Model { + #[serde(skip_deserializing)] #[sea_orm(primary_key)] pub id: i32, pub name: String, - pub description: Option, + pub first_name: String, + pub last_name: Option, + pub email: String, + // pub profile_url: String, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::user_group::Entity")] - UserGroup, -} +pub enum Relation {} -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserGroup.def() - } -} impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/app/app.rs b/crates/libs/entity/src/app/app.rs similarity index 100% rename from entity/src/app/app.rs rename to crates/libs/entity/src/app/app.rs diff --git a/entity/src/app/mod.rs b/crates/libs/entity/src/app/mod.rs similarity index 100% rename from entity/src/app/mod.rs rename to crates/libs/entity/src/app/mod.rs diff --git a/cerium/src/server/mod.rs b/crates/libs/entity/src/auth/mod.rs similarity index 100% rename from cerium/src/server/mod.rs rename to crates/libs/entity/src/auth/mod.rs diff --git a/entity/src/command.rs b/crates/libs/entity/src/command.rs similarity index 100% rename from entity/src/command.rs rename to crates/libs/entity/src/command.rs diff --git a/entity/src/common/attachment.rs b/crates/libs/entity/src/common/attachment.rs similarity index 100% rename from entity/src/common/attachment.rs rename to crates/libs/entity/src/common/attachment.rs diff --git a/entity/src/common/config.rs b/crates/libs/entity/src/common/config.rs similarity index 100% rename from entity/src/common/config.rs rename to crates/libs/entity/src/common/config.rs diff --git a/entity/src/common/mod.rs b/crates/libs/entity/src/common/mod.rs similarity index 100% rename from entity/src/common/mod.rs rename to crates/libs/entity/src/common/mod.rs diff --git a/entity/src/common/tag.rs b/crates/libs/entity/src/common/tag.rs similarity index 100% rename from entity/src/common/tag.rs rename to crates/libs/entity/src/common/tag.rs diff --git a/entity/src/common/tag_entity.rs b/crates/libs/entity/src/common/tag_entity.rs similarity index 100% rename from entity/src/common/tag_entity.rs rename to crates/libs/entity/src/common/tag_entity.rs diff --git a/crates/libs/entity/src/core/mod.rs b/crates/libs/entity/src/core/mod.rs new file mode 100644 index 0000000..f70ec86 --- /dev/null +++ b/crates/libs/entity/src/core/mod.rs @@ -0,0 +1,8 @@ +use sea_orm::{ActiveModelBehavior, ActiveModelTrait}; + +pub trait OrcaModel: ActiveModelBehavior { + fn new() -> Self { + ::default() + } + +} \ No newline at end of file diff --git a/entity/src/lib.rs b/crates/libs/entity/src/lib.rs similarity index 79% rename from entity/src/lib.rs rename to crates/libs/entity/src/lib.rs index 53e78ac..17cc818 100644 --- a/entity/src/lib.rs +++ b/crates/libs/entity/src/lib.rs @@ -7,8 +7,5 @@ pub mod common; pub mod test; pub mod app; pub mod command; - - - - - +pub mod core; +pub mod admin; diff --git a/entity/src/mod.rs b/crates/libs/entity/src/mod.rs similarity index 100% rename from entity/src/mod.rs rename to crates/libs/entity/src/mod.rs diff --git a/entity/src/prelude.rs b/crates/libs/entity/src/prelude.rs similarity index 57% rename from entity/src/prelude.rs rename to crates/libs/entity/src/prelude.rs index 9d90fc9..78cc95f 100644 --- a/entity/src/prelude.rs +++ b/crates/libs/entity/src/prelude.rs @@ -1,14 +1,5 @@ //! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 -// pub use super::group::Entity as Group; -// pub use super::profile::Entity as Profile; -// pub use super::profile_data::Entity as ProfileData; -// pub use super::test_case::Entity as TestCase; -// pub use super::test_step::Entity as TestStep; -// pub use super::user::Entity as User; -// pub use super::user_group::Entity as UserGroup; - - pub use super::common::attachment; pub use super::test::ui::{ action::{ diff --git a/entity/src/test/ui/action/datatable.rs b/crates/libs/entity/src/test/datatable.rs similarity index 100% rename from entity/src/test/ui/action/datatable.rs rename to crates/libs/entity/src/test/datatable.rs diff --git a/entity/src/test/ui/action/field.rs b/crates/libs/entity/src/test/field.rs similarity index 77% rename from entity/src/test/ui/action/field.rs rename to crates/libs/entity/src/test/field.rs index 2ce5f0a..8aa417b 100644 --- a/entity/src/test/ui/action/field.rs +++ b/crates/libs/entity/src/test/field.rs @@ -6,12 +6,15 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] #[sea_orm(rs_type = "String", db_type = "String(Some(5))", enum_name = "table_kind")] -pub enum ActionDataKind { +pub enum FieldDataKind { #[sea_orm(string_value = "S")] + #[serde(rename = "S")] String, #[sea_orm(string_value = "I")] + #[serde(rename = "I")] Int, #[sea_orm(string_value = "B")] + #[serde(rename = "B")] Bool } @@ -25,18 +28,8 @@ pub struct Model { #[serde(skip_deserializing)] pub table_id: i32, pub name: String, - pub kind: ActionDataKind, + pub kind: FieldDataKind, pub option: Option - // #[serde(skip_deserializing)] - // #[sea_orm(primary_key)] - // pub id: i32, - // pub name: String, - // #[serde(skip_deserializing)] - // pub field_id: String, - // pub kind: ActionDataKind, - // pub option: Option, - // #[serde(skip_deserializing)] - // pub table_id: i32 } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/crates/libs/entity/src/test/mod.rs b/crates/libs/entity/src/test/mod.rs new file mode 100644 index 0000000..c445da8 --- /dev/null +++ b/crates/libs/entity/src/test/mod.rs @@ -0,0 +1,4 @@ +pub mod ui; +pub mod datatable; +pub mod field; +pub mod profile; \ No newline at end of file diff --git a/entity/src/test/ui/profile/data.rs b/crates/libs/entity/src/test/profile/data.rs similarity index 100% rename from entity/src/test/ui/profile/data.rs rename to crates/libs/entity/src/test/profile/data.rs diff --git a/entity/src/test/ui/profile/mod.rs b/crates/libs/entity/src/test/profile/mod.rs similarity index 100% rename from entity/src/test/ui/profile/mod.rs rename to crates/libs/entity/src/test/profile/mod.rs diff --git a/entity/src/test/ui/profile/profile.rs b/crates/libs/entity/src/test/profile/profile.rs similarity index 100% rename from entity/src/test/ui/profile/profile.rs rename to crates/libs/entity/src/test/profile/profile.rs diff --git a/entity/src/test/ui/action/action.rs b/crates/libs/entity/src/test/ui/action/action.rs similarity index 100% rename from entity/src/test/ui/action/action.rs rename to crates/libs/entity/src/test/ui/action/action.rs diff --git a/entity/src/test/ui/action/data.rs b/crates/libs/entity/src/test/ui/action/data.rs similarity index 100% rename from entity/src/test/ui/action/data.rs rename to crates/libs/entity/src/test/ui/action/data.rs diff --git a/entity/src/test/ui/action/group.rs b/crates/libs/entity/src/test/ui/action/group.rs similarity index 100% rename from entity/src/test/ui/action/group.rs rename to crates/libs/entity/src/test/ui/action/group.rs diff --git a/entity/src/test/ui/action/mod.rs b/crates/libs/entity/src/test/ui/action/mod.rs similarity index 64% rename from entity/src/test/ui/action/mod.rs rename to crates/libs/entity/src/test/ui/action/mod.rs index af166b4..0737f1d 100644 --- a/entity/src/test/ui/action/mod.rs +++ b/crates/libs/entity/src/test/ui/action/mod.rs @@ -3,5 +3,3 @@ pub mod action; pub mod target; pub mod data; pub mod group; -pub mod datatable; -pub mod field; diff --git a/entity/src/test/ui/action/target.rs b/crates/libs/entity/src/test/ui/action/target.rs similarity index 100% rename from entity/src/test/ui/action/target.rs rename to crates/libs/entity/src/test/ui/action/target.rs diff --git a/entity/src/test/ui/case/case.rs b/crates/libs/entity/src/test/ui/case/case.rs similarity index 100% rename from entity/src/test/ui/case/case.rs rename to crates/libs/entity/src/test/ui/case/case.rs diff --git a/entity/src/test/ui/case/case_block.rs b/crates/libs/entity/src/test/ui/case/case_block.rs similarity index 100% rename from entity/src/test/ui/case/case_block.rs rename to crates/libs/entity/src/test/ui/case/case_block.rs diff --git a/entity/src/test/ui/case/data_binding.rs b/crates/libs/entity/src/test/ui/case/data_binding.rs similarity index 100% rename from entity/src/test/ui/case/data_binding.rs rename to crates/libs/entity/src/test/ui/case/data_binding.rs diff --git a/entity/src/test/ui/case/mod.rs b/crates/libs/entity/src/test/ui/case/mod.rs similarity index 100% rename from entity/src/test/ui/case/mod.rs rename to crates/libs/entity/src/test/ui/case/mod.rs diff --git a/entity/src/test/ui/elements.rs b/crates/libs/entity/src/test/ui/elements.rs similarity index 100% rename from entity/src/test/ui/elements.rs rename to crates/libs/entity/src/test/ui/elements.rs diff --git a/entity/src/test/ui/mod.rs b/crates/libs/entity/src/test/ui/mod.rs similarity index 81% rename from entity/src/test/ui/mod.rs rename to crates/libs/entity/src/test/ui/mod.rs index 6c791f8..cb8c646 100644 --- a/entity/src/test/ui/mod.rs +++ b/crates/libs/entity/src/test/ui/mod.rs @@ -1,6 +1,5 @@ pub mod case; pub mod action; -pub mod profile; pub mod suit; pub mod elements; pub mod screen; \ No newline at end of file diff --git a/entity/src/test/ui/screen.rs b/crates/libs/entity/src/test/ui/screen.rs similarity index 100% rename from entity/src/test/ui/screen.rs rename to crates/libs/entity/src/test/ui/screen.rs diff --git a/entity/src/test/ui/suit/mod.rs b/crates/libs/entity/src/test/ui/suit/mod.rs similarity index 100% rename from entity/src/test/ui/suit/mod.rs rename to crates/libs/entity/src/test/ui/suit/mod.rs diff --git a/entity/src/test/ui/suit/suite.rs b/crates/libs/entity/src/test/ui/suit/suite.rs similarity index 100% rename from entity/src/test/ui/suit/suite.rs rename to crates/libs/entity/src/test/ui/suit/suite.rs diff --git a/entity/src/test/ui/suit/suite_block.rs b/crates/libs/entity/src/test/ui/suit/suite_block.rs similarity index 100% rename from entity/src/test/ui/suit/suite_block.rs rename to crates/libs/entity/src/test/ui/suit/suite_block.rs diff --git a/crates/libs/macroni/Cargo.toml b/crates/libs/macroni/Cargo.toml new file mode 100644 index 0000000..d951d33 --- /dev/null +++ b/crates/libs/macroni/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "macroni" +authors.workspace = true +edition.workspace = true +version.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true +exclude.workspace = true + +[lib] +proc-macro = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +syn = "2.0.37" +quote = "1.0" \ No newline at end of file diff --git a/crates/libs/macroni/src/lib.rs b/crates/libs/macroni/src/lib.rs new file mode 100644 index 0000000..90670ae --- /dev/null +++ b/crates/libs/macroni/src/lib.rs @@ -0,0 +1,74 @@ + + +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, DeriveInput}; + +#[proc_macro_derive(CustomModel)] +pub fn custom_model(input: TokenStream) -> TokenStream { + // Parse the input into a Rust AST + let input = parse_macro_input!(input as DeriveInput); + + // Generate new code based on the input AST + let output = quote! { + // Add a new field to the struct + struct #input { + pub my_field: u32, + #input + } + + // Add a new trait to the struct + // impl #input { + // fn my_trait(&self) { + // // Trait implementation code goes here + // } + // } + }; + + // Return the generated code as a TokenStream + output.into() +} + +#[proc_macro_derive(HelloMacro)] +pub fn hello_macro_derive(input: TokenStream) -> TokenStream { + // Construct a representation of Rust code as a syntax tree + // that we can manipulate + let ast = syn::parse(input).unwrap(); + + // Build the trait implementation + impl_hello_macro(&ast) +} + +fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { + let name = &ast.ident; + let gen = quote! { + impl HelloMacro for #name { + fn hello_macro() { + println!("Hello, Macro! My name is {}!", stringify!(#name)); + } + } + }; + gen.into() +} + +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(HelloMacro)] + struct Hellow { + pub message: string + } + + #[test] + fn it_works() { + let a = Hellow{message:"hellow"}; + a.hello_macro(); + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/crates/libs/migration/Cargo.toml b/crates/libs/migration/Cargo.toml new file mode 100644 index 0000000..2b6007a --- /dev/null +++ b/crates/libs/migration/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "migration" +version = "0.1.0" +publish = false +authors.workspace = true +edition.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true + +[lib] +name = "migration" +path = "src/lib.rs" + +[dependencies] +async-std = { version = "^1", features = ["attributes", "tokio1"] } +entity.workspace=true +sea-orm.workspace=true +sea-query.workspace=true +sea-orm-migration.workspace=true +#[dependencies.sea-orm-migration] +##version = "0.10.7" +#version = "0.12.3" +#features = [ +# # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI. +# # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime. +# # e.g. +# # "runtime-tokio-rustls", # `ASYNC_RUNTIME` feature +# "sqlx-postgres", +#] diff --git a/migration/README.md b/crates/libs/migration/README.md similarity index 100% rename from migration/README.md rename to crates/libs/migration/README.md diff --git a/migration/src/lib.rs b/crates/libs/migration/src/lib.rs similarity index 100% rename from migration/src/lib.rs rename to crates/libs/migration/src/lib.rs diff --git a/migration/src/main.rs b/crates/libs/migration/src/main.rs similarity index 100% rename from migration/src/main.rs rename to crates/libs/migration/src/main.rs diff --git a/migration/src/migration001.rs b/crates/libs/migration/src/migration001.rs similarity index 94% rename from migration/src/migration001.rs rename to crates/libs/migration/src/migration001.rs index 73a4cec..410c235 100644 --- a/migration/src/migration001.rs +++ b/crates/libs/migration/src/migration001.rs @@ -1,10 +1,11 @@ use sea_orm_migration::prelude::*; +use entity::admin::user; use entity::app::app; use entity::command; use entity::prelude::{case, case_block, data_binding}; -use entity::test::ui::action::{action, data, datatable, field, group as action_group, target}; -use entity::test::ui::profile::{data as profile_data, profile}; +use entity::test::ui::action::{action, data, group as action_group, target}; +use entity::test::{profile::{data as profile_data, profile}, datatable, field}; use entity::test::ui::suit::{suite, suite_block}; use crate::sea_orm::{ConnectionTrait, Statement}; @@ -14,6 +15,21 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + + //****************** Admin ****************** + + + manager.create_table(Table::create() + .table(user::Entity) + .if_not_exists() + .col(ColumnDef::new(user::Column::Id).integer().auto_increment().not_null().primary_key()) + .col(ColumnDef::new(user::Column::Name).string().not_null()) + .col(ColumnDef::new(user::Column::FirstName).string().not_null()) + .col(ColumnDef::new(user::Column::LastName).string()) + .col(ColumnDef::new(user::Column::Email).string().not_null()) + .to_owned(), + ).await?; + //****************** Application ****************** manager.create_table(Table::create() .table(app::Entity) @@ -171,7 +187,7 @@ impl MigrationTrait for Migration { manager.get_connection().execute( Statement::from_string( manager.get_database_backend(), - "alter table field add constraint com_key_id primary key (field_id, table_id)".parse().unwrap()) + "alter table field add constraint com_key_id primary key (field_id, table_id)") ) .await?; diff --git a/migration/src/migration002.rs b/crates/libs/migration/src/migration002.rs similarity index 100% rename from migration/src/migration002.rs rename to crates/libs/migration/src/migration002.rs diff --git a/migration/src/migration003.rs b/crates/libs/migration/src/migration003.rs similarity index 99% rename from migration/src/migration003.rs rename to crates/libs/migration/src/migration003.rs index aa74ac8..c305417 100644 --- a/migration/src/migration003.rs +++ b/crates/libs/migration/src/migration003.rs @@ -28,7 +28,7 @@ impl MigrationTrait for Migration { .to_owned(), ).await?; - + //****************** Application ****************** manager.create_table(Table::create() .table(attachment::Entity) diff --git a/api/Cargo.toml b/crates/services/api-old/Cargo.toml similarity index 76% rename from api/Cargo.toml rename to crates/services/api-old/Cargo.toml index 472d777..2e1c180 100644 --- a/api/Cargo.toml +++ b/crates/services/api-old/Cargo.toml @@ -1,12 +1,17 @@ [package] name = "api" version = "0.1.0" -edition = "2021" -authors = ["Vasanthkumar Kalaiselvan "] +authors.workspace = true +edition.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true [[bin]] -name = "api" +name = "apiold" path = "src/main.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -41,10 +46,10 @@ sea-orm = { version = "0.10.7", default-features = true, features = [ ] } -cerium = { path = "../cerium" } -migration = { path = "../migration" } -entity = { path = "../entity" } -engine = { path = "../engine" } +cerium = { workspace=true } +migration = { workspace=true } +entity = { workspace=true } +engine = { workspace=true } [dev-dependencies] diff --git a/api/src/bootstrap.rs b/crates/services/api-old/src/bootstrap.rs similarity index 100% rename from api/src/bootstrap.rs rename to crates/services/api-old/src/bootstrap.rs diff --git a/api/src/error.rs b/crates/services/api-old/src/error.rs similarity index 100% rename from api/src/error.rs rename to crates/services/api-old/src/error.rs diff --git a/api/src/main.rs b/crates/services/api-old/src/main.rs similarity index 90% rename from api/src/main.rs rename to crates/services/api-old/src/main.rs index 9abf7f8..ffd7cb5 100644 --- a/api/src/main.rs +++ b/crates/services/api-old/src/main.rs @@ -15,7 +15,7 @@ pub(crate) mod error; async fn main() -> std::io::Result<()> { init_logger(); - info!("!!! Starting Orca Application !!!"); + info!("!!! Starting Orca Application v2 !!!"); run_migration().await.expect("Failed to Migrating the Latest Version"); info!("Exiting Migrating DDL Command "); info!("Starting Application Server "); diff --git a/api/src/route/app/action.rs b/crates/services/api-old/src/route/app/action.rs similarity index 100% rename from api/src/route/app/action.rs rename to crates/services/api-old/src/route/app/action.rs diff --git a/api/src/route/app/case.rs b/crates/services/api-old/src/route/app/case.rs similarity index 100% rename from api/src/route/app/case.rs rename to crates/services/api-old/src/route/app/case.rs diff --git a/api/src/route/app/datatable.rs b/crates/services/api-old/src/route/app/datatable.rs similarity index 100% rename from api/src/route/app/datatable.rs rename to crates/services/api-old/src/route/app/datatable.rs diff --git a/api/src/route/app/group.rs b/crates/services/api-old/src/route/app/group.rs similarity index 100% rename from api/src/route/app/group.rs rename to crates/services/api-old/src/route/app/group.rs diff --git a/api/src/route/app/mod.rs b/crates/services/api-old/src/route/app/mod.rs similarity index 100% rename from api/src/route/app/mod.rs rename to crates/services/api-old/src/route/app/mod.rs diff --git a/engine/src/controller/suite.rs b/crates/services/api-old/src/route/app/object_repo.rs similarity index 100% rename from engine/src/controller/suite.rs rename to crates/services/api-old/src/route/app/object_repo.rs diff --git a/api/src/route/app/profile.rs b/crates/services/api-old/src/route/app/profile.rs similarity index 100% rename from api/src/route/app/profile.rs rename to crates/services/api-old/src/route/app/profile.rs diff --git a/api/src/route/app/suit.rs b/crates/services/api-old/src/route/app/suit.rs similarity index 100% rename from api/src/route/app/suit.rs rename to crates/services/api-old/src/route/app/suit.rs diff --git a/api/src/route/file.rs b/crates/services/api-old/src/route/file.rs similarity index 100% rename from api/src/route/file.rs rename to crates/services/api-old/src/route/file.rs diff --git a/api/src/route/mod.rs b/crates/services/api-old/src/route/mod.rs similarity index 100% rename from api/src/route/mod.rs rename to crates/services/api-old/src/route/mod.rs diff --git a/api/src/route/ws.rs b/crates/services/api-old/src/route/ws.rs similarity index 100% rename from api/src/route/ws.rs rename to crates/services/api-old/src/route/ws.rs diff --git a/api/src/server/context/mod.rs b/crates/services/api-old/src/server/context/mod.rs similarity index 100% rename from api/src/server/context/mod.rs rename to crates/services/api-old/src/server/context/mod.rs diff --git a/api/src/server/context/request.rs b/crates/services/api-old/src/server/context/request.rs similarity index 100% rename from api/src/server/context/request.rs rename to crates/services/api-old/src/server/context/request.rs diff --git a/api/src/server/middleware/mod.rs b/crates/services/api-old/src/server/middleware/mod.rs similarity index 100% rename from api/src/server/middleware/mod.rs rename to crates/services/api-old/src/server/middleware/mod.rs diff --git a/api/src/server/middleware/request.rs b/crates/services/api-old/src/server/middleware/request.rs similarity index 100% rename from api/src/server/middleware/request.rs rename to crates/services/api-old/src/server/middleware/request.rs diff --git a/api/src/server/mod.rs b/crates/services/api-old/src/server/mod.rs similarity index 100% rename from api/src/server/mod.rs rename to crates/services/api-old/src/server/mod.rs diff --git a/api/src/utils/client/mod.rs b/crates/services/api-old/src/utils/client/mod.rs similarity index 100% rename from api/src/utils/client/mod.rs rename to crates/services/api-old/src/utils/client/mod.rs diff --git a/api/src/utils/config.rs b/crates/services/api-old/src/utils/config.rs similarity index 100% rename from api/src/utils/config.rs rename to crates/services/api-old/src/utils/config.rs diff --git a/api/src/utils/mod.rs b/crates/services/api-old/src/utils/mod.rs similarity index 100% rename from api/src/utils/mod.rs rename to crates/services/api-old/src/utils/mod.rs diff --git a/api/tests/mod.rs b/crates/services/api-old/tests/mod.rs similarity index 100% rename from api/tests/mod.rs rename to crates/services/api-old/tests/mod.rs diff --git a/api/tests/seed_data.rs b/crates/services/api-old/tests/seed_data.rs similarity index 100% rename from api/tests/seed_data.rs rename to crates/services/api-old/tests/seed_data.rs diff --git a/crates/services/api/Cargo.toml b/crates/services/api/Cargo.toml new file mode 100644 index 0000000..5fa964f --- /dev/null +++ b/crates/services/api/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "api" +authors.workspace = true +edition.workspace = true +version.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true +exclude.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde.workspace=true +serde_json.workspace=true +tracing.workspace=true +tracing-subscriber.workspace=true +jsonwebtoken.workspace=true +tower.workspace=true +tower-http.workspace=true +uuid.workspace=true +futures.workspace=true +futures-util.workspace=true +config.workspace=true +chrono.workspace=true + +sea-orm.workspace=true +sea-query.workspace=true +sea-orm-migration.workspace=true + +cerium.workspace=true +migration.workspace=true +entity.workspace=true +thiserror.workspace=true + +tokio = { version = "1.0", features = ["full"] } +axum = "0.7.2" + diff --git a/crates/services/api/src/error.rs b/crates/services/api/src/error.rs new file mode 100644 index 0000000..c8cf9be --- /dev/null +++ b/crates/services/api/src/error.rs @@ -0,0 +1,77 @@ +use axum::http::StatusCode; +use axum::Json; +use axum::response::{IntoResponse, Response}; +use sea_orm::DbErr; +use serde_json::{Error as SerdeJsonError, json}; +use thiserror::Error; +use crate::error::OrcaError::RepoError; + +// pub type OrcaResult = InternalResult; + +pub type InternalResult = Result; + +/// Errors that can happen when using the user repo. +#[derive(Error, Debug)] +pub enum OrcaRepoError { + #[error("Item Not Found: {0}")] + NotFound(String), + #[error("{0} Not Found: {1}")] + ModelNotFound(String, String), + #[error("Invalid UserName: {0}")] + InvalidUsername(i32), +} + +/// Our app's top level error type. +pub enum OrcaError { + /// Something went wrong when calling the user repo. + DataBaseError(DbErr), + RepoError(OrcaRepoError), + SerializerError(SerdeJsonError) +} + +/// This makes it possible to use `?` to automatically convert a `DbErr` +/// into an `OrcaError`. +impl From for OrcaError { + fn from(inner: OrcaRepoError) -> Self { + OrcaError::RepoError(inner) + } +} + +/// This makes it possible to use `?` to automatically convert a `DbErr` +/// into an `OrcaError`. +impl From for OrcaError { + fn from(inner: DbErr) -> Self { + OrcaError::DataBaseError(inner) + } +} + +/// This makes it possible to use `?` to automatically convert a `DbErr` +/// into an `OrcaError`. +impl From for OrcaError { + fn from(inner: SerdeJsonError) -> Self { + OrcaError::SerializerError(inner) + } +} + +impl IntoResponse for OrcaError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + OrcaError::DataBaseError(err) =>{ + (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) + } + OrcaError::SerializerError(err) => { + (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) + } + RepoError(err) => { + (StatusCode::NOT_FOUND, err.to_string()) + } + _ => (StatusCode::INTERNAL_SERVER_ERROR, "Internal Error Not Specify".to_string()) + }; + + let body = Json(json!({ + "error": error_message, + })); + + (status, body).into_response() + } +} \ No newline at end of file diff --git a/crates/services/api/src/main.rs b/crates/services/api/src/main.rs new file mode 100644 index 0000000..d9a6984 --- /dev/null +++ b/crates/services/api/src/main.rs @@ -0,0 +1,37 @@ +use std::sync::Arc; + +use sea_orm::{DatabaseConnection, DbErr}; +use tracing::Level; + +use cerium::client::Client; +use cerium::server::App; +use migration::MigratorTrait; + +use crate::server::middleware::OrcaLayer; +use crate::route::handle_router; + +pub(crate) mod route; +pub(crate) mod error; +pub(crate) mod service; +pub(crate) mod server; +pub(crate) mod utils; + + +pub(crate) async fn run_migration(db: &DatabaseConnection) -> Result<(), DbErr> { + migration::Migrator::up(db, None).await.expect("TODO: panic message"); + Ok(()) +} + + +#[tokio::main] +async fn main() { + let cli = Client::new(Some("postgres://root:root@localhost:5432/orca".to_string()), None).await; + let mut app = App::new("OrcaWeb", cli.clone()); + app.set_logger(Level::DEBUG); + app.set_port(8080); + + run_migration(cli.db()).await.expect("TODO: panic message"); + let routers = handle_router().layer(OrcaLayer { db: Arc::new(cli.db.clone()) }); + app.set_router(routers); + app.run().await; +} diff --git a/crates/services/api/src/route/admin/mod.rs b/crates/services/api/src/route/admin/mod.rs new file mode 100644 index 0000000..22d12a3 --- /dev/null +++ b/crates/services/api/src/route/admin/mod.rs @@ -0,0 +1 @@ +pub mod user; diff --git a/crates/services/api/src/route/admin/user.rs b/crates/services/api/src/route/admin/user.rs new file mode 100644 index 0000000..161ce2a --- /dev/null +++ b/crates/services/api/src/route/admin/user.rs @@ -0,0 +1,63 @@ +use axum::{Extension, Json, Router}; +use axum::extract::{Path, Query}; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, post}; +use sea_orm::{IntoActiveModel}; +use sea_orm::ActiveValue::Set; +use serde_json::json; +use tracing::info; + +use entity::admin::user; + +use crate::error::InternalResult; +use crate::route::Pagination; +use crate::server::session::OrcaSession; +use crate::service::admin::user::UserService; + +pub(crate) fn user_route() -> Router { + Router::new() + .route("/", post(create_user).get(list_user)) + .route("/:user_id",get(get_user_by_id) + .put(update_user_by_id) + .delete(delete_user_by_id) + ) +} + + + +/// create_user - this will create new User in Orca +async fn create_user(Extension(session): Extension, Json(body): Json) -> InternalResult { + let result = UserService::new(session).create_user(body.into_active_model()).await?; + Ok((StatusCode::CREATED, Json(result))) +} + + +/// list_user - this will list User in Orca +async fn list_user(Extension(session): Extension, page: Option>) -> InternalResult { + let _page = page.unwrap_or_default().0; + let result = UserService::new(session).list_users(_page).await?; + Ok(Json(result)) +} + +/// get_user - this will get User by ID in Orca +async fn get_user_by_id(Extension(session): Extension, Path(user_id): Path) -> InternalResult { + let result = UserService::new(session).get_user_by_id(user_id).await?; + Ok(Json(result)) +} + +/// update_user_by_id - update user by user ID in Orca +async fn update_user_by_id(Extension(session): Extension, Path(user_id): Path, Json(body): Json) -> InternalResult { + let mut _user = body.clone().into_active_model(); + _user.id = Set(user_id); + let result = UserService::new(session).update_user(_user).await?; + info!("User Got Updated - {:?}", user_id); + Ok(Json(result)) +} + +/// delete_user_by_id - delete user by User by ID in Orca +async fn delete_user_by_id(Extension(session): Extension, Path(user_id): Path) -> InternalResult { + UserService::new(session).delete_user_by_id(user_id).await?; + Ok(Json(json!({"status": "success"}))) +} + diff --git a/crates/services/api/src/route/app/action.rs b/crates/services/api/src/route/app/action.rs new file mode 100644 index 0000000..3f3129c --- /dev/null +++ b/crates/services/api/src/route/app/action.rs @@ -0,0 +1,59 @@ +use axum::{Extension, Json, Router}; +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, post, put}; +use sea_orm::prelude::Uuid; +use serde_json::json; + +use entity::test::ui::action::action::Model; + +use crate::error::InternalResult; +use crate::server::session::OrcaSession; +use crate::service::app::action::ActionService; + +/// action_route - this will register all the endpoint in ACTION route +pub(crate) fn action_route() -> Router { + Router::new() + .route("/", get(get_action).post(create_action)) + .route("/batch", post(batch_update_action)) + .route("/:action_id",put(update_action).delete(delete_action)) +} + +/// get_action - list all the Action Group in Specific Application in the Orca Application +async fn get_action(Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>) -> InternalResult { + let result = ActionService::new(session).get_actions(group_id).await?; + Ok(Json(result)) +} + + +/// create_action - this will create new Action Group in Application Application in Orca +async fn create_action(Extension(session): Extension, Path((_app_id, group_id)): Path<(Uuid, Uuid)>, + Json(body): Json) -> InternalResult { + let result = ActionService::new(session).create_action(group_id, body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + +/// batch_update_action - This will update batch Action Group in Application in Orca +async fn batch_update_action(Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>, + Json(body): Json>) -> InternalResult { + ActionService::new(session).batch_update_action(group_id, body).await?; + Ok(Json(json!({"status": "success"}))) +} + +/// update_action - this will create new Application in Orca +async fn update_action(Extension(session): Extension, + Path((_app_id, _group_id, action_id)): Path<(Uuid, Uuid, Uuid)>, + Json(body): Json) -> InternalResult { + let result = ActionService::new(session).update_action(action_id, body).await?; + Ok(Json(result)) +} + +/// delete_action - this will delete Action for Action Group in Application in Orca +async fn delete_action(Extension(session): Extension, + Path((_app_id, _group_id, action_id)): Path<(Uuid, Uuid, Uuid)>) -> InternalResult { + ActionService::new(session).delete_action(action_id).await?; + Ok(Json(json!({"status": "success"}))) +} diff --git a/crates/services/api/src/route/app/case.rs b/crates/services/api/src/route/app/case.rs new file mode 100644 index 0000000..56d3015 --- /dev/null +++ b/crates/services/api/src/route/app/case.rs @@ -0,0 +1,89 @@ + +use axum::{Extension, Json, Router}; +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, post}; +use uuid::Uuid; +use entity::prelude::case::Model; +use entity::prelude::case_block::Model as BlockModel; + +use crate::error::InternalResult; +use crate::server::session::OrcaSession; +use crate::service::app::case::CaseService; + +/// test_case_route - this will register all the endpoint in Suit route +pub(crate) fn test_case_route() -> Router { + Router::new() + .route("/", get(list_cases).post(create_case)) + .nest("/:case_id", + Router::new() + .route("/detail", get(get_case_info)) + .route("/run", post(dry_run)) + .nest( + "/block", + Router::new() + .route("/batch", post(update_block)) + .route("/", post(insert_block)) + ) + ) + +} + +/// list_cases - list all the Case that is Bind with Current Application +async fn list_cases(Extension(session): Extension, + Path(app_id): Path) -> InternalResult { + let result = CaseService::new(session, app_id).list_cases().await?; + Ok(Json(result)) +} + + +/// create_case - This will New Test Case for the specific Application in Orca +async fn create_case(Extension(session): Extension, Path(app_id): Path, + Json(body): Json) -> InternalResult { + let result = CaseService::new(session, app_id).create_case(body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + + +/// get_case_info - Get Case Info and the batch information with the list of block +async fn get_case_info(Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>) -> InternalResult { + let result = CaseService::new(session, app_id).get_case_info(case_id).await?; + Ok(Json(result)) +} + + +/// dry_run - Dry run the Test case +async fn dry_run(Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>) -> InternalResult { + let result = CaseService::new(session, app_id).run(case_id).await?; + Ok(Json(result)) +} + + +/// update_block - update test case Block +async fn update_block(Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>, + Json(body): Json>) -> InternalResult { + let result = CaseService::new(session, app_id).batch_update_case_block(case_id, body).await?; + Ok(Json(result)) +} + + +/// insert_block - This will Append New Block to the code for spe +async fn insert_block(Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>, + Json(body): Json) -> InternalResult { + let result = CaseService::new(session, app_id).push_block(case_id, body, None, None).await?; + Ok(Json(result)) +} + +// /// push_block - This will New Block to the code +// async fn push_block(Extension(session): Extension, +// Path((app_id, case_id)): Path<(Uuid, Uuid)>, +// Json(body): Json) -> InternalResult { +// let result = CaseService::new(session, app_id).push_block(case_id, body, None).await?; +// Ok(Json(result)) +// } + diff --git a/crates/services/api/src/route/app/case_old.rs b/crates/services/api/src/route/app/case_old.rs new file mode 100644 index 0000000..b446b56 --- /dev/null +++ b/crates/services/api/src/route/app/case_old.rs @@ -0,0 +1,215 @@ +use std::str::FromStr; + +use actix_web::{HttpResponse, web}; +use actix_web::web::Path; +use futures_util::StreamExt; +use log::{debug, info}; +use sea_orm::{ActiveModelTrait, Condition, InsertResult, IntoActiveModel, QuerySelect}; +use sea_orm::ActiveValue::Set; +use sea_orm::ColumnTrait; +use sea_orm::EntityTrait; +use sea_orm::prelude::Uuid; +use sea_orm::QueryFilter; +use sea_orm::QueryOrder; +use serde::Deserialize; + +use engine::controller::case::CaseController; +use engine::server::driver::UIHelper; +use entity::{prelude::*}; + +use crate::error::OrcaError; +use crate::utils::config::CONFIG; + +#[derive(Debug, Deserialize)] +pub struct QueryParams { + pub index: Option, + pub parent: Option, +} + +/// profile_config - this will register all the endpoint in profile route +pub fn test_case_config(cfg: &mut web::ServiceConfig) { + cfg.service( + web::scope("/case") + .route("/", web::get().to(get_cases)) + .route("/", web::post().to(create_case)) + .route("/{case_id}/detail/", web::get().to(get_case_info)) + .route("/{case_id}/batch/", web::post().to(batch_update_case_block)) + + .route("/{case_id}/block/{case_block_id}/", web::post().to(update_case_block)) + .route("/{case_id}/insert/", web::post().to(push_block)) + + .route("/{case_id}/run/", web::post().to(run)) + ); + +} + +/// list all the test cases in the Orca Application +async fn get_cases(path: Path) -> Result { + let app_id = path.into_inner(); + let _filter = Condition::all() + .add(case::Column::AppId.eq(app_id)); + let cases = case::Entity::find().filter(_filter) + .order_by_asc(case::Column::Name).all(&CONFIG.get().await.db_client).await + .expect("TODO: panic message"); + Ok(HttpResponse::Ok().json(cases)) +} + +/// Create New test case +async fn create_case(path: Path, mut body: web::Json) -> Result { + let app_id = path.into_inner(); + body.id = Uuid::new_v4(); + body.app_id = app_id; + let _case = body.clone().into_active_model(); + let result = _case.insert(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + Ok(HttpResponse::Ok().json(result)) +} + +/// get_case_info - Get Case Info +async fn get_case_info(path: Path<(Uuid, Uuid)>) -> Result { + let (_, case_id) = path.into_inner(); + let cases = case::Entity::find_by_id(case_id) + .one(&CONFIG.get().await.db_client).await + .expect("TODO: panic message"); + if let Some(mut case) = cases { + let _filter = Condition::all() + .add(case_block::Column::CaseId.eq(case_id)); + // let mut _case = case.into_active_model(); + let case_blocks = case_block::Entity::find().filter(_filter) + .order_by_asc(case_block::Column::ExecutionOrder).all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + case.case_execution = Some(serde_json::to_value(case_blocks).expect("TODO: panic message")); + return Ok(HttpResponse::Ok().json(case)); + }; + Ok(HttpResponse::NoContent().finish()) +} + +/// batch_update_case_block - update Case Block +async fn batch_update_case_block(path: Path<(Uuid, Uuid)>, mut body: web::Json>) -> Result { + let (_, case_id) = path.into_inner(); + let case_blocks : Vec = body.clone().into_iter().map(|mut block| { + block.case_id = case_id.clone(); + block.into_active_model() + }).collect(); + let blocks = case_block::Entity::insert_many(case_blocks) + .exec(&CONFIG.get().await.db_client).await + .expect("TODO: panic message"); + Ok(HttpResponse::NoContent().finish()) +} + +/// push_into_index - This will Append New Block to the code for spe +async fn push_into_index(path: Path<(Uuid, Uuid, i32)>, mut body: web::Json, param: web::Query) -> Result { + let (_, case_id, index) = path.into_inner(); + + let mut _filter = Condition::all() + .add(case_block::Column::CaseId.eq(case_id)); + if param.parent.is_some() { + _filter = _filter.add(case_block::Column::ParentId.eq(param.parent.unwrap())); + } + + let _index : i32 = match param.index { + Some(x) => x, + _ => { + let mut i = 1; + let blocks = case_block::Entity::find().filter(_filter.clone()) + .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + if let Some(b) = blocks.last() { + i = b.execution_order + 1; + } + i + } + }; + _filter = _filter.add(case_block::Column::ExecutionOrder.gte(index)); + + + let blocks = case_block::Entity::find().filter(_filter) + .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + for block in blocks { + let new_order = block.execution_order + 1; + let mut action_model = block.into_active_model(); + action_model.execution_order = Set(new_order); + action_model.save(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + } + body.id = Uuid::new_v4(); + body.case_id = case_id; + let _case = body.clone().into_active_model(); + debug!("{:?}", _case); + let result = _case.insert(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + Ok(HttpResponse::NoContent().finish()) +} + + +/// push_block - This will Append New Block to the code for spe +async fn push_block(path: Path<(Uuid, Uuid)>, mut body: web::Json, param: web::Query) -> Result { + let (_, case_id) = path.into_inner(); + + let mut _filter = Condition::all() + .add(case_block::Column::CaseId.eq(case_id)); + if param.parent.is_some() { + _filter = _filter.add(case_block::Column::ParentId.eq(param.parent.unwrap())); + } + let blocks = case_block::Entity::find().filter(_filter.clone()) + .order_by_desc(case_block::Column::ExecutionOrder).limit(1) + .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + let mut last_index = 1; + if let Some(b) = blocks.last() { + last_index = b.execution_order + 1; + } + let _index : i32 = match param.index { + Some(x) => { + let i = if x > last_index { last_index } else {x}; + i + }, + _ => last_index + }; + _filter = _filter.add(case_block::Column::ExecutionOrder.gte(_index)); + + + let blocks = case_block::Entity::find().filter(_filter) + .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + for block in blocks { + let new_order = block.execution_order + 1; + let mut action_model = block.into_active_model(); + action_model.execution_order = Set(new_order); + action_model.save(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + } + body.id = Uuid::new_v4(); + body.case_id = case_id; + body.execution_order = _index; + let _case = body.clone().into_active_model(); + debug!("{:?}", _case); + let result = _case.insert(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + Ok(HttpResponse::NoContent().finish()) +} + +/// update_case_block - this will update the single case block +async fn update_case_block(path: Path<(Uuid, Uuid, Uuid)>, body: web::Json) -> Result { + let (_, _, case_block_id) = path.into_inner(); + let case_block = case_block::Entity::find_by_id(case_block_id) + .one(&CONFIG.get().await.db_client).await + .expect("TODO: panic message"); + if let Some(_case_block) = case_block { + let mut _block: case_block::ActiveModel = _case_block.into(); + _block.kind = Set(body.kind.to_owned()); + // _block.execution_order = Set(body.execution_order.to_owned()); + _block.type_field = Set(body.type_field.to_owned()); + _block.reference = Set(body.reference.to_owned()); + _block.parent_id = Set(body.parent_id.to_owned()); + let _ = _block.save(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); + return Ok(HttpResponse::NoContent().finish()); + } + Ok(HttpResponse::NoContent().finish()) +} + +async fn run(path: Path<(Uuid, Uuid)>) -> Result { + let (_, case_id) = path.into_inner(); + let case = case::Entity::find_by_id(case_id) + .one(&CONFIG.get().await.db_client).await + .expect("TODO: panic message"); + + let ui_driver = UIHelper::default().await.expect("error"); + info!("got the driver"); + let controller = CaseController::new(&CONFIG.get().await.db_client, &ui_driver); + info!("got the controller"); + controller.process(&case.unwrap()).await.expect("error"); + ui_driver.driver.quit().await.expect("TODO: panic message"); + Ok(HttpResponse::NoContent().finish()) +} \ No newline at end of file diff --git a/crates/services/api/src/route/app/datatable.rs b/crates/services/api/src/route/app/datatable.rs new file mode 100644 index 0000000..927a235 --- /dev/null +++ b/crates/services/api/src/route/app/datatable.rs @@ -0,0 +1,110 @@ +use axum::{Extension, Json, Router}; +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, post}; +use sea_orm::prelude::Uuid; +use serde_json::{json, Value}; +use tracing::debug; + +use entity::test::datatable::Model; +use entity::test::field::Model as FieldModel; + +use crate::error::InternalResult; +use crate::server::session::OrcaSession; +use crate::service::app::datatable::{DatatableService, TableDataRequest}; + +/// datatable_route - this will register all the endpoint in Datatable route +pub(crate) fn datatable_route() -> Router { + Router::new() + .route("/", get(list_datatables).post(create_datatable)) + .nest("/:table_id", + Router::new() + .route("/batch", post(update_value)) + .route("/data/batch", post(update_value).get(get_data)) + .route("/field", post(create_field)) + .route("/", get(get_datatable).delete(delete_table).post(update_data)) + .route("/field/:field_id", post(delete_field)) + ) + +} + +/// list_datatables - list all the DataTable in Specific Application +async fn list_datatables(Extension(session): Extension, + Path((app_id)): Path) -> InternalResult { + let result = DatatableService::new(session, app_id).list_datatables().await?; + Ok(Json(result)) +} + + +/// create_datatable - this will create new Datatable in Application +async fn create_datatable(Extension(session): Extension, Path(app_id): Path, + Json(body): Json) -> InternalResult { + let result = DatatableService::new(session, app_id).create_datatable(body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + +/// get_datatable - Get the Basic Information for Datatable +async fn get_datatable(Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>) -> InternalResult { + + let result = DatatableService::new(session, app_id).get_datatable_info(table_id).await?; + Ok(Json(result)) +} + + +/// create_field - this will create field in Application +async fn create_field(Extension(session): Extension, Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json) -> InternalResult { + let result = DatatableService::new(session, app_id).create_new_field(table_id, body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + + +/// delete_field - this will delete field in Application +async fn delete_field(Extension(session): Extension, + Path((app_id, table_id, field_id)): Path<(Uuid, i32, String)>) + -> InternalResult { + DatatableService::new(session, app_id).drop_field(table_id, field_id).await?; + Ok((StatusCode::NO_CONTENT, Json(json!({"status": "success"})))) +} + +/// update_value - batch update the data in Datatable in Application +async fn update_value(Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json>) -> InternalResult { + DatatableService::new(session, app_id).batch_update_data(table_id, body).await?; + Ok(Json(json!({"status": "success"}))) +} + +/// get_data - get data for specify Datatable in Application +async fn get_data(Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>) -> InternalResult { + let response = DatatableService::new(session, app_id).get_data(table_id).await?; + Ok(Json(response)) +} + + +/// update_data - update data for specify Datatable in Application +async fn update_data(Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json) -> InternalResult { + let response = DatatableService::new(session, app_id).update_data(table_id, body).await?; + Ok(Json(response)) +} + + +/// update_data - update data for specify Datatable in Application +async fn delete_table(Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>) -> InternalResult { + let response = DatatableService::new(session, app_id).delete_table(table_id).await?; + Ok(Json(response)) +} + +/// update_table - update data for specify Datatable in Application +async fn update_table(Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json) -> InternalResult { + let response = DatatableService::new(session, app_id).delete_table(table_id).await?; + Ok(Json(response)) +} diff --git a/crates/services/api/src/route/app/group.rs b/crates/services/api/src/route/app/group.rs new file mode 100644 index 0000000..2f2fd2c --- /dev/null +++ b/crates/services/api/src/route/app/group.rs @@ -0,0 +1,48 @@ +use axum::{Extension, Json, Router}; +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, put}; +use sea_orm::prelude::Uuid; + +use entity::prelude::group::Model; + +use crate::error::InternalResult; +use crate::server::session::OrcaSession; +use crate::service::app::group::GroupService; + +/// group_route - this will register all the endpoint in ACTION group route +pub(crate) fn group_route() -> Router { + Router::new() + .route("/", get(get_groups).post(create_group)) + .route("/:group_id",put(update_action_group).delete(delete_action_group)) +} + +/// get_groups - list all the Action Group in Specific Application in the Orca Application +async fn get_groups(Extension(session): Extension, + Path(app_id): Path) -> InternalResult { + let result = GroupService::new(session).get_groups(app_id).await?; + Ok(Json(result)) +} + +/// create_group - This will create new Action Group in Application in Orca +async fn create_group(Extension(session): Extension, Path(app_id): Path, + Json(body): Json) -> InternalResult { + let result = GroupService::new(session).create_group(app_id, body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + +/// update_action_group - this will create new Application in Orca +async fn update_action_group(Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>, + Json(body): Json) -> InternalResult { + let result = GroupService::new(session).update_action_group(group_id, body).await?; + Ok(Json(result)) +} + +/// delete_action_group - this will delete Action Group in Application Application in Orca +async fn delete_action_group(Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>) -> InternalResult { + let result = GroupService::new(session).delete_group(group_id).await?; + Ok(Json(result)) +} diff --git a/crates/services/api/src/route/app/mod.rs b/crates/services/api/src/route/app/mod.rs new file mode 100644 index 0000000..3fa758a --- /dev/null +++ b/crates/services/api/src/route/app/mod.rs @@ -0,0 +1,82 @@ +use axum::{Extension, Json, Router}; +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, put}; +use uuid::Uuid; + +use entity::app::app::Model; + +use crate::error::InternalResult; +use crate::route::app::action::action_route; +use crate::route::app::case::test_case_route; +use crate::route::app::datatable::datatable_route; +use crate::route::app::group::group_route; +use crate::route::app::profile::profile_route; +use crate::route::app::suit::suite_route; +use crate::server::session::OrcaSession; +use crate::service::app::AppService; + +pub(crate) mod action; +pub(crate) mod group; +pub(crate) mod profile; +pub(crate) mod datatable; +pub(crate) mod suit; +pub(crate) mod case; + + +pub fn app_route() -> Router { + Router::new() + .route("/", get(get_app).post(create_app)) + .nest( + "/:app_id", + Router::new() + .route("/", put(update_app)) + .nest( + "/group", + group_route() + .merge( + Router::new().nest("/:group_id/action", action_route()) + ) + ) + .nest( + "/profile", + profile_route() + ) + .nest( + "/datatable", + datatable_route() + ) + .nest( + "/case", + test_case_route() + ) + .nest( + "/suite", + suite_route() + ) + ) +} + + +/// get_app - list all the Application in the Orca Application +async fn get_app(Extension(session): Extension) -> InternalResult { + println!("Heelo"); + let result = AppService::new(session).list_apps().await?; + Ok(Json(result)) +} + + +/// create_app - this will create new Application in Orca +async fn create_app(Extension(session): Extension, + Json(body): Json) -> InternalResult { + let result = AppService::new(session).create_app(body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + +/// update_app - this will update Application in Orca +async fn update_app(Extension(session): Extension, + Path(_app_id): Path, + Json(body): Json) -> InternalResult { + Ok(Json(body)) +} diff --git a/entity/src/auth/mod.rs b/crates/services/api/src/route/app/object_repo.rs similarity index 100% rename from entity/src/auth/mod.rs rename to crates/services/api/src/route/app/object_repo.rs diff --git a/crates/services/api/src/route/app/profile.rs b/crates/services/api/src/route/app/profile.rs new file mode 100644 index 0000000..2936b75 --- /dev/null +++ b/crates/services/api/src/route/app/profile.rs @@ -0,0 +1,65 @@ + +use axum::{Extension, Json, Router}; +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{delete, get, post, put}; +use sea_orm::prelude::Uuid; +use serde_json::json; +use entity::test::profile::profile::Model; + + +use crate::error::InternalResult; +use crate::server::session::OrcaSession; +use crate::service::app::profile::ProfileService; + +/// profile_route - this will register all the endpoint in profile route +pub(crate) fn profile_route() -> Router { + Router::new() + .route("/", get(list_profile).post(create_profile)) + .nest("/:profile_id", + Router::new() + .route("/", put(update_profile).delete(delete_profile)) + .route("/data/batch", delete(update_profile)) + .route("/data/{data_id}", delete(delete_profile_data)) + + ) +} + +/// list_profile - list all the Profile that is Binded with Current Application +async fn list_profile(Extension(session): Extension, + Path(app_id): Path) -> InternalResult { + let result = ProfileService::new(session, app_id).list_profile().await?; + Ok(Json(result)) +} + + +/// create_profile - This will New Profile for the specific Application in Orca +async fn create_profile(Extension(session): Extension, Path(app_id): Path, + Json(body): Json) -> InternalResult { + let result = ProfileService::new(session, app_id).create_profile(body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + +/// update_profile - this will update the existing profile information in Orca +async fn update_profile(Extension(session): Extension, + Path((app_id, profile_id)): Path<(Uuid, Uuid)>, + Json(body): Json) -> InternalResult { + let result = ProfileService::new(session, app_id).update_profile(profile_id, body).await?; + Ok(Json(result)) +} + +/// delete_profile - this will delete existing profile in Application Application in Orca +async fn delete_profile(Extension(session): Extension, + Path((app_id, profile_id)): Path<(Uuid, Uuid)>) -> InternalResult { + let result = ProfileService::new(session, app_id).delete_profile(profile_id).await?; + Ok(Json(json!({"status": "success"}))) +} + +/// delete_profile_data - this will delete existing profile data in Application Application in Orca +async fn delete_profile_data(Extension(session): Extension, + Path((app_id, profile_id, data_id)): Path<(Uuid, Uuid, Uuid)>) -> InternalResult { + let result = ProfileService::new(session, app_id).delete_profile_data(data_id).await?; + Ok(Json(json!({"status": "success"}))) +} + diff --git a/crates/services/api/src/route/app/suit.rs b/crates/services/api/src/route/app/suit.rs new file mode 100644 index 0000000..4a4d2e4 --- /dev/null +++ b/crates/services/api/src/route/app/suit.rs @@ -0,0 +1,236 @@ +// use actix_web::{HttpResponse, web}; +// use actix_web::web::Path; +// use log::debug; +// use sea_orm::{ActiveModelTrait, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryOrder, QuerySelect}; +// use sea_orm::ActiveValue::Set; +// use sea_orm::prelude::Uuid; +// use entity::test::ui::suit::{suite, suite_block}; +// use crate::error::OrcaError; +// use crate::utils::config::CONFIG; +// use sea_orm::QueryFilter; +// use entity::{prelude::*}; +// use crate::route::app::case::QueryParams; +// +// pub fn test_suit_config(cfg: &mut web::ServiceConfig) { +// cfg.service( +// web::scope("/suite") +// .route("/", web::get().to(get_suites)) +// .route("/", web::post().to(create_suit)) +// +// .route("/{suite_id}/detail/", web::get().to(get_suite_info)) +// .route("/{suite_id}/batch/", web::post().to(batch_update_suite_block)) +// +// // .route("/{suite_id}/block/{case_block_id}/", web::post().to(update_case_block)) +// .route("/{suite_id}/insert/", web::post().to(push_block)) +// // .route("/{suit_id}/detail/", web::get().to(get_case_info)) +// ); +// +// } +// +// /// list all the test suites in the Orca Application +// async fn get_suites(path: Path) -> Result { +// let app_id = path.into_inner(); +// let _filter = Condition::all() +// .add(suite::Column::AppId.eq(app_id)); +// let suites = suite::Entity::find().filter(_filter) +// .order_by_asc(suite::Column::Name).all(&CONFIG.get().await.db_client).await +// .expect("TODO: panic message"); +// Ok(HttpResponse::Ok().json(suites)) +// } +// +// +// async fn create_suit(path: Path, mut body: web::Json) -> Result { +// let app_id = path.into_inner(); +// body.id = Uuid::new_v4(); +// body.app_id = app_id; +// let _case = body.clone().into_active_model(); +// let result = _case.insert(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// Ok(HttpResponse::Ok().json(result)) +// } +// +// +// +// /// get_suits_info - Get Suite Info and the batch information with the list of block +// async fn get_suite_info(path: Path<(Uuid, Uuid)>) -> Result { +// let (_, suite_id) = path.into_inner(); +// let suites = suite::Entity::find_by_id(suite_id) +// .one(&CONFIG.get().await.db_client).await +// .expect("TODO: panic message"); +// if let Some(mut suite) = suites { +// let _filter = Condition::all() +// .add(suite_block::Column::SuiteId.eq(suite_id)); +// let suite_blocks = suite_block::Entity::find().filter(_filter) +// .order_by_asc(suite_block::Column::ExecutionOrder).all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// suite.suite_execution = Some(serde_json::to_value(suite_blocks).expect("TODO: panic message")); +// return Ok(HttpResponse::Ok().json(suite)); +// }; +// Ok(HttpResponse::NoContent().finish()) +// } +// +// /// batch_update_suite_block - update suite Block +// async fn batch_update_suite_block(path: Path<(Uuid, Uuid)>, mut body: web::Json>) -> Result { +// let (_, suite_id) = path.into_inner(); +// let suite_blocks : Vec = body.clone().into_iter().map(|mut block| { +// block.suite_id = suite_id.clone(); +// block.into_active_model() +// }).collect(); +// let blocks = suite_block::Entity::insert_many(suite_blocks) +// .exec(&CONFIG.get().await.db_client).await +// .expect("TODO: panic message"); +// Ok(HttpResponse::NoContent().finish()) +// } +// // +// // /// push_into_index - This will Append New Block to the code for spe +// // async fn push_into_index(path: Path<(Uuid, Uuid, i32)>, mut body: web::Json, param: web::Query) -> Result { +// // let (_, case_id, index) = path.into_inner(); +// // +// // let mut _filter = Condition::all() +// // .add(case_block::Column::CaseId.eq(case_id)); +// // if param.parent.is_some() { +// // _filter = _filter.add(case_block::Column::ParentId.eq(param.parent.unwrap())); +// // } +// // +// // let _index : i32 = match param.index { +// // Some(x) => x, +// // _ => { +// // let mut i = 1; +// // let blocks = case_block::Entity::find().filter(_filter.clone()) +// // .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// // if let Some(b) = blocks.last() { +// // i = b.execution_order + 1; +// // } +// // i +// // } +// // }; +// // _filter = _filter.add(case_block::Column::ExecutionOrder.gte(index)); +// // +// // +// // let blocks = case_block::Entity::find().filter(_filter) +// // .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// // for block in blocks { +// // let new_order = block.execution_order + 1; +// // let mut action_model = block.into_active_model(); +// // action_model.execution_order = Set(new_order); +// // action_model.save(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// // } +// // body.id = Uuid::new_v4(); +// // body.case_id = case_id; +// // let _case = body.clone().into_active_model(); +// // debug!("{:?}", _case); +// // let result = _case.insert(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// // Ok(HttpResponse::NoContent().finish()) +// // } +// +// +// /// push_block - This will Append New Block to the code for spe +// async fn push_block(path: Path<(Uuid, Uuid)>, mut body: web::Json, param: web::Query) -> Result { +// let (_, suite_id) = path.into_inner(); +// +// let mut _filter = Condition::all() +// .add(suite_block::Column::SuiteId.eq(suite_id)); +// // if param.parent.is_some() { +// // _filter = _filter.add(case_block::Column::ParentId.eq(param.parent.unwrap())); +// // } +// let blocks = suite_block::Entity::find().filter(_filter.clone()) +// .order_by_desc(suite_block::Column::ExecutionOrder).limit(1) +// .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// let mut last_index = 1; +// if let Some(b) = blocks.last() { +// last_index = b.execution_order + 1; +// } +// let _index : i32 = match param.index { +// Some(x) => { +// let i = if x > last_index { last_index } else {x}; +// i +// }, +// _ => last_index +// }; +// _filter = _filter.add(suite_block::Column::ExecutionOrder.gte(_index)); +// +// +// let blocks = suite_block::Entity::find().filter(_filter) +// .all(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// for block in blocks { +// let new_order = block.execution_order + 1; +// let mut action_model = block.into_active_model(); +// action_model.execution_order = Set(new_order); +// action_model.save(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// } +// body.id = Uuid::new_v4(); +// body.suite_id = suite_id; +// body.execution_order = _index; +// let _suite = body.clone().into_active_model(); +// debug!("{:?}", _suite); +// let result = _suite.insert(&CONFIG.get().await.db_client).await.expect("TODO: panic message"); +// Ok(HttpResponse::NoContent().finish()) +// } + + +use axum::{Extension, Json, Router}; +use axum::extract::Path; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, post}; +use uuid::Uuid; +use entity::test::ui::suit::suite::Model; +use entity::test::ui::suit::suite_block::Model as BlockModel; + +use crate::error::InternalResult; +use crate::server::session::OrcaSession; +use crate::service::app::suit::SuitService; + +/// suite_route - this will register all the endpoint in Suit route +pub(crate) fn suite_route() -> Router { + Router::new() + .route("/", get(list_suites).post(create_suite)) + .nest("/:suite_id", + Router::new() + .route("/batch/update", post(update_block)) + .nest( + "/block", + Router::new() + .route("/", get(get_suite_info).post(insert_block)) + ) + ) + +} + +/// list_suites - list all the Suites that is Bind with Current Application +async fn list_suites(Extension(session): Extension, + Path(app_id): Path) -> InternalResult { + let result = SuitService::new(session, app_id).list_suites().await?; + Ok(Json(result)) +} + + +/// create_profile - This will New Profile for the specific Application in Orca +async fn create_suite(Extension(session): Extension, Path(app_id): Path, + Json(body): Json) -> InternalResult { + let result = SuitService::new(session, app_id).create_suit(body).await?; + Ok((StatusCode::CREATED, Json(result))) +} + + +/// get_suits_info - Get Suite Info and the batch information with the list of block +async fn get_suite_info(Extension(session): Extension, + Path((app_id, suite_id)): Path<(Uuid, Uuid)>) -> InternalResult { + let result = SuitService::new(session, app_id).get_suite_info(suite_id).await?; + Ok(Json(result)) +} + +/// insert_block - This will Append New Block to the code for spe +async fn insert_block(Extension(session): Extension, + Path((app_id, suite_id)): Path<(Uuid, Uuid)>, + Json(body): Json) -> InternalResult { + let result = SuitService::new(session, app_id).push_block(suite_id, body, None).await?; + Ok(Json(result)) +} + + +/// update_block - update suite Block +async fn update_block(Extension(session): Extension, + Path((app_id, suite_id)): Path<(Uuid, Uuid)>, + Json(body): Json>) -> InternalResult { + let result = SuitService::new(session, app_id).batch_update_suite_block(suite_id, body).await?; + Ok(Json(result)) +} diff --git a/crates/services/api/src/route/mod.rs b/crates/services/api/src/route/mod.rs new file mode 100644 index 0000000..a990777 --- /dev/null +++ b/crates/services/api/src/route/mod.rs @@ -0,0 +1,47 @@ +use axum::Router; +use serde::Deserialize; +use crate::route::public::local_route; + +pub(crate) mod public; +pub(crate) mod admin; +pub(crate) mod app; + +fn v1_route() -> Router { + Router::new() + .nest("/user", admin::user::user_route()) + .nest("/app", app::app_route()) +} + + +pub fn handle_router() -> Router { + let api_routes = Router::new().nest("/v1", v1_route()); + let routes = Router::new() + .nest("/", local_route()) + .nest("/api", api_routes); + routes +} + +#[derive(Deserialize)] +pub struct Pagination { + pub offset: u64, + pub limit: u64, +} + +impl Pagination { + pub fn offset(&self) -> u64 { + self.offset + } + pub fn limit(&self) -> u64 { + self.limit + } + +} + +impl Default for Pagination { + fn default() -> Self { + Self { + offset: 1, + limit: 10 + } + } +} \ No newline at end of file diff --git a/crates/services/api/src/route/public.rs b/crates/services/api/src/route/public.rs new file mode 100644 index 0000000..8bb8e3b --- /dev/null +++ b/crates/services/api/src/route/public.rs @@ -0,0 +1,12 @@ +use axum::Router; +use axum::response::IntoResponse; +use axum::routing::get; + +pub fn local_route() -> Router<> { + Router::new().route("/ping", get(health_checker_handler)) +} + +async fn health_checker_handler() -> impl IntoResponse { + const MESSAGE: &str = "Pong"; + MESSAGE +} \ No newline at end of file diff --git a/crates/services/api/src/server/middleware/mod.rs b/crates/services/api/src/server/middleware/mod.rs new file mode 100644 index 0000000..d164e49 --- /dev/null +++ b/crates/services/api/src/server/middleware/mod.rs @@ -0,0 +1,62 @@ +use std::sync::Arc; +use std::task::{Context, Poll}; + +use axum::{async_trait, extract::Request, response::Response}; +use futures::executor::block_on; +use futures_util::future::BoxFuture; +use sea_orm::{DatabaseConnection, TransactionTrait}; +use tower::{Layer, Service}; +use tracing::info; +use crate::server::session::OrcaSession; + +pub mod orca; + + +#[derive(Clone)] +pub struct OrcaLayer { + pub db: Arc +} + +impl Layer for OrcaLayer { + type Service = OrcaMiddleware; + + fn layer(&self, inner: S) -> Self::Service { + OrcaMiddleware { db: self.db.clone(), inner } + } +} + +#[derive(Clone)] +pub struct OrcaMiddleware { + pub db: Arc, + inner: S, +} + +#[async_trait] +impl Service for OrcaMiddleware +where + S: Service + Send + 'static, + S::Future: Send + 'static, +{ + type Response = S::Response; + type Error = S::Error; + // `BoxFuture` is a type alias for `Pin>` + type Future = BoxFuture<'static, Result>; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, mut request: Request) -> Self::Future { + let ext = request.extensions_mut(); + let trx = block_on(self.db.begin()).expect("got error on trx"); + ext.insert(OrcaSession::new(trx.clone())); + let future = self.inner.call(request); + Box::pin(async move { + let mut response: Response = future.await?; + let headers = response.headers_mut(); + trx.commit().await.expect("TODO: panic message"); + info!("headers - {:?}", headers); + Ok(response) + }) + } +} \ No newline at end of file diff --git a/crates/services/api/src/server/middleware/orca.rs b/crates/services/api/src/server/middleware/orca.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/services/api/src/server/mod.rs b/crates/services/api/src/server/mod.rs new file mode 100644 index 0000000..7322c0b --- /dev/null +++ b/crates/services/api/src/server/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod session; +pub(crate) mod middleware; diff --git a/crates/services/api/src/server/session.rs b/crates/services/api/src/server/session.rs new file mode 100644 index 0000000..4838361 --- /dev/null +++ b/crates/services/api/src/server/session.rs @@ -0,0 +1,16 @@ +use sea_orm::DatabaseTransaction; + + +#[derive(Clone)] +pub struct OrcaSession(DatabaseTransaction); + +impl OrcaSession { + pub fn new(trx: DatabaseTransaction) -> Self{ + OrcaSession(trx) + } + pub fn trx(&self) -> &DatabaseTransaction { + &self.0 + } + +} + diff --git a/crates/services/api/src/service/admin/mod.rs b/crates/services/api/src/service/admin/mod.rs new file mode 100644 index 0000000..41e4ecf --- /dev/null +++ b/crates/services/api/src/service/admin/mod.rs @@ -0,0 +1 @@ +pub(crate) mod user; \ No newline at end of file diff --git a/crates/services/api/src/service/admin/user.rs b/crates/services/api/src/service/admin/user.rs new file mode 100644 index 0000000..1d94b52 --- /dev/null +++ b/crates/services/api/src/service/admin/user.rs @@ -0,0 +1,55 @@ +use sea_orm::{ActiveModelTrait, DatabaseTransaction, EntityTrait, NotSet, QuerySelect, TryIntoModel}; +use tracing::info; +use entity::admin::user; +use entity::admin::user::{ActiveModel, Model}; +use crate::error::{InternalResult, OrcaRepoError}; +use crate::route::Pagination; +use crate::server::session::OrcaSession; + +pub(crate) struct UserService(OrcaSession); + +impl UserService { + pub fn new(session: OrcaSession) -> Self { + Self(session) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + pub async fn create_user(&self, mut user: ActiveModel) -> InternalResult { + user.id = NotSet; + let result = user.insert(self.trx()).await?; + Ok(result) + } + + pub async fn list_users(&self, page: Pagination) -> InternalResult> { + let users = user::Entity::find() + .offset((page.offset() - 1) * page.limit()).limit(page.limit()) + .all(self.trx()).await?; + Ok(users) + } + + pub async fn get_user_by_id(&self, id: i32) -> InternalResult { + let user = user::Entity::find_by_id(id).one(self.trx()).await?; + if user.is_none(){ + return Err(OrcaRepoError::ModelNotFound("User".to_string(), id.to_string()))?; + } + return Ok(user.unwrap()); + } + + pub async fn update_user(&self, mut user: ActiveModel) -> InternalResult { + let result = user.save(self.trx()).await?.try_into_model()?; + return Ok(result); + } + + pub async fn delete_user_by_id(&self, id: i32) -> InternalResult<()> { + let result = user::Entity::delete_by_id(id).exec(self.trx()).await?; + if result.rows_affected == 0 { + return Err(OrcaRepoError::ModelNotFound("User".to_string(), id.to_string()))?; + } + info!("User Got deleted - {:?}, status - {:?}", id, result.rows_affected); + return Ok(()); + } + +} \ No newline at end of file diff --git a/crates/services/api/src/service/app/action.rs b/crates/services/api/src/service/app/action.rs new file mode 100644 index 0000000..6cc7608 --- /dev/null +++ b/crates/services/api/src/service/app/action.rs @@ -0,0 +1,86 @@ +use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, TryIntoModel}; +use sea_orm::ActiveValue::Set; +use sea_orm::prelude::Uuid; +use sea_query::Expr; +use tracing::info; + +use entity::test::ui::action::action; +use entity::test::ui::action::action::{ActiveModel, Model}; + +use crate::error::{InternalResult, OrcaRepoError}; +use crate::server::session::OrcaSession; + +pub(crate) struct ActionService(OrcaSession); + +impl ActionService { + pub fn new(session: OrcaSession) -> Self { + Self(session) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + /// get_actions - list all the Action Group in Specific Application in the Orca Application + pub async fn get_actions(&self, group_id: Uuid) -> InternalResult> { + let actions = action::Entity::find().filter(action::Column::ActionGroupId.eq(group_id)) + .order_by_asc(action::Column::ExecutionOrder).all(self.trx()).await?; + Ok(actions) + } + + /// create_action - this will create new Action Group in Application in Orca + pub async fn create_action(&self, group_id: Uuid, mut action: Model) -> InternalResult { + action.id = Uuid::new_v4(); + action.action_group_id = group_id; + let action = action.into_active_model(); + let result = action.insert(self.trx()).await?; + Ok(result) + } + + /// update_action - this will update existing Action in Application in Orca + pub async fn update_action(&self, action_id: Uuid, mut action: Model) -> InternalResult { + let mut _action = action::Entity::find_by_id(action_id).one(self.trx()).await?; + if _action.is_none() { + return Err(OrcaRepoError::ModelNotFound("Action".to_string(), action_id.to_string()))?; + } + let exist_action = _action.unwrap(); + let mut action = action.into_active_model(); + action.id = Set(action_id); + action.action_group_id = Set(exist_action.action_group_id); + let result = action.save(self.trx()).await?.try_into_model()?; + Ok(result) + } + + + /// delete_action - this will delete Action for Action Group in Application in Orca + pub async fn delete_action(&self, action_id: Uuid) -> InternalResult<()> { + let action = action::Entity::find_by_id(action_id).one(self.trx()).await?; + if action.is_none() { + return Err(OrcaRepoError::ModelNotFound("Action".to_string(), action_id.to_string()))?; + } + let _action = action.unwrap(); + let action_obj: action::ActiveModel = _action.into(); + let action_order = action_obj.clone().execution_order.unwrap(); + action_obj.delete(self.trx()).await?; + let update_result = action::Entity::update_many() + .col_expr(action::Column::ExecutionOrder, Expr::expr(Expr::col(action::Column::ExecutionOrder).if_null(0)).add(1)) + .filter(action::Column::ExecutionOrder.gt(action_order)) + .exec(self.trx()) + .await?; + info!("Updated the Action which have execution order gt {:?}, count - {:?}", action_order, update_result.rows_affected); + Ok(()) + } + + /// batch_update_action - This will update batch Action Group in Application in Orca + pub async fn batch_update_action(&self, group_id: Uuid, mut actions: Vec) -> InternalResult<()> { + let actions : Vec = actions.iter_mut().map(|item| { + item.id = Uuid::new_v4(); + item.action_group_id = group_id; + let _item = item.clone().into_active_model(); + return _item; + }).collect(); + action::Entity::insert_many(actions).exec(self.trx()).await?; + Ok(()) + } + +} diff --git a/crates/services/api/src/service/app/case.rs b/crates/services/api/src/service/app/case.rs new file mode 100644 index 0000000..5d00142 --- /dev/null +++ b/crates/services/api/src/service/app/case.rs @@ -0,0 +1,177 @@ +use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, QuerySelect, TryIntoModel}; +use sea_orm::ActiveValue::Set; +use sea_query::{Condition, Expr}; +use tracing::{debug, info}; +use uuid::Uuid; + +use entity::prelude::case::{Column, Entity, Model}; +use entity::prelude::case_block::{ActiveModel as BlockActiveModel, Column as BlockColumn, Entity as BlockEntity, Model as BlockModel}; + +use crate::error::{InternalResult, OrcaRepoError}; +use crate::server::session::OrcaSession; + +pub(crate) struct CaseService(OrcaSession, Uuid); + +impl CaseService { + pub fn new(session: OrcaSession, app_id: Uuid) -> Self { + Self(session, app_id) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + /// list all the test suites in the Orca Application + pub(crate) async fn list_cases(&self) -> InternalResult> { + let cases = Entity::find().filter(Column::AppId.eq(self.1)) + .order_by_asc(Column::Name) + .all(self.trx()).await?; + Ok(cases) + } + + /// create_case - this will create new Application in Orca + pub async fn create_case(&self, mut app: Model) -> InternalResult { + app.id = Uuid::new_v4(); + app.app_id = self.1; + let app = app.into_active_model(); + let result = app.insert(self.trx()).await?; + Ok(result) + } + + /// get_case_info - Get Case Info + pub async fn get_case_info(&self, case_id: Uuid) -> InternalResult { + let case = Entity::find_by_id(case_id).one(self.trx()).await?; + if case.is_none() { + return Err(OrcaRepoError::ModelNotFound("Test Case".to_string(), case_id.to_string()))?; + } + let mut case = case.unwrap(); + let case_blocks = BlockEntity::find().filter(BlockColumn::CaseId.eq(case_id)) + .order_by_asc(BlockColumn::ExecutionOrder).all(self.trx()).await?; + case.case_execution = Some(serde_json::to_value(case_blocks)?); + Ok(case) + } + + /// batch_update_case_block - update Case Block + pub async fn batch_update_case_block(&self, case_id: Uuid, + mut body: Vec) -> InternalResult<()> { + let case_blocks : Vec = body.into_iter().map(|mut block| { + block.case_id = case_id.clone(); + block.into_active_model() + }).collect(); + let blocks = BlockEntity::insert_many(case_blocks) + .exec(self.trx()).await?; + Ok(()) + } + + /// update_case_block - this will update the single case block + async fn update_case_block(&self, case_id: Uuid, case_block_id: Uuid, + mut body: BlockModel) -> InternalResult { + let case_block = BlockEntity::find_by_id(case_block_id) + .one(self.trx()).await?; + if case_block.is_none() { + return Err(OrcaRepoError::ModelNotFound("Test Case Block".to_string(), case_block_id.to_string()))?; + } + let mut _block = case_block.unwrap().into_active_model(); + _block.kind = Set(body.kind.to_owned()); + // _block.execution_order = Set(body.execution_order.to_owned()); + _block.type_field = Set(body.type_field.to_owned()); + _block.reference = Set(body.reference.to_owned()); + _block.parent_id = Set(body.parent_id.to_owned()); + let result = _block.save(self.trx()).await?; + Ok(result.try_into_model()?) + } + + /// run - this will run the single tes case + pub async fn run(&self, case_id: Uuid) -> InternalResult<()> { + let case = Entity::find_by_id(case_id) + .one(self.trx()).await?; + if case.is_none() { + return Err(OrcaRepoError::ModelNotFound("Test Case".to_string(), case_id.to_string()))?; + } + + // let ui_driver = UIHelper::default().await.expect("error"); + // info!("got the driver"); + // let controller = CaseController::new(&CONFIG.get().await.db_client, &ui_driver); + // info!("got the controller"); + // controller.process(&case.unwrap()).await.expect("error"); + // ui_driver.driver.quit().await.expect("TODO: panic message"); + Ok(()) + } + + /// push_into_index - This will Append New Block to the code for spe + async fn push_into_index(&self, case_id: Uuid, mut body: BlockModel, + parent: Option, index: Option) -> InternalResult { + + let mut _filter = Condition::all().add(BlockColumn::CaseId.eq(case_id)); + + if parent.is_some() { + _filter = _filter.add(BlockColumn::ParentId.eq(parent.unwrap())); + } + + let _index : i32 = match index { + Some(x) => x, + _ => { + let mut i = 1; + let blocks = BlockEntity::find().filter(_filter.clone()) + .all(self.trx()).await?; + if let Some(b) = blocks.last() { + i = b.execution_order + 1; + } + i + } + }; + _filter = _filter.add(BlockColumn::ExecutionOrder.gte(index)); + + let update_result = BlockEntity::update_many() + .col_expr(BlockColumn::ExecutionOrder, Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1)) + .filter(_filter) + .exec(self.trx()) + .await?; + + body.id = Uuid::new_v4(); + body.case_id = case_id; + let _case = body.clone().into_active_model(); + debug!("{:?}", _case); + let result = _case.insert(self.trx()).await?; + Ok(result) + } + + /// push_block - This will Append New Case + pub(crate) async fn push_block(&self, case_id: Uuid, mut body: BlockModel, + index: Option, parent: Option) -> InternalResult { + + let mut _filter = Condition::all().add(BlockColumn::CaseId.eq(case_id)); + if parent.is_some() { + _filter = _filter.add(BlockColumn::ParentId.eq(parent.unwrap())); + } + let blocks = BlockEntity::find().filter(_filter.clone()) + .order_by_desc(BlockColumn::ExecutionOrder).limit(1) + .all(self.trx()).await?; + let mut last_index = 1; + if let Some(last_item) = blocks.last() { + last_index = last_item.execution_order + 1; + } + let _index : i32 = match index { + Some(x) => { + let i = if x > last_index { last_index } else {x}; + i + }, + _ => last_index + }; + _filter = _filter.add(BlockColumn::ExecutionOrder.gte(_index)); + + let update_result = BlockEntity::update_many() + .col_expr(BlockColumn::ExecutionOrder, Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1)) + .filter(_filter) + .exec(self.trx()) + .await?; + body.id = Uuid::new_v4(); + body.case_id = case_id; + body.execution_order = _index; + let _case = body.clone().into_active_model(); + info!("{:?}", _case); + let result = _case.insert(self.trx()).await?; + Ok(result) + } + +} diff --git a/crates/services/api/src/service/app/datatable.rs b/crates/services/api/src/service/app/datatable.rs new file mode 100644 index 0000000..1bb9392 --- /dev/null +++ b/crates/services/api/src/service/app/datatable.rs @@ -0,0 +1,184 @@ +use chrono::Utc; +use futures_util::StreamExt; +use sea_orm::{ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseBackend, DatabaseTransaction, EntityTrait, IntoActiveModel, JsonValue, ModelTrait, NotSet, QueryFilter, QueryOrder, QueryResult, Statement, TryIntoModel}; +use sea_orm::ActiveValue::Set; +use sea_orm_migration::SchemaManager; +use sea_query::{Alias, Asterisk, ColumnDef, Condition, Expr, Order, PostgresQueryBuilder, Query, Table}; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use tracing::info; +use uuid::Uuid; + +use entity::test::datatable::{Column, Entity, Model}; +use entity::test::field::{Column as FieldColumn, Entity as FieldEntity, Model as FieldModel}; + +use crate::error::{InternalResult, OrcaRepoError}; +use crate::server::session::OrcaSession; +use crate::utils::replace_special_chars; + +#[derive(Clone, Deserialize, Serialize)] +pub(crate) struct TableDataRequest { + pub row_id: i32, + pub field_id: String, + pub data: String +} + +pub(crate) struct DatatableService(OrcaSession, Uuid); + +impl DatatableService { + pub fn new(session: OrcaSession, app_id: Uuid) -> Self { + Self(session, app_id) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + /// list_datatables - list all the DataTable in Specific Application in the Orca + pub async fn list_datatables(&self) -> InternalResult> { + let tables = Entity::find().filter(Column::AppId.eq(self.1)) + .order_by_asc(Column::Name).all(self.trx()).await?; + Ok(tables) + } + + /// get_datatable - Get the datatable by id in application + pub async fn get_datatable(&self, id: i32) -> InternalResult { + let tables = Entity::find_by_id(id).one(self.trx()).await?; + if tables.is_none() { + return Err(OrcaRepoError::ModelNotFound("Datatable".to_string(), id.to_string()))?; + } + Ok(tables.unwrap()) + } + + + /// get_datatable - Get the datatable by id in application + pub async fn get_datatable_info(&self, id: i32) -> InternalResult { + let mut table = self.get_datatable(id).await?; + let fields = table.find_related(FieldEntity).all(self.trx()).await?; + table.fields = Some(fields); + Ok(table) + } + + + /// create_datatable - this will create new DataTable in Application in Orca + pub async fn create_datatable(&self, mut table: Model) -> InternalResult { + table.app_id = self.1; + table.table_name = format!("table_{:?}", Utc::now().timestamp_micros()); + let mut _table = table.into_active_model(); + _table.id = NotSet; + let result = _table.insert(self.trx()).await?; + let stm = format!(r#"CREATE TABLE IF NOT EXISTS {} (id SERIAL NOT NULL PRIMARY KEY )"#, result.table_name); + let exec_res= self.trx().execute(Statement::from_string(DatabaseBackend::Postgres, stm)).await?; + info!("Created the Table - {:?}", exec_res); + Ok(result) + } + + /// create_new_field - this will create new Field in Data Application in Orca + pub async fn create_new_field(&self, mut table_id: i32, mut field: FieldModel) -> InternalResult { + let table = self.get_datatable(table_id).await?; + field.table_id = table_id; + let mut field = field.into_active_model(); + let _field_id = replace_special_chars(field.name.clone().unwrap().as_str(), '_'); + let mut field_id = _field_id.clone(); + let mut iter = 0; + loop { + field.field_id = Set(field_id.clone()); + let result = field.clone().insert(self.trx()).await; + if !result.is_err(){ + break + } + iter += 1; + field_id = format!("{_field_id}_{iter}"); + } + let manager = SchemaManager::new(self.trx()); + let res = manager.alter_table( + Table::alter().table(Alias::new(table.table_name)) + .add_column(ColumnDef::new(Alias::new(field_id.clone())).string()) + .to_owned() + ).await?; + + Ok(field.try_into_model()?) + } + + /// drop_field - this will drop Field in Data Application in Orca + pub async fn drop_field(&self, table_id: i32, field_id: String) -> InternalResult<()> { + let _filter = Condition::all() + .add(FieldColumn::FieldId.eq(field_id.clone())) + .add(FieldColumn::TableId.eq(table_id)); + + let manager = SchemaManager::new(self.trx()); + manager.alter_table( + Table::alter().table(FieldEntity) + .drop_column(Alias::new(field_id.clone())).to_owned() + ).await?; + let result = FieldEntity::delete_many().filter(_filter).exec(self.trx()).await?; + info!("Deleted Column({:?}) from Table ({:?})", field_id, table_id); + info!("field Removed {:?}", result.rows_affected); + Ok(()) + } + + /// batch_update_data - this will Batch update data in Application Datatable + pub async fn batch_update_data(&self, table_id: i32, + mut table_datas: Vec) -> InternalResult<()> { + let table = self.get_datatable(table_id).await?; + // let result = table_datas.iter_mut().map(|item| { + // return 1; + // }).collect::>()?; + for data in table_datas { + let query = Query::update() + .table(Alias::new(table.table_name.clone())) + .values([(Alias::new(data.field_id), data.data.into())]) + .and_where(Expr::col(Alias::new("id")).eq(data.row_id)) + .to_owned().to_string(PostgresQueryBuilder); + self.trx().execute(Statement::from_string(DatabaseBackend::Postgres, + query)).await?; + } + Ok(()) + } + + /// get_data - get data for specify Datatable in Application + pub async fn get_data(&self, table_id: i32) -> InternalResult> { + let table = self.get_datatable(table_id).await?; + let query = Query::select() + .from(Alias::new(table.table_name.clone())) + .expr(Expr::col(Asterisk)) + .order_by(Alias::new("id"), Order::Asc) + .to_owned().to_string(PostgresQueryBuilder); + let data = Entity::find() + .from_raw_sql(Statement::from_string( + DatabaseBackend::Postgres, + query + )) + .into_model::() + .all(self.trx()) + .await?; + Ok(data) + } + /// update_data - get data for specify Datatable in Application + pub async fn update_data(&self, table_id: i32, value: Value) -> InternalResult<()> { + let table = self.get_datatable(table_id).await?; + let query = Query::insert() + .into_table(Alias::new(table.table_name.clone())).or_default_values() + .to_owned().to_string(PostgresQueryBuilder); + self.trx().execute(Statement::from_string(DatabaseBackend::Postgres, + query)).await?; + Ok(()) + } + + + /// delete_action - this will delete Action for Action Group in Application in Orca + pub async fn delete_table(&self, table_id: i32) -> InternalResult<()> { + let table = Entity::find_by_id(table_id).one(self.trx()).await?; + if table.is_none() { + return Err(OrcaRepoError::ModelNotFound("Table".to_string(), table_id.to_string()))?; + } + let table = table.unwrap(); + let manager = SchemaManager::new(self.trx()); + let res = manager.drop_table( + Table::drop().table(Alias::new(table.table_name.clone())) + .to_owned() + ).await?; + table.delete(self.trx()).await?; + Ok(()) + } +} diff --git a/crates/services/api/src/service/app/group.rs b/crates/services/api/src/service/app/group.rs new file mode 100644 index 0000000..1796aef --- /dev/null +++ b/crates/services/api/src/service/app/group.rs @@ -0,0 +1,67 @@ +use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, TryIntoModel}; +use sea_query::Condition; +use tracing::info; +use uuid::Uuid; + +use entity::prelude::group::{ActionGroupKind, Column, Entity, Model}; + +use crate::error::{InternalResult, OrcaRepoError}; +use crate::server::session::OrcaSession; + +pub(crate) struct GroupService(OrcaSession); + +impl GroupService { + pub fn new(session: OrcaSession) -> Self { + Self(session) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + + /// get_groups - list all the Action Group in Specific Application in the Orca Application + pub async fn get_groups(&self, app_id: Uuid) -> InternalResult> { + let _filter = Condition::all() + .add(Column::AppId.eq(app_id)) + .add(Column::TypeField.eq(ActionGroupKind::ActionGroup)); + let groups = Entity::find().filter(_filter) + .order_by_asc(Column::Name).all(self.trx()).await?; + Ok(groups) + } + + /// create_group - This will create new Action Group in Application in Orca + pub async fn create_group(&self, app_id: Uuid, mut group: Model) -> InternalResult { + group.id = Uuid::new_v4(); + group.app_id = app_id; + let app = group.into_active_model(); + let result = app.insert(self.trx()).await?; + Ok(result) + } + + /// update_action_group - this will create new Application in Orca + pub async fn update_action_group(&self, group_id: Uuid, mut group: Model) -> InternalResult { + let _group = Entity::find_by_id(group_id) + .one(self.trx()).await?; + if _group.is_none() { + return Err(OrcaRepoError::ModelNotFound("Action Group".to_string(), group_id.to_string()))?; + } + let group = group.into_active_model(); + let result = group.save(self.trx()).await?; + Ok(result.try_into_model()?) + } + + /// delete_action_group - this will delete Action Group in Application Application in Orca + pub async fn delete_group(&self, group_id: Uuid) -> InternalResult<()> { + let result = Entity::delete_by_id(group_id).exec(self.trx()).await?; + if result.rows_affected == 0 { + return Err(OrcaRepoError::ModelNotFound("Action Group".to_string(), group_id.to_string()))?; + } + info!("Deleting Action group - {:?}", group_id); + Ok(()) + } + +} + + + diff --git a/crates/services/api/src/service/app/mod.rs b/crates/services/api/src/service/app/mod.rs new file mode 100644 index 0000000..03a6bfd --- /dev/null +++ b/crates/services/api/src/service/app/mod.rs @@ -0,0 +1,51 @@ +use sea_orm::{ActiveModelTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryOrder}; +use uuid::Uuid; +use entity::app::app::{Column, Entity, Model}; +use crate::error::InternalResult; +use crate::server::session::OrcaSession; + +pub(crate) mod action; +pub(crate) mod group; +pub(crate) mod profile; +pub(crate) mod datatable; +pub(crate) mod suit; +pub(crate) mod case; + + +pub(crate) struct AppService(OrcaSession); + +impl AppService { + pub fn new(session: OrcaSession) -> Self { + Self(session) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + /// list all the Application in the Orca Application + pub async fn list_apps(&self) -> InternalResult> { + let actions = Entity::find() + .order_by_asc(Column::Name).all(self.trx()).await?; + Ok(actions) + } + + /// create_app - this will create new Application in Orca + pub async fn create_app(&self, mut app: Model) -> InternalResult { + app.id = Uuid::new_v4(); + let app = app.into_active_model(); + let result = app.insert(self.trx()).await?; + Ok(result) + } + + /// create_app - this will create new Application in Orca + pub async fn update_app(&self, mut app: Model) -> InternalResult { + app.id = Uuid::new_v4(); + let app = app.into_active_model(); + let result = app.insert(self.trx()).await?; + Ok(result) + } + +} + + diff --git a/crates/services/api/src/service/app/object_repo.rs b/crates/services/api/src/service/app/object_repo.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/services/api/src/service/app/profile.rs b/crates/services/api/src/service/app/profile.rs new file mode 100644 index 0000000..b5b20a9 --- /dev/null +++ b/crates/services/api/src/service/app/profile.rs @@ -0,0 +1,85 @@ +use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder}; +use sea_query::Condition; +use tracing::info; +use uuid::Uuid; +use entity::test::profile::data::{Column as DataColumn, Entity as DataEntity, Model as DataModel}; +use entity::test::profile::profile::{Column, Entity, Model}; +use crate::error::{InternalResult, OrcaRepoError}; +use crate::server::session::OrcaSession; + +pub(crate) struct ProfileService(OrcaSession, Uuid); + +impl ProfileService { + pub fn new(session: OrcaSession, app_id: Uuid) -> Self { + Self(session, app_id) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + /// list_profile - list all the Profile that is Bound with Current Application + pub async fn list_profile(&self) -> InternalResult> { + let _filter = Condition::all().add(Column::AppId.eq(self.1)); + let profiles = Entity::find().filter(_filter).order_by_asc(Column::Name).all(self.trx()).await?; + Ok(profiles) + } + + /// create_profile - This will New Profile for the specific Application in Orca + pub async fn create_profile(&self, mut profile: Model) -> InternalResult { + profile.id = Uuid::new_v4(); + profile.app_id = self.1; + let _profile = profile.into_active_model(); + let result = _profile.insert(self.trx()).await?; + Ok(result) + } + + /// update_profile - this will update the existing profile information in Orca + pub async fn update_profile(&self, profile_id: Uuid, mut profile: Model) -> InternalResult { + let _profile = Entity::find_by_id(profile_id).one(self.trx()).await?; + if _profile.is_none() { + return Err(OrcaRepoError::ModelNotFound("Profile".to_string(), profile_id.to_string()))?; + } + profile.id = profile_id; + profile.app_id = self.1.clone(); + let _profile = profile.into_active_model(); + let result = _profile.update(self.trx()).await?; + Ok(result) + } + + /// delete_profile - this will delete existing profile in Application Application in Orca + pub async fn delete_profile(&self, profile_id: Uuid) -> InternalResult<()> { + let result = Entity::delete_by_id(profile_id).exec(self.trx()).await?; + if result.rows_affected == 0 { + return Err(OrcaRepoError::ModelNotFound("Profile".to_string(), profile_id.to_string()))?; + } + info!("Deleted Application Profile - {:?}", profile_id); + info!("Deleting Application Profile Data of ProfileID- {:?}", profile_id); + let result = DataEntity::delete_many() + .filter(DataColumn::ProfileId.eq(profile_id)) + .exec(self.trx()).await?; + info!("Deleted Application Profile Data of ProfileID- {:?}, count - {:?}", profile_id, result.rows_affected); + Ok(()) + } + + /// delete_profile_data - this will delete existing profile data in Application Application in Orca + pub async fn delete_profile_data(&self, _data_id: Uuid) -> InternalResult<()> { + let result = DataEntity::delete_by_id(_data_id).exec(self.trx()).await?; + if result.rows_affected == 0 { + return Err(OrcaRepoError::ModelNotFound("Profile Item Data".to_string(), _data_id.to_string()))?; + } + info!("Deleted Application Profile Data - {:?}", _data_id); + Ok(()) + } + + /// batch_update_action - This will update batch Action Group in Application in Orca + pub async fn batch_update_action(&self, _data_id: Uuid) -> InternalResult<()> { + let result = DataEntity::delete_by_id(_data_id).exec(self.trx()).await?; + if result.rows_affected == 0 { + return Err(OrcaRepoError::ModelNotFound("Profile Item Data".to_string(), _data_id.to_string()))?; + } + info!("Deleted Application Profile Data - {:?}", _data_id); + Ok(()) + } + +} diff --git a/crates/services/api/src/service/app/suit.rs b/crates/services/api/src/service/app/suit.rs new file mode 100644 index 0000000..3a74a6f --- /dev/null +++ b/crates/services/api/src/service/app/suit.rs @@ -0,0 +1,103 @@ +use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, QuerySelect}; +use sea_query::{Condition, Expr}; +use tracing::info; +use uuid::Uuid; + +use entity::test::ui::suit::suite::{Column, Entity, Model}; +use entity::test::ui::suit::suite_block::{ActiveModel, Column as BlockColumn, Entity as BlockEntity, Model as BlockModel}; + +use crate::error::{InternalResult, OrcaRepoError}; +use crate::server::session::OrcaSession; + +pub(crate) struct SuitService(OrcaSession, Uuid); + +impl SuitService { + pub fn new(session: OrcaSession, app_id: Uuid) -> Self { + Self(session, app_id) + } + + pub fn trx(&self) -> &DatabaseTransaction { + self.0.trx() + } + + /// list all the test suites in the Orca Application + pub(crate) async fn list_suites(&self) -> InternalResult> { + let suites = Entity::find().filter(Column::AppId.eq(self.1)) + .order_by_asc(Column::Name) + .all(self.trx()).await?; + Ok(suites) + } + + pub(crate) async fn create_suit(&self, mut body: Model) -> InternalResult { + body.id = Uuid::new_v4(); + body.app_id = self.1; + let _case = body.into_active_model(); + let result = _case.insert(self.trx()).await?; + return Ok(result) + } + + /// batch_update_suite_block - update suite Block + pub(crate) async fn batch_update_suite_block(&self, suite_id: Uuid, + mut body: Vec) -> InternalResult<()> { + let suit_blocks: Vec = body.into_iter().map(|mut block|{ + block.suite_id = suite_id.clone(); + block.into_active_model() + }).collect(); + let blocks = BlockEntity::insert_many(suit_blocks) + .exec(self.trx()).await?; + Ok(()) + } + + /// get_suits_info - Get Suite Info and the batch information with the list of block + pub(crate) async fn get_suite_info(&self, suite_id: Uuid) -> InternalResult { + let suite = Entity::find_by_id(suite_id) + .one(self.trx()).await?; + if suite.is_none() { + return Err(OrcaRepoError::ModelNotFound("Test Suite".to_string(), suite_id.to_string()))?; + } + let mut suite = suite.unwrap(); + let suite_blocks = BlockEntity::find() + .filter(BlockColumn::SuiteId.eq(suite_id)) + .order_by_asc(BlockColumn::ExecutionOrder) + .all(self.trx()).await?; + suite.suite_execution = Some(serde_json::to_value(suite_blocks)?); + Ok(suite) + } + + /// push_block - This will Append New Block to the code for spe + pub(crate) async fn push_block(&self, suite_id: Uuid, mut body: BlockModel, index: Option) -> InternalResult { + + let mut _filter = Condition::all().add(BlockColumn::SuiteId.eq(suite_id)); + // if param.parent.is_some() { + // _filter = _filter.add(case_block::Column::ParentId.eq(param.parent.unwrap())); + // } + let blocks = BlockEntity::find().filter(_filter.clone()) + .order_by_desc(BlockColumn::ExecutionOrder).limit(1) + .all(self.trx()).await?; + let mut last_index = 1; + if let Some(last_item) = blocks.last() { + last_index = last_item.execution_order + 1; + } + let _index : i32 = match index { + Some(x) => { + let i = if x > last_index { last_index } else {x}; + i + }, + _ => last_index + }; + _filter = _filter.add(BlockColumn::ExecutionOrder.gte(_index)); + + let update_result = BlockEntity::update_many() + .col_expr(BlockColumn::ExecutionOrder, Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1)) + .filter(_filter) + .exec(self.trx()) + .await?; + body.id = Uuid::new_v4(); + body.suite_id = suite_id; + body.execution_order = _index; + let _suite = body.clone().into_active_model(); + info!("{:?}", _suite); + let result = _suite.insert(self.trx()).await?; + Ok(result) + } +} \ No newline at end of file diff --git a/crates/services/api/src/service/mod.rs b/crates/services/api/src/service/mod.rs new file mode 100644 index 0000000..ee12753 --- /dev/null +++ b/crates/services/api/src/service/mod.rs @@ -0,0 +1,22 @@ +use axum::async_trait; +use sea_orm::{ActiveModelBehavior, ActiveModelTrait, DatabaseTransaction, ModelTrait}; +use crate::error::InternalResult; + +pub(crate) mod admin; +pub(crate) mod app; + + +// #[async_trait] +// pub trait CrudService { +// +// fn trx(&self) -> &DatabaseTransaction; +// +// async fn new(self, am: AM) -> InternalResult +// where +// AM: ActiveModelTrait, +// M: ModelTrait +// { +// let result = am.insert(self.trx()).await?; +// // Ok(result) +// } +// } \ No newline at end of file diff --git a/crates/services/api/src/utils/mod.rs b/crates/services/api/src/utils/mod.rs new file mode 100644 index 0000000..7e4d31a --- /dev/null +++ b/crates/services/api/src/utils/mod.rs @@ -0,0 +1,15 @@ + + + +pub fn replace_special_chars(input: &str, replace_with: char) -> String { + let mut result = String::with_capacity(input.len()); + + for c in input.chars() { + if c.is_ascii_alphanumeric() || c == replace_with { + result.push(c); + } else { + result.push(replace_with); + } + } + result +} \ No newline at end of file diff --git a/engine/Cargo.toml b/crates/services/engine/Cargo.toml similarity index 72% rename from engine/Cargo.toml rename to crates/services/engine/Cargo.toml index 0e34970..83a35ef 100644 --- a/engine/Cargo.toml +++ b/crates/services/engine/Cargo.toml @@ -1,9 +1,14 @@ [package] name = "engine" version = "0.1.0" -edition = "2021" description = "Engine Have all the common code for the Orca" -authors = ["Vasanth Kumar Kalaiselvan "] +authors.workspace = true +edition.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true [lib] @@ -26,8 +31,9 @@ tokio = "1.17.0" thiserror = "1.0.31" thirtyfour = "0.31.0" -entity = { path = "../entity" } -cerium = { path = "../cerium"} +entity = { workspace=true } +cerium = { workspace=true } + sea-orm = { version = "0.10.6", default-features = true, features = [ "macros", "debug-print", "runtime-async-std-native-tls", "sqlx-postgres"] } diff --git a/engine/src/controller/action.rs b/crates/services/engine/src/controller/action.rs similarity index 92% rename from engine/src/controller/action.rs rename to crates/services/engine/src/controller/action.rs index 811483a..b81f121 100644 --- a/engine/src/controller/action.rs +++ b/crates/services/engine/src/controller/action.rs @@ -27,8 +27,12 @@ impl<'ccl> ActionController<'ccl> { /// # Example /// /// ``` + /// use sea_orm::DatabaseConnection; + /// use engine::controller::action::ActionController; + /// use engine::server::driver::UIHelper; + /// /// let db = DatabaseConnection::new(); - /// let driver = UIHelper::new(); + /// let driver = UIHelper::default(); /// let controller = ActionController::new(&db, &driver); /// ``` pub fn new(db: &'ccl DatabaseConnection, driver: &'ccl UIHelper) -> ActionController<'ccl> { @@ -45,7 +49,14 @@ impl<'ccl> ActionController<'ccl> { /// # Example /// /// ```rust - /// let action = action::Model::new(); + /// use sea_orm::DatabaseConnection; + /// use engine::controller::action::ActionController; + /// use engine::server::driver::UIHelper; + /// use entity::test::ui::action::action::Model; + /// + /// let db = DatabaseConnection::new(); + /// let driver = UIHelper::default(); + /// let action = Model::new(); /// let controller = ActionController::new(&db, &driver); /// controller.command_open(&action).await; /// ``` @@ -53,7 +64,7 @@ impl<'ccl> ActionController<'ccl> { /// # Returns /// /// * `Result<(), EngineError>` - If the `data_value` field is `None`, it returns an `Err` with an `EngineError::Forbidden` variant. If the `data_value` field is not `None`, it opens the URL using the `drive` object and returns `Ok(())`. - async fn command_open(&self, action: &action::Model) -> EngineResult<()> { + pub async fn command_open(&self, action: &action::Model) -> EngineResult<()> { let _action = match action.to_owned().data_value { None => Err(EngineError::Forbidden), Some(url) => self.driver.open(url.as_str()).await diff --git a/engine/src/controller/case.rs b/crates/services/engine/src/controller/case.rs similarity index 100% rename from engine/src/controller/case.rs rename to crates/services/engine/src/controller/case.rs diff --git a/engine/src/controller/mod.rs b/crates/services/engine/src/controller/mod.rs similarity index 100% rename from engine/src/controller/mod.rs rename to crates/services/engine/src/controller/mod.rs diff --git a/crates/services/engine/src/controller/suite.rs b/crates/services/engine/src/controller/suite.rs new file mode 100644 index 0000000..e69de29 diff --git a/engine/src/driver/api.rs b/crates/services/engine/src/driver/api.rs similarity index 100% rename from engine/src/driver/api.rs rename to crates/services/engine/src/driver/api.rs diff --git a/engine/src/driver/mod.rs b/crates/services/engine/src/driver/mod.rs similarity index 100% rename from engine/src/driver/mod.rs rename to crates/services/engine/src/driver/mod.rs diff --git a/engine/src/driver/ui.rs b/crates/services/engine/src/driver/ui.rs similarity index 100% rename from engine/src/driver/ui.rs rename to crates/services/engine/src/driver/ui.rs diff --git a/crates/services/engine/src/error.rs b/crates/services/engine/src/error.rs new file mode 100644 index 0000000..def66c1 --- /dev/null +++ b/crates/services/engine/src/error.rs @@ -0,0 +1,23 @@ +use sea_orm::DbErr; +use serde_json::Error as SerdeJsonError; +use thirtyfour::error::WebDriverError; +use thiserror::Error; + +pub type EngineResult = Result; + + +/// EngineError - will have all the error raised from Cerium system +#[derive(Error, Debug)] +pub enum EngineError { + #[error("You are forbidden to access requested file.")] + Forbidden, + #[error("Missing Parameter: field - {0}, {1}")] + MissingParameter(String, String), + #[error("Webdriver error: {0}")] + WebdriverError(#[from] WebDriverError), + #[error("Database error: {0}")] + DatabaseError(#[from] DbErr), + #[error("Json Serialization error: {0}")] + SerializerError(#[from] SerdeJsonError) +} + diff --git a/engine/src/lib.rs b/crates/services/engine/src/lib.rs similarity index 100% rename from engine/src/lib.rs rename to crates/services/engine/src/lib.rs diff --git a/engine/src/server/driver.rs b/crates/services/engine/src/server/driver.rs similarity index 91% rename from engine/src/server/driver.rs rename to crates/services/engine/src/server/driver.rs index 9766d83..e733898 100644 --- a/engine/src/server/driver.rs +++ b/crates/services/engine/src/server/driver.rs @@ -12,9 +12,11 @@ impl UIHelper { /// # Example /// ```no_run /// use engine::error::EngineResult; + /// use thirtyfour::WebDriver; /// fn main() -> EngineResult<()> { - /// use engine::server::driver::UIHelper; - /// let driver = UIHelper::new()?; + /// use engine::server::driver::UIHelper; + /// let _driver = WebDriver::default(); + /// let driver = UIHelper::new(_driver)?; /// } /// ``` /// diff --git a/engine/src/server/mod.rs b/crates/services/engine/src/server/mod.rs similarity index 100% rename from engine/src/server/mod.rs rename to crates/services/engine/src/server/mod.rs diff --git a/engine/src/ui/mod.rs b/crates/services/engine/src/ui/mod.rs similarity index 100% rename from engine/src/ui/mod.rs rename to crates/services/engine/src/ui/mod.rs diff --git a/engine/src/ui/step.rs b/crates/services/engine/src/ui/step.rs similarity index 100% rename from engine/src/ui/step.rs rename to crates/services/engine/src/ui/step.rs diff --git a/engine/tests/controller.rs b/crates/services/engine/tests/controller.rs similarity index 100% rename from engine/tests/controller.rs rename to crates/services/engine/tests/controller.rs diff --git a/crates/web/render/Cargo.toml b/crates/web/render/Cargo.toml new file mode 100644 index 0000000..a8e9265 --- /dev/null +++ b/crates/web/render/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "render" +authors.workspace = true +edition.workspace = true +version.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true +exclude.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dioxus = "0.4.3" +dioxus-web = "0.4.3" diff --git a/crates/web/render/Dioxus.toml b/crates/web/render/Dioxus.toml new file mode 100644 index 0000000..51d506a --- /dev/null +++ b/crates/web/render/Dioxus.toml @@ -0,0 +1,11 @@ +[application] +name = "render" +# Currently supported platforms: web, desktop +default_platform = "web" + +[web.app] +title = "Hello" + +[web.watcher] + +[web.resource.dev] \ No newline at end of file diff --git a/crates/web/render/src/main.rs b/crates/web/render/src/main.rs new file mode 100644 index 0000000..0154df4 --- /dev/null +++ b/crates/web/render/src/main.rs @@ -0,0 +1,18 @@ +#![allow(non_snake_case)] +// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types +use dioxus::prelude::*; + +fn main() { + // launch the web app + dioxus_web::launch(App); +} + +// create a component that renders a div with the text "Hello, world!" +fn App(cx: Scope) -> Element { + cx.render(rsx! { + div { + "Hello, world!" + } + }) +} + diff --git a/crates/web/tail-rs/Cargo.toml b/crates/web/tail-rs/Cargo.toml new file mode 100644 index 0000000..38b0f1f --- /dev/null +++ b/crates/web/tail-rs/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "tail-rs" +authors.workspace = true +edition.workspace = true +version.workspace = true +license.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true +exclude.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/crates/web/tail-rs/src/button/button.rs b/crates/web/tail-rs/src/button/button.rs new file mode 100644 index 0000000..5002cd0 --- /dev/null +++ b/crates/web/tail-rs/src/button/button.rs @@ -0,0 +1,19 @@ + + +// Remember: Owned props must implement `PartialEq`! +#[derive(PartialEq, Props)] +struct LikesProps { + score: i32, +} + +pub fn button(cx: Scope) -> Element { + cx.render(rsx! { + div { + "This post has ", + b { "{cx.props.score}" }, + " likes" + } + }) +} + + diff --git a/crates/web/tail-rs/src/button/mod.rs b/crates/web/tail-rs/src/button/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/web/tail-rs/src/lib.rs b/crates/web/tail-rs/src/lib.rs new file mode 100644 index 0000000..7d12d9a --- /dev/null +++ b/crates/web/tail-rs/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/docs/setup/config.md b/docs/setup/config.md new file mode 100644 index 0000000..e69de29 diff --git a/engine/src/error.rs b/engine/src/error.rs deleted file mode 100644 index 92f5d94..0000000 --- a/engine/src/error.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::fmt; -use std::fmt::Formatter; - -use thiserror::Error; - -pub type EngineResult = Result; - -#[derive(Clone)] -pub struct ErrorResponse { - code: String, - error: String, - message: String, -} - -impl ErrorResponse { - pub fn new(error: &str, message: String) -> Self { - Self { code: "".to_string(), error: error.to_string(), message } - } -} - -/// EngineError - will have all the error raised from Cerium system -#[derive(Error, Debug)] -pub enum EngineError { - #[error("You are forbidden to access requested file.")] - Forbidden, - #[error("Missing Parameter: field - {0}, {1}")] - MissingParameter(String, String), - #[error("Webdriver error: {0}")] - WebdriverError(#[from] thirtyfour::error::WebDriverError), - #[error("Database error: {0}")] - DatabaseError(#[from] sea_orm::DbErr), - -} - -impl EngineError { - pub fn decode(&self) -> ErrorResponse { - match self { - Self::Forbidden => ErrorResponse::new("Unknown", self.to_string()), - Self::MissingParameter(ref e, ref b) => ErrorResponse::new("MissingParameter", self.to_string()), - Self::WebdriverError(ref e) => ErrorResponse::new("WebdriverError", self.to_string()), - Self::DatabaseError(ref e) => ErrorResponse::new("DatabaseError", self.to_string()), - _ => ErrorResponse::new("Unknown", self.to_string()), - } - } - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!( - "An error occurred: \"{}\"", - self.to_string() - )) - } -} \ No newline at end of file diff --git a/entity/Cargo.toml b/entity/Cargo.toml deleted file mode 100644 index 8ac3fdd..0000000 --- a/entity/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "entity" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -sea-orm = { version = "0.10.6", default-features = true, features = [ "macros", "debug-print", "runtime-async-std-native-tls", "sqlx-postgres"] } - -serde = { version = "1.0.147", features = ["derive"] } -serde_json = "1.0.87" \ No newline at end of file diff --git a/entity/src/backup/activity.rs b/entity/src/backup/activity.rs deleted file mode 100644 index fe73313..0000000 --- a/entity/src/backup/activity.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "activity_log")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub event: String, - pub created_at: String, - pub created_by: String, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/audit_log.rs b/entity/src/backup/audit_log.rs deleted file mode 100644 index 5c6613d..0000000 --- a/entity/src/backup/audit_log.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use sea_orm::EntityTrait; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "audit_log")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: i64, - pub event: String, - pub action: String, - pub payload: String, - pub acted_by: i64, - pub created_at: DateTimeUtc, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::user::Entity")] - User, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/backup.rs b/entity/src/backup/backup.rs deleted file mode 100644 index 07e1434..0000000 --- a/entity/src/backup/backup.rs +++ /dev/null @@ -1,151 +0,0 @@ -use serde::{Deserialize, Serialize}; -use serde::{Deserialize, Serialize}; - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Case { - pub id: String, - pub name: String, - pub actors: Vec, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct CaseBlock { - pub id: String, - pub execution_order: i64, - pub kind: String, - pub type_field: String, - pub reference: String, - // pub filter: Option, - pub actors: Vec, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Filter { - pub scenario: String, - pub case: String, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Actor { - pub execution_order: i64, - pub action_kind: String, - pub action_reference: String, - pub data_binding: Vec, - pub description: Option, -} - -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct DataBinding { - pub key: String, - pub value: String, -} - - - -//!------------------------------------------------- -//!------------------------------------------------- -//!------------------------------------------------- -//!------------------------------------------------- - - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all="camelCase")] -pub enum ATargetKind{ - Css, - Id, - Xpath, -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all="camelCase")] -pub enum ADataKind{ - Runtime, - Static, -} - - -#[derive(Serialize, Deserialize, Debug)] -#[serde(rename_all="camelCase")] -pub enum ActionKind{ - Click, - Enter, - DoubleClick, -} - - -#[derive(Serialize, Deserialize, Debug)] -pub struct ActionTarget { - #[serde(rename = "type")] - pub kind: ATargetKind, - pub value: String, -} - -/// ActionData - object to Have information of the datatype -#[derive(Serialize, Deserialize, Debug)] -pub struct ActionData { - #[serde(rename = "type")] - pub kind: ADataKind, - pub value: String -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct Action { - #[serde(rename = "type")] - pub kind: ActionKind, - pub description: String, - pub target: ActionTarget, - pub data: Option -} - - -#[derive(Serialize, Deserialize, Debug)] -pub struct ActionGroup { - pub name: String, - pub description: Option, - pub actions: Vec -} - - -impl ActionGroup { - -} - -/// Evaluate action type -/// 1. if enter -/// 1.1 find css using ActionTarget -/// 1.2 fill up target using ActionData -// pub fn evaluate_action_type() { -// let action = Action { -// description: "test descritpion".parse().unwrap(), -// kind: "enter".parse().unwrap(), -// target: ActionTarget { -// value: "css".parse().unwrap(), -// kind: "#email".parse().unwrap(), -// }, -// data: ActionData { -// kind: "harcode".to_string(), -// value: "manikandantest".to_string() -// }, -// }; -// -// let action_type = action.kind; -// -// } - - - -// pub mod driver; -// mod ui; -// -// extern crate entity; - - - -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - let result = 2 + 2; - assert_eq!(result, 4); - } -} diff --git a/entity/src/backup/profile.rs b/entity/src/backup/profile.rs deleted file mode 100644 index eb8de36..0000000 --- a/entity/src/backup/profile.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -use crate::profile_data; -use crate::profile_data::EnvironmentData; - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct Profile { - pub name: String, - pub is_default: bool, -} - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "profile")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub name: String, - pub is_default: bool, - #[sea_orm(ignore)] - pub data: Vec, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::profile_data::Entity")] - ProfileData, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::ProfileData.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/profile_data.rs b/entity/src/backup/profile_data.rs deleted file mode 100644 index 1bec62d..0000000 --- a/entity/src/backup/profile_data.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct ProfileData { - pub name: String, - pub value: String, -} - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, DeriveIntoActiveModel)] -pub struct EnvironmentData { - pub name: String, - pub value: String, -} - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "profile_data")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub name: String, - pub value: String, - pub profile_id: i32, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::profile::Entity", - from = "Column::ProfileId", - to = "super::profile::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - Profile, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Profile.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/role.rs b/entity/src/backup/role.rs deleted file mode 100644 index a6c6526..0000000 --- a/entity/src/backup/role.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use sea_orm::EntityTrait; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "role")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: i32, - pub name: String, - pub description: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::user_role::Entity")] - UserRole, - #[sea_orm(has_many = "super::role_scope::Entity")] - RoleScope, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserRole.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::RoleScope.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/role_scope.rs b/entity/src/backup/role_scope.rs deleted file mode 100644 index 26ee3c7..0000000 --- a/entity/src/backup/role_scope.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use sea_orm::EntityTrait; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "role_scope")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: i32, - pub name: String, - pub scope: String, - pub role_id: i64, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::role::Entity", - from = "Column::RoleId", - to = "super::role::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - Role, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Role.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/test_action.rs b/entity/src/backup/test_action.rs deleted file mode 100644 index 0e4d9ae..0000000 --- a/entity/src/backup/test_action.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, DeriveIntoActiveModel)] -pub struct TestAction { - pub command: String, - pub target: String, - pub selector: Option, - pub value: Option, - pub output: Option, - pub desc: Option, - pub execution_order: i32, -} - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "test_action")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub command: String, - pub target: String, - #[sea_orm(nullable)] - pub selector: Option, - #[sea_orm(nullable)] - pub value: Option, - #[sea_orm(nullable)] - pub output: Option, - #[sea_orm(nullable)] - pub desc: Option, - pub execution_order: i32, - pub test_case_id: i32, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::test_case::Entity", - from = "Column::TestCaseId", - to = "super::test_case::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - TestCase, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::TestCase.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/test_case.rs b/entity/src/backup/test_case.rs deleted file mode 100644 index 15e5e90..0000000 --- a/entity/src/backup/test_case.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct TestCase { - pub name: String, -} - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "test_case")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub name: String, - pub is_deleted: bool, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::test_step::Entity")] - TestStep, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::TestStep.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/test_step.rs b/entity/src/backup/test_step.rs deleted file mode 100644 index 29dce4f..0000000 --- a/entity/src/backup/test_step.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct TestStep { - pub command: String, - pub target: String, - pub value: Option, - pub output: Option, - pub desc: Option, - pub execution_order: i32, -} - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "test_step")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub command: String, - pub target: String, - #[sea_orm(nullable)] - pub value: Option, - #[sea_orm(nullable)] - pub output: Option, - #[sea_orm(nullable)] - pub desc: Option, - pub execution_order: i32, - pub test_case_id: i32, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::test_case::Entity", - from = "Column::TestCaseId", - to = "super::test_case::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - TestCase, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::TestCase.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/user.rs b/entity/src/backup/user.rs deleted file mode 100644 index ab4210e..0000000 --- a/entity/src/backup/user.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use sea_orm::EntityTrait; -use sea_orm::Set; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct User { - pub id: Option, - pub first_name: String, - pub last_name: Option, - pub name: String, - pub email: String, - pub is_active: Option, -} - -impl User { - pub fn to_active_model(&self) -> ActiveModel { - let user_response = ActiveModel { - first_name: Set(self.first_name.to_owned()), - last_name: Set(self.last_name.to_owned()), - email: Set(self.email.to_owned()), - name: Set(self.name.to_owned()), - is_active: Set(self.is_active.to_owned().or(Some(false)).unwrap()), - ..Default::default() - }; - return user_response; - } - pub fn from_active_model(mut am: ActiveModel) -> Self { - Self { - id: Some(am.id.take().unwrap()), - first_name: am.first_name.take().unwrap(), - last_name: None, - name: am.name.take().unwrap(), - email: am.email.take().unwrap(), - is_active: None, - } - } -} - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "user")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub first_name: String, - pub last_name: Option, - pub name: String, - pub email: String, - pub password: Option, - pub is_active: bool, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::user_group::Entity")] - UserGroup, - #[sea_orm(has_many = "super::user_session::Entity")] - UserSession, - #[sea_orm(has_many = "super::user_role::Entity")] - UserRole, - #[sea_orm(has_many = "super::audit_log::Entity")] - AuditLog, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserGroup.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserSession.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::AuditLog.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserRole.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/user_group.rs b/entity/src/backup/user_group.rs deleted file mode 100644 index 1d51cfd..0000000 --- a/entity/src/backup/user_group.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "user_group")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub user_id: i64, - #[sea_orm(primary_key, auto_increment = false)] - pub group_id: i64, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::UserId", - to = "super::user::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - User, - #[sea_orm( - belongs_to = "super::group::Entity", - from = "Column::GroupId", - to = "super::group::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - Group, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Group.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/user_role.rs b/entity/src/backup/user_role.rs deleted file mode 100644 index 00fec10..0000000 --- a/entity/src/backup/user_role.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "user_role")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub user_id: i64, - #[sea_orm(primary_key, auto_increment = false)] - pub role_id: i64, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::UserId", - to = "super::user::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - User, - #[sea_orm( - belongs_to = "super::role::Entity", - from = "Column::RoleId", - to = "super::role::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - Role, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Role.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/backup/user_session.rs b/entity/src/backup/user_session.rs deleted file mode 100644 index ba5d30c..0000000 --- a/entity/src/backup/user_session.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - -use sea_orm::entity::prelude::*; -use sea_orm::EntityTrait; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct UserSession { - pub id: i32, - pub user_id: i32, - pub session_id: String, - pub session_type: String, - pub user_agent: String, - pub email: String, - pub expires_by: DateTime, -} - -impl UserSession { - pub fn from_active_model(mut am: ActiveModel) -> Self { - Self { - id: am.id.take().unwrap(), - user_id: am.user_id.take().unwrap(), - session_id: am.session_id.take().unwrap(), - session_type: am.session_type.take().unwrap(), - user_agent: am.user_agent.take().unwrap(), - email: am.email.take().unwrap(), - expires_by: am.expires_by.take().unwrap(), - } - } -} - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] -#[sea_orm(table_name = "user_session")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = true)] - pub id: i32, - pub user_id: i32, - pub session_id: String, - pub session_type: String, - pub user_agent: String, - pub email: String, - pub expires_by: DateTime, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::user::Entity")] - User, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/test/mod.rs b/entity/src/test/mod.rs deleted file mode 100644 index b71b381..0000000 --- a/entity/src/test/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod ui; \ No newline at end of file diff --git a/migration/Cargo.toml b/migration/Cargo.toml deleted file mode 100644 index 2ea1bd8..0000000 --- a/migration/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "migration" -version = "0.1.0" -edition = "2021" -publish = false - -[lib] -name = "migration" -path = "src/lib.rs" - -[dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } -entity = { path="../entity" } - -[dependencies.sea-orm-migration] -version = "0.10.6" -features = [ - # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI. - # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime. - # e.g. - # "runtime-tokio-rustls", # `ASYNC_RUNTIME` feature - "sqlx-postgres", -] diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..268bfc8 --- /dev/null +++ b/start.sh @@ -0,0 +1,2 @@ +docker compose up -d +cargo run -p api From ebdb6d457bc2d3e8fef324826719f933382f67fc Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Thu, 28 Dec 2023 20:02:39 +0530 Subject: [PATCH 3/8] removed unwanted Ui code --- crates/web/render/Cargo.toml | 17 ----------------- crates/web/render/Dioxus.toml | 11 ----------- crates/web/render/src/main.rs | 18 ------------------ crates/web/tail-rs/Cargo.toml | 15 --------------- crates/web/tail-rs/src/button/button.rs | 19 ------------------- crates/web/tail-rs/src/button/mod.rs | 0 crates/web/tail-rs/src/lib.rs | 14 -------------- 7 files changed, 94 deletions(-) delete mode 100644 crates/web/render/Cargo.toml delete mode 100644 crates/web/render/Dioxus.toml delete mode 100644 crates/web/render/src/main.rs delete mode 100644 crates/web/tail-rs/Cargo.toml delete mode 100644 crates/web/tail-rs/src/button/button.rs delete mode 100644 crates/web/tail-rs/src/button/mod.rs delete mode 100644 crates/web/tail-rs/src/lib.rs diff --git a/crates/web/render/Cargo.toml b/crates/web/render/Cargo.toml deleted file mode 100644 index a8e9265..0000000 --- a/crates/web/render/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "render" -authors.workspace = true -edition.workspace = true -version.workspace = true -license.workspace = true -documentation.workspace = true -homepage.workspace = true -repository.workspace = true -rust-version.workspace = true -exclude.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -dioxus = "0.4.3" -dioxus-web = "0.4.3" diff --git a/crates/web/render/Dioxus.toml b/crates/web/render/Dioxus.toml deleted file mode 100644 index 51d506a..0000000 --- a/crates/web/render/Dioxus.toml +++ /dev/null @@ -1,11 +0,0 @@ -[application] -name = "render" -# Currently supported platforms: web, desktop -default_platform = "web" - -[web.app] -title = "Hello" - -[web.watcher] - -[web.resource.dev] \ No newline at end of file diff --git a/crates/web/render/src/main.rs b/crates/web/render/src/main.rs deleted file mode 100644 index 0154df4..0000000 --- a/crates/web/render/src/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![allow(non_snake_case)] -// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types -use dioxus::prelude::*; - -fn main() { - // launch the web app - dioxus_web::launch(App); -} - -// create a component that renders a div with the text "Hello, world!" -fn App(cx: Scope) -> Element { - cx.render(rsx! { - div { - "Hello, world!" - } - }) -} - diff --git a/crates/web/tail-rs/Cargo.toml b/crates/web/tail-rs/Cargo.toml deleted file mode 100644 index 38b0f1f..0000000 --- a/crates/web/tail-rs/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "tail-rs" -authors.workspace = true -edition.workspace = true -version.workspace = true -license.workspace = true -documentation.workspace = true -homepage.workspace = true -repository.workspace = true -rust-version.workspace = true -exclude.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/crates/web/tail-rs/src/button/button.rs b/crates/web/tail-rs/src/button/button.rs deleted file mode 100644 index 5002cd0..0000000 --- a/crates/web/tail-rs/src/button/button.rs +++ /dev/null @@ -1,19 +0,0 @@ - - -// Remember: Owned props must implement `PartialEq`! -#[derive(PartialEq, Props)] -struct LikesProps { - score: i32, -} - -pub fn button(cx: Scope) -> Element { - cx.render(rsx! { - div { - "This post has ", - b { "{cx.props.score}" }, - " likes" - } - }) -} - - diff --git a/crates/web/tail-rs/src/button/mod.rs b/crates/web/tail-rs/src/button/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/crates/web/tail-rs/src/lib.rs b/crates/web/tail-rs/src/lib.rs deleted file mode 100644 index 7d12d9a..0000000 --- a/crates/web/tail-rs/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} From b18f60c5cc30f3d267c1271bfffc9ffc342111e9 Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Thu, 28 Dec 2023 20:18:36 +0530 Subject: [PATCH 4/8] Fixed deleted lib --- Cargo.toml | 1 - start.sh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b4e9de3..87d49fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ members=[ "crates/libs/migration", "crates/services/engine", "crates/services/api", - "crates/web/render" ] [workspace.package] diff --git a/start.sh b/start.sh index 268bfc8..90710c7 100644 --- a/start.sh +++ b/start.sh @@ -1,2 +1,3 @@ +cargo install docker compose up -d cargo run -p api From 2dc1e1d46ffab5718f7b35bb7c12cac253bc7f4e Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Sat, 30 Dec 2023 19:14:55 +0530 Subject: [PATCH 5/8] Staging after first mvp ingration in application --- Cargo.toml | 16 ++-- crates/libs/cerium/Cargo.toml | 25 +++---- crates/libs/cerium/src/client/driver/mod.rs | 1 + crates/libs/cerium/src/client/driver/web.rs | 61 +++++++++++++++ crates/libs/cerium/src/client/mod.rs | 6 +- crates/libs/cerium/src/error/mod.rs | 34 +++------ crates/libs/cerium/src/server/utils.rs | 30 -------- crates/libs/cerium/src/utils/mod.rs | 27 ------- .../libs/entity/src/test/ui/action/action.rs | 2 - crates/libs/macroni/Cargo.toml | 20 ----- crates/libs/macroni/src/lib.rs | 74 ------------------- crates/libs/migration/src/migration002.rs | 2 +- crates/services/api/Cargo.toml | 3 +- crates/services/api/src/route/app/action.rs | 4 +- crates/services/api/src/service/app/action.rs | 22 +++--- crates/services/api/src/service/app/case.rs | 14 ++-- crates/services/engine/Cargo.toml | 21 +++--- .../services/engine/src/controller/action.rs | 68 ++++++++++------- crates/services/engine/src/controller/case.rs | 37 +++++----- crates/services/engine/src/driver/api.rs | 5 -- crates/services/engine/src/driver/mod.rs | 6 -- crates/services/engine/src/driver/ui.rs | 48 ------------ crates/services/engine/src/error.rs | 5 +- crates/services/engine/src/lib.rs | 1 - crates/services/engine/src/server/driver.rs | 58 --------------- crates/services/engine/src/server/mod.rs | 1 - crates/services/engine/tests/controller.rs | 18 +++-- docker-compose.yml | 1 + 28 files changed, 203 insertions(+), 407 deletions(-) create mode 100644 crates/libs/cerium/src/client/driver/mod.rs create mode 100644 crates/libs/cerium/src/client/driver/web.rs delete mode 100644 crates/libs/macroni/Cargo.toml delete mode 100644 crates/libs/macroni/src/lib.rs delete mode 100644 crates/services/engine/src/driver/api.rs delete mode 100644 crates/services/engine/src/driver/mod.rs delete mode 100644 crates/services/engine/src/driver/ui.rs delete mode 100644 crates/services/engine/src/server/driver.rs diff --git a/Cargo.toml b/Cargo.toml index 87d49fc..5005d90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ repository = "https://github.com/orcaci/orca" rust-version = "1.74.1" exclude = [".github/**"] - [workspace.dependencies] cerium = { path = "crates/libs/cerium", default-features = true } entity = { path = "crates/libs/entity", default-features = true } @@ -37,6 +36,12 @@ chrono = { version = "0.4.31"} tracing = "0.1.37" tracing-subscriber = "0.3.16" uuid = { version = "1.6.1", features = ["serde", "v4"] } +config = "0.13.3" +dotenv = "0.15.0" +futures = "0.3.29" +futures-util = "0.3.29" +rust_decimal = "1.14.3" +cross-test = "0.1.6" sea-query = "0.30.5" sea-orm = { version = "0.12.3", features = [ @@ -46,20 +51,15 @@ sea-orm = { version = "0.12.3", features = [ "sqlx-postgres", ] } sea-orm-migration = {version = "0.12.3", features = ["sqlx-postgres"]} - axum = "0.7.1" axum-extra = "0.8.0" tokio = { version = "1.34.0", features = ["full"] } tower = "0.4.13" tower-http = { version = "0.5.0", default-features = true, features = ["uuid", "cors", "trace", "compression-br", "catch-panic", "request-id"] } -config = "0.13.3" -dotenv = "0.15.0" -futures = "0.3.29" -futures-util = "0.3.29" -rust_decimal = "1.14.3" -cross-test = "0.1.6" +thirtyfour = "0.31.0" + [patch.crates-io] sea-orm = { git="https://github.com/itsparser/sea-orm", branch = "master" } \ No newline at end of file diff --git a/crates/libs/cerium/Cargo.toml b/crates/libs/cerium/Cargo.toml index 48f89c7..9809d63 100644 --- a/crates/libs/cerium/Cargo.toml +++ b/crates/libs/cerium/Cargo.toml @@ -21,10 +21,12 @@ crate-type = ["lib"] [features] default = [] -actix = ["dep:actix-web"] -axum = [] +#actix = ["dep:actix-web"] +#axum = ["dep:axum"] [dependencies] +entity.workspace=true + tracing.workspace=true tracing-subscriber.workspace=true tokio.workspace=true @@ -35,22 +37,15 @@ tower-http.workspace=true config.workspace=true sea-orm.workspace=true sea-query.workspace=true - -bytes = "1" -http-body-util = "0.1.0" +thirtyfour.workspace=true +chrono.workspace=true +jsonwebtoken.workspace=true +thiserror.workspace=true +serde.workspace=true +serde_json.workspace=true lazy_static = "1.4.0" async_once = "0.2.6" -log = "0.4.16" -env_logger = "0.10.0" -chrono = "0.4.23" -jsonwebtoken = "8" -thiserror = "1.0.31" -serde = { version = "1.0.147", features = ["derive"] } -serde_json = "1.0.87" -http = "0.2.8" rand = { version = "0.8.5", default-features = false, features = ["std"] } -actix-web = { version = "4.2.1", optional = true } - diff --git a/crates/libs/cerium/src/client/driver/mod.rs b/crates/libs/cerium/src/client/driver/mod.rs new file mode 100644 index 0000000..d7cf837 --- /dev/null +++ b/crates/libs/cerium/src/client/driver/mod.rs @@ -0,0 +1 @@ +pub mod web; \ No newline at end of file diff --git a/crates/libs/cerium/src/client/driver/web.rs b/crates/libs/cerium/src/client/driver/web.rs new file mode 100644 index 0000000..9efb008 --- /dev/null +++ b/crates/libs/cerium/src/client/driver/web.rs @@ -0,0 +1,61 @@ +use thirtyfour::{WebDriver as TFWebDriver}; + + +use thirtyfour::{By, DesiredCapabilities, WebElement}; +use crate::error::CeriumResult; + +#[derive(Clone)] +pub struct WebDriver { + pub driver: TFWebDriver, +} + +impl WebDriver { + /// new - will create new Helper object with the EngineResult Wrap around it + /// + /// # Example + /// ```no_run + /// use thirtyfour::{WebDriver as WD}; + /// use cerium::error::CeriumResult; + /// use cerium::client::driver::web::WebDriver; + /// + /// fn main() -> CeriumResult<()> { + /// let _driver = WD::default(); + /// let driver = WebDriver::new(_driver)?; + /// } + /// ``` + /// + /// **NOTE:** If the webdriver appears to hang or give no response, please check that the + /// capabilities object is of the correct type for that webdriver. + pub fn new(driver: TFWebDriver) -> CeriumResult { + let helper = WebDriver{driver}; + Ok(helper) + } + + pub async fn default() -> CeriumResult { + let caps = DesiredCapabilities::firefox(); + let driver = TFWebDriver::new("http://localhost:4444/wd/hub/session", caps).await?; + Self::new(driver) + } + + + pub async fn open(&self, url: &str) -> CeriumResult<()> { + Ok(self.driver.goto(url).await?) + } + + pub async fn create_window(&self, name: &str) -> CeriumResult<()> { + let win_handler = self.driver.new_window().await?; + self.driver.switch_to_window(win_handler).await?; + self.driver.set_window_name(name).await?; + Ok(()) + } + + pub async fn find(&self, by: impl Into) -> CeriumResult { + Ok(self.driver.find(by).await?) + } + + + /// take_screenshot - will take screenshot and send png back to the requester + pub async fn take_screenshot(&self) -> CeriumResult> { + Ok(self.driver.screenshot_as_png().await?) + } +} diff --git a/crates/libs/cerium/src/client/mod.rs b/crates/libs/cerium/src/client/mod.rs index 82ac7ea..81543cb 100644 --- a/crates/libs/cerium/src/client/mod.rs +++ b/crates/libs/cerium/src/client/mod.rs @@ -4,6 +4,7 @@ use sea_orm::{ConnectOptions, Database, DatabaseConnection}; pub mod cache; pub mod db; +pub mod driver; #[derive(Debug, Clone)] @@ -35,9 +36,8 @@ impl Client { .acquire_timeout(Duration::from_secs(8)) .idle_timeout(Duration::from_secs(8)) .max_lifetime(Duration::from_secs(8)) - .sqlx_logging(true) - .sqlx_logging_level(log::LevelFilter::Info); + .sqlx_logging(true); Database::connect(opt).await.expect("Error unable to connect DB") // Database::connect(uri.unwrap()).await.expect("Error unable to connect DB") } -} \ No newline at end of file +} diff --git a/crates/libs/cerium/src/error/mod.rs b/crates/libs/cerium/src/error/mod.rs index 3b4465f..8088270 100644 --- a/crates/libs/cerium/src/error/mod.rs +++ b/crates/libs/cerium/src/error/mod.rs @@ -3,37 +3,25 @@ use axum::Json; use axum::response::{IntoResponse, Response}; use sea_orm::DbErr; use serde_json::{Error as SerdeJsonError, json}; +use thirtyfour::error::WebDriverError; +use thiserror::Error; -pub use cerium::{CeriumError as OtherCeriumError, CeriumResult, ErrorResponse}; +// pub use cerium::{CeriumError as OtherCeriumError, CeriumResult, ErrorResponse}; +pub type CeriumResult = Result; pub mod web; pub mod cerium; -// pub type OrcaResult = InternalResult; - -pub type InternalResult = Result; - /// Our app's top level error type. +#[derive(Error, Debug)] pub enum CeriumError { /// Something went wrong when calling the user repo. - DataBaseError(DbErr), - SerializerError(SerdeJsonError) -} - -/// This makes it possible to use `?` to automatically convert a `DbErr` -/// into an `CeriumError`. -impl From for CeriumError { - fn from(inner: DbErr) -> Self { - CeriumError::DataBaseError(inner) - } -} - -/// This makes it possible to use `?` to automatically convert a `DbErr` -/// into an `CeriumError`. -impl From for CeriumError { - fn from(inner: SerdeJsonError) -> Self { - CeriumError::SerializerError(inner) - } + #[error("Got A Database Error: {0}")] + DataBaseError(#[from] DbErr), + #[error("Error While Serializer: {0}")] + SerializerError(#[from] SerdeJsonError), + #[error("Webdriver error: {0}")] + WebdriverError(#[from] WebDriverError), } impl IntoResponse for CeriumError { diff --git a/crates/libs/cerium/src/server/utils.rs b/crates/libs/cerium/src/server/utils.rs index b4e8d01..e69de29 100644 --- a/crates/libs/cerium/src/server/utils.rs +++ b/crates/libs/cerium/src/server/utils.rs @@ -1,30 +0,0 @@ -use std::any::Any; - -use bytes::Bytes; -use http::{header::{self}, Response, StatusCode}; -use http_body_util::Full; - - -pub fn handle_panic(err: Box) -> Response> { - let details = if let Some(s) = err.downcast_ref::() { - s.clone() - } else if let Some(s) = err.downcast_ref::<&str>() { - s.to_string() - } else { - "Unknown panic message".to_string() - }; - - let body = serde_json::json!({ - "error": { - "kind": "panic", - "details": details, - } - }); - let body = serde_json::to_string(&body).unwrap(); - - Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .header(header::CONTENT_TYPE, "application/json") - .body(Full::from(body)) - .unwrap() -} \ No newline at end of file diff --git a/crates/libs/cerium/src/utils/mod.rs b/crates/libs/cerium/src/utils/mod.rs index 6e6dd4a..81b2cee 100644 --- a/crates/libs/cerium/src/utils/mod.rs +++ b/crates/libs/cerium/src/utils/mod.rs @@ -1,31 +1,4 @@ -use std::io::Write; -use chrono::Local; -use env_logger::Builder; -use env_logger::fmt::Color; -use log::LevelFilter; pub mod uuid; - -/// init_logger - function will initialize log Handler for the application -pub fn init_logger() { - Builder::new() - .format(|buf, record| { - let mut timestamp_style = buf.style(); - timestamp_style.set_color(Color::Magenta); - - let mut level_style = buf.style(); - level_style.set_color(Color::Red); - writeln!(buf, - "[{} {}] {} >>> {}", - timestamp_style.value(Local::now().format("%d-%m-%Y %H:%M:%S")), - level_style.value(record.level()), - record.module_path_static().unwrap_or(""), - record.args() - ) - }) - .filter_level(LevelFilter::Debug) - .init(); - // env_logger::init(); -} \ No newline at end of file diff --git a/crates/libs/entity/src/test/ui/action/action.rs b/crates/libs/entity/src/test/ui/action/action.rs index 885c8a8..f0c050d 100644 --- a/crates/libs/entity/src/test/ui/action/action.rs +++ b/crates/libs/entity/src/test/ui/action/action.rs @@ -28,7 +28,6 @@ pub enum ActionKind { #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] #[sea_orm(table_name = "action")] pub struct Model { - #[serde(skip_deserializing)] #[sea_orm(primary_key)] pub id: Uuid, pub execution_order: i32, @@ -40,7 +39,6 @@ pub struct Model { pub target_kind: Option, pub target_value: Option, - #[serde(skip_deserializing)] pub action_group_id: Uuid, #[sea_orm(ignore)] diff --git a/crates/libs/macroni/Cargo.toml b/crates/libs/macroni/Cargo.toml deleted file mode 100644 index d951d33..0000000 --- a/crates/libs/macroni/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "macroni" -authors.workspace = true -edition.workspace = true -version.workspace = true -license.workspace = true -documentation.workspace = true -homepage.workspace = true -repository.workspace = true -rust-version.workspace = true -exclude.workspace = true - -[lib] -proc-macro = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -syn = "2.0.37" -quote = "1.0" \ No newline at end of file diff --git a/crates/libs/macroni/src/lib.rs b/crates/libs/macroni/src/lib.rs deleted file mode 100644 index 90670ae..0000000 --- a/crates/libs/macroni/src/lib.rs +++ /dev/null @@ -1,74 +0,0 @@ - - -use proc_macro::TokenStream; -use quote::quote; -use syn::{parse_macro_input, DeriveInput}; - -#[proc_macro_derive(CustomModel)] -pub fn custom_model(input: TokenStream) -> TokenStream { - // Parse the input into a Rust AST - let input = parse_macro_input!(input as DeriveInput); - - // Generate new code based on the input AST - let output = quote! { - // Add a new field to the struct - struct #input { - pub my_field: u32, - #input - } - - // Add a new trait to the struct - // impl #input { - // fn my_trait(&self) { - // // Trait implementation code goes here - // } - // } - }; - - // Return the generated code as a TokenStream - output.into() -} - -#[proc_macro_derive(HelloMacro)] -pub fn hello_macro_derive(input: TokenStream) -> TokenStream { - // Construct a representation of Rust code as a syntax tree - // that we can manipulate - let ast = syn::parse(input).unwrap(); - - // Build the trait implementation - impl_hello_macro(&ast) -} - -fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { - let name = &ast.ident; - let gen = quote! { - impl HelloMacro for #name { - fn hello_macro() { - println!("Hello, Macro! My name is {}!", stringify!(#name)); - } - } - }; - gen.into() -} - -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[derive(HelloMacro)] - struct Hellow { - pub message: string - } - - #[test] - fn it_works() { - let a = Hellow{message:"hellow"}; - a.hello_macro(); - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/crates/libs/migration/src/migration002.rs b/crates/libs/migration/src/migration002.rs index 0a1f45a..258ed79 100644 --- a/crates/libs/migration/src/migration002.rs +++ b/crates/libs/migration/src/migration002.rs @@ -97,7 +97,7 @@ impl MigrationTrait for Migration { data_kind: Set(Some(ActionDataKind::Static)), data_value: Set(Some("Ana de Armas".to_string())), target_kind: Set(Some(ActionTargetKind::Xpath)), - target_value: Set(Some("//h1[@id='firstHeading']/span".to_string())), + target_value: Set(Some("//*[@id='search-form']/fieldset/button".to_string())), execution_order: Set(1), action_group_id: Set(assert_g_m.clone().id), ..Default::default() diff --git a/crates/services/api/Cargo.toml b/crates/services/api/Cargo.toml index 5fa964f..1bdc8b7 100644 --- a/crates/services/api/Cargo.toml +++ b/crates/services/api/Cargo.toml @@ -29,12 +29,13 @@ chrono.workspace=true sea-orm.workspace=true sea-query.workspace=true sea-orm-migration.workspace=true +axum.workspace=true cerium.workspace=true +engine.workspace=true migration.workspace=true entity.workspace=true thiserror.workspace=true tokio = { version = "1.0", features = ["full"] } -axum = "0.7.2" diff --git a/crates/services/api/src/route/app/action.rs b/crates/services/api/src/route/app/action.rs index 3f3129c..3e0de2b 100644 --- a/crates/services/api/src/route/app/action.rs +++ b/crates/services/api/src/route/app/action.rs @@ -39,8 +39,8 @@ async fn create_action(Extension(session): Extension, Path((_app_id async fn batch_update_action(Extension(session): Extension, Path((_app_id, group_id)): Path<(Uuid, Uuid)>, Json(body): Json>) -> InternalResult { - ActionService::new(session).batch_update_action(group_id, body).await?; - Ok(Json(json!({"status": "success"}))) + let response = ActionService::new(session).batch_update_action(group_id, body).await?; + Ok(Json(response)) } /// update_action - this will create new Application in Orca diff --git a/crates/services/api/src/service/app/action.rs b/crates/services/api/src/service/app/action.rs index 6cc7608..a5b3843 100644 --- a/crates/services/api/src/service/app/action.rs +++ b/crates/services/api/src/service/app/action.rs @@ -1,11 +1,11 @@ -use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, TryIntoModel}; +use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, NotSet, QueryFilter, QueryOrder, TryIntoModel}; use sea_orm::ActiveValue::Set; use sea_orm::prelude::Uuid; use sea_query::Expr; use tracing::info; use entity::test::ui::action::action; -use entity::test::ui::action::action::{ActiveModel, Model}; +use entity::test::ui::action::action::{ActiveModel, Entity, Model}; use crate::error::{InternalResult, OrcaRepoError}; use crate::server::session::OrcaSession; @@ -72,15 +72,15 @@ impl ActionService { } /// batch_update_action - This will update batch Action Group in Application in Orca - pub async fn batch_update_action(&self, group_id: Uuid, mut actions: Vec) -> InternalResult<()> { - let actions : Vec = actions.iter_mut().map(|item| { - item.id = Uuid::new_v4(); - item.action_group_id = group_id; - let _item = item.clone().into_active_model(); - return _item; - }).collect(); - action::Entity::insert_many(actions).exec(self.trx()).await?; - Ok(()) + pub async fn batch_update_action(&self, group_id: Uuid, mut actions: Vec) -> InternalResult> { + let mut result: Vec = vec![]; + for item in actions { + let mut _item = item.into_active_model().reset_all(); + info!("For Input update for {:?}", _item); + let item =_item.save(self.trx()).await?.try_into_model()?; + result.push( item); + } + Ok(result) } } diff --git a/crates/services/api/src/service/app/case.rs b/crates/services/api/src/service/app/case.rs index 5d00142..93af954 100644 --- a/crates/services/api/src/service/app/case.rs +++ b/crates/services/api/src/service/app/case.rs @@ -3,6 +3,8 @@ use sea_orm::ActiveValue::Set; use sea_query::{Condition, Expr}; use tracing::{debug, info}; use uuid::Uuid; +use cerium::client::driver::web::WebDriver; +use engine::controller::case::CaseController; use entity::prelude::case::{Column, Entity, Model}; use entity::prelude::case_block::{ActiveModel as BlockActiveModel, Column as BlockColumn, Entity as BlockEntity, Model as BlockModel}; @@ -89,12 +91,12 @@ impl CaseService { return Err(OrcaRepoError::ModelNotFound("Test Case".to_string(), case_id.to_string()))?; } - // let ui_driver = UIHelper::default().await.expect("error"); - // info!("got the driver"); - // let controller = CaseController::new(&CONFIG.get().await.db_client, &ui_driver); - // info!("got the controller"); - // controller.process(&case.unwrap()).await.expect("error"); - // ui_driver.driver.quit().await.expect("TODO: panic message"); + let ui_driver = WebDriver::default().await.expect("error"); + info!("got the driver"); + let controller = CaseController::new(self.trx(), ui_driver.clone()); + info!("got the controller"); + controller.process(&case.unwrap()).await.expect("error"); + ui_driver.driver.quit().await.expect("TODO: panic message"); Ok(()) } diff --git a/crates/services/engine/Cargo.toml b/crates/services/engine/Cargo.toml index 83a35ef..69322eb 100644 --- a/crates/services/engine/Cargo.toml +++ b/crates/services/engine/Cargo.toml @@ -24,18 +24,17 @@ ui-automation = [] default = ["ui-automation", "api-automation"] [dependencies] -log = "0.4.16" -serde = { version = "1.0.123", features = ["derive"] } -serde_json = "1.0.59" -tokio = "1.17.0" -thiserror = "1.0.31" -thirtyfour = "0.31.0" +cerium.workspace = true +entity.workspace = true -entity = { workspace=true } -cerium = { workspace=true } - - -sea-orm = { version = "0.10.6", default-features = true, features = [ "macros", "debug-print", "runtime-async-std-native-tls", "sqlx-postgres"] } +sea-orm.workspace = true +serde.workspace = true +serde_json.workspace = true +thiserror.workspace = true +tokio.workspace = true +tracing.workspace=true +tracing-subscriber.workspace=true +thirtyfour.workspace = true diff --git a/crates/services/engine/src/controller/action.rs b/crates/services/engine/src/controller/action.rs index b81f121..b818018 100644 --- a/crates/services/engine/src/controller/action.rs +++ b/crates/services/engine/src/controller/action.rs @@ -1,18 +1,20 @@ -use log::info; -use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, ModelTrait, PaginatorTrait, QueryFilter, QueryOrder}; +use std::fs; +use std::io::Write; +use sea_orm::{ColumnTrait, DatabaseConnection, DatabaseTransaction, EntityTrait, ModelTrait, PaginatorTrait, QueryFilter, QueryOrder}; use sea_orm::prelude::Uuid; +use tracing::info; use thirtyfour::By; +use cerium::client::driver::web::WebDriver; use entity::prelude::target::ActionTargetKind; use entity::test::ui::action::action; use entity::test::ui::action::action::ActionKind; use crate::error::{EngineError, EngineResult}; -use crate::server::driver::UIHelper; pub struct ActionController<'ccl>{ - db: &'ccl DatabaseConnection, - driver: &'ccl UIHelper + db: &'ccl DatabaseTransaction, + driver: WebDriver } impl<'ccl> ActionController<'ccl> { @@ -27,15 +29,16 @@ impl<'ccl> ActionController<'ccl> { /// # Example /// /// ``` - /// use sea_orm::DatabaseConnection; + /// use sea_orm::{DatabaseConnection, DatabaseTransaction}; + /// use cerium::client::driver::web::WebDriver; /// use engine::controller::action::ActionController; /// use engine::server::driver::UIHelper; /// - /// let db = DatabaseConnection::new(); - /// let driver = UIHelper::default(); - /// let controller = ActionController::new(&db, &driver); + /// let db = DatabaseTransaction::new(); + /// let driver = WebDriver::default(); + /// let controller = ActionController::new(&db, driver); /// ``` - pub fn new(db: &'ccl DatabaseConnection, driver: &'ccl UIHelper) -> ActionController<'ccl> { + pub fn new(db: &'ccl DatabaseTransaction, driver: WebDriver) -> ActionController<'ccl> { Self{db, driver} } @@ -49,15 +52,15 @@ impl<'ccl> ActionController<'ccl> { /// # Example /// /// ```rust - /// use sea_orm::DatabaseConnection; + /// use sea_orm::{DatabaseConnection, DatabaseTransaction}; + /// use cerium::client::driver::web::WebDriver; /// use engine::controller::action::ActionController; - /// use engine::server::driver::UIHelper; /// use entity::test::ui::action::action::Model; /// - /// let db = DatabaseConnection::new(); - /// let driver = UIHelper::default(); + /// let db = DatabaseTransaction::new(); + /// let driver = WebDriver::default(); /// let action = Model::new(); - /// let controller = ActionController::new(&db, &driver); + /// let controller = ActionController::new(&db, driver); /// controller.command_open(&action).await; /// ``` /// @@ -65,11 +68,10 @@ impl<'ccl> ActionController<'ccl> { /// /// * `Result<(), EngineError>` - If the `data_value` field is `None`, it returns an `Err` with an `EngineError::Forbidden` variant. If the `data_value` field is not `None`, it opens the URL using the `drive` object and returns `Ok(())`. pub async fn command_open(&self, action: &action::Model) -> EngineResult<()> { - let _action = match action.to_owned().data_value { - None => Err(EngineError::Forbidden), - Some(url) => self.driver.open(url.as_str()).await - }; - Ok(()) + match action.data_value.clone() { + Some(value) => Ok(self.driver.open(value.as_str()).await?), + None => Err(EngineError::MissingParameter("url".to_string(), "".to_string())) + } } /// Asynchronously enters data into a target element on a web page using a WebDriver. @@ -130,10 +132,10 @@ impl<'ccl> ActionController<'ccl> { /// /// Returns `Ok(())` if the click action is performed successfully. async fn command_click(&self, action: &action::Model) -> EngineResult<()> { - let target_value = action.data_value.clone() - .ok_or_else(|| EngineError::MissingParameter("action.target_value".to_string(), "".to_string()))?; + let target_value = action.target_value.clone() + .ok_or_else(|| EngineError::MissingParameter("command_click.action.target_value".to_string(), "".to_string()))?; let target_kind = action.target_kind.clone() - .ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; + .ok_or_else(|| EngineError::MissingParameter("command_click.action.target_kind".to_string(), "".to_string()))?; let by_kind = match target_kind { ActionTargetKind::Css => By::Css(target_value.as_str()), ActionTargetKind::Id => By::Id(target_value.as_str()), @@ -147,7 +149,7 @@ impl<'ccl> ActionController<'ccl> { let data_value = action.data_value.clone() .ok_or_else(|| EngineError::MissingParameter("action.data_value".to_string(), "".to_string()))?; let target_value = action.target_value.clone() - .ok_or_else(|| EngineError::MissingParameter("action.target_value".to_string(), "".to_string()))?; + .ok_or_else(|| EngineError::MissingParameter("command_verify_text.action.target_value".to_string(), "".to_string()))?; let target_kind = action.target_kind.clone() .ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; let by_kind = match target_kind { @@ -155,7 +157,9 @@ impl<'ccl> ActionController<'ccl> { ActionTargetKind::Id => By::Id(target_value.as_str()), ActionTargetKind::Xpath => By::XPath(target_value.as_str()) }; - let text = self.driver.find(by_kind).await?.inner_html().await?; + let we = self.driver.find(by_kind).await?; + let text = we.inner_html().await?; + info!(text); if text != data_value { info!("Verify text is failed {}", data_value); return Err(EngineError::MissingParameter("action.data_value".to_string(), data_value)); @@ -165,7 +169,7 @@ impl<'ccl> ActionController<'ccl> { } pub async fn step_executor(&self, action: &action::Model) -> EngineResult<()> { - let set_response = match action.kind { + let set_response = match action.kind.clone() { ActionKind::Open => self.command_open(action).await?, ActionKind::Enter => self.command_enter(action).await?, ActionKind::Click => self.command_click(action).await?, @@ -176,6 +180,13 @@ impl<'ccl> ActionController<'ccl> { }; Ok(()) } + + async fn take_screenshot(&self, id: String) -> EngineResult<()> { + let result = self.driver.take_screenshot().await?; + let mut file = fs::File::create(format!("evidence_{id}.png")).expect("error"); + file.write_all(&*result).expect("error"); + Ok(()) + } /// run_case - will execute the test case by the case ID pub async fn execute(&self, id: Uuid) -> EngineResult<()> { @@ -183,11 +194,12 @@ impl<'ccl> ActionController<'ccl> { let mut action_page = action::Entity::find() .filter(action::Column::ActionGroupId.eq(id)) .order_by_asc(action::Column::ExecutionOrder).paginate(self.db, 50); - while let Some(actions) = action_page.fetch_and_next().await - .map_err(EngineError::DatabaseError)? { + while let Some(actions) = action_page.fetch_and_next().await? { for action in actions.into_iter() { info!("Executing step == [id] {:?}, [desc] {:?}", action.id, action.description); self.step_executor(&action).await?; + self.take_screenshot(action.id.to_string()).await?; + info!("Done step == [id] {:?}, [desc] {:?}", action.id, action.description); } } Ok(()) diff --git a/crates/services/engine/src/controller/case.rs b/crates/services/engine/src/controller/case.rs index 7f8c736..ca40632 100644 --- a/crates/services/engine/src/controller/case.rs +++ b/crates/services/engine/src/controller/case.rs @@ -1,51 +1,53 @@ -use log::{error, info}; -use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder}; +use sea_orm::{ColumnTrait, DatabaseTransaction, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder}; use sea_orm::prelude::Uuid; +use tracing::{error, info}; +use cerium::client::driver::web::WebDriver; +use entity::prelude::case::Entity; use entity::prelude::case_block; use entity::prelude::case_block::{BlockKind, BlockType}; use entity::test::ui::case::case; use crate::controller::action::ActionController; -use crate::server::driver::UIHelper; +use crate::error::EngineResult; pub struct CaseController<'ccl>{ - db: &'ccl DatabaseConnection, - drive: &'ccl UIHelper + db: &'ccl DatabaseTransaction, + drive: WebDriver } impl<'ccl> CaseController<'ccl> { - pub fn new(db: &'ccl DatabaseConnection, drive: &'ccl UIHelper) -> CaseController<'ccl> { + pub fn new(db: &'ccl DatabaseTransaction, drive: WebDriver) -> CaseController<'ccl> { Self{db, drive } } /// run_case - will execute the test case by the case ID - pub async fn run_case(&self, id: Uuid) -> Result<(), sea_orm::DbErr> { - let case_res = case::Entity::find_by_id(id).all(self.db).await?; - if case_res.is_empty() { + pub async fn run_case(&self, id: Uuid) -> EngineResult<()> { + let case_res = Entity::find_by_id(id).one(self.db).await?; + if case_res.is_none() { error!("Unable to find the Case - {:?}", id.clone()); return Ok(()); } - let case: &case::Model = &case_res[0]; + let case: &case::Model = &case_res.unwrap(); info!("Start Processing Case - [[ {name} || {id} ]]", name=case.name, id=case.id); self.process(case).await?; Ok(()) } /// process will get the block and execute in the batch based on the kind of the block - pub async fn process(&self, case: &case::Model) -> Result<(), sea_orm::DbErr> { + pub async fn process(&self, case: &case::Model) -> EngineResult<()> { let mut block_page = case_block::Entity::find() .filter(case_block::Column::CaseId.eq(case.id)) .order_by_asc(case_block::Column::ExecutionOrder).paginate(self.db, 10); while let Some(blocks) = block_page.fetch_and_next().await? { for block in blocks.into_iter() { - self.switch_block(&block).await + self.switch_block(&block).await?; } } Ok(()) } /// switch_block - function to switch the block based on the type and kind of the block - async fn switch_block(&self, block: &case_block::Model){ + async fn switch_block(&self, block: &case_block::Model) -> EngineResult<()>{ let result = match block.kind { BlockKind::Loop => { match block.type_field { @@ -68,7 +70,8 @@ impl<'ccl> CaseController<'ccl> { _ => todo!("Need to raise a error from here since non other supported") } }, - }.await; + }.await?; + Ok(()) } async fn process_in_memory_loop(&self, block: &case_block::Model) -> () { @@ -83,10 +86,10 @@ impl<'ccl> CaseController<'ccl> { } - async fn process_action_group(&self, block: &case_block::Model) -> () { + async fn process_action_group(&self, block: &case_block::Model) -> EngineResult<()> { info!("Starting processing {block_id}", block_id=block.id); - ActionController::new(self.db, self.drive).execute(block.reference.unwrap()).await - .expect("failed on error") + Ok(ActionController::new(self.db, self.drive.clone()) + .execute(block.reference.unwrap()).await?) } } diff --git a/crates/services/engine/src/driver/api.rs b/crates/services/engine/src/driver/api.rs deleted file mode 100644 index 77369f1..0000000 --- a/crates/services/engine/src/driver/api.rs +++ /dev/null @@ -1,5 +0,0 @@ - - - -pub struct APIDriver { -} \ No newline at end of file diff --git a/crates/services/engine/src/driver/mod.rs b/crates/services/engine/src/driver/mod.rs deleted file mode 100644 index 35bea3a..0000000 --- a/crates/services/engine/src/driver/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod ui; -pub mod api; - -pub trait EngineDriver { - -} \ No newline at end of file diff --git a/crates/services/engine/src/driver/ui.rs b/crates/services/engine/src/driver/ui.rs deleted file mode 100644 index d1cb07e..0000000 --- a/crates/services/engine/src/driver/ui.rs +++ /dev/null @@ -1,48 +0,0 @@ -use thirtyfour::{By, WebDriver}; - -use entity::prelude::target::ActionTargetKind; -use entity::test::ui::action::action::ActionKind; - -// use entity::action::{ActionGroup, ActionKind, ActionTarget, ATargetKind}; - -/// Controller -/// - Make sure the Object Construction Happen -/// - Correlation -/// -/// // Driver Layer - Gets client as ref, Api Group -/// - -/// UIDriver is driver that will Handle all the -pub struct UIDriver<'uid> { - pub(crate) client: &'uid WebDriver, -} - -impl<'uid> UIDriver<'uid> { - /// set_client Set the client object into the driver - pub fn set_client(client: &WebDriver) { - } - /// default will create a new object to UI driver that will make - /// the driver execute the command obj the W3C COMMAND - pub fn default(client: &WebDriver) -> UIDriver { - UIDriver{client} - } - - pub fn match_action_type(&self, kind: &ActionKind){ - match kind { - ActionKind::Click => {} - ActionKind::Enter => {} - ActionKind::DoubleClick => {} - _ => {} - } - } - - /// target - get the target object by - fn target(&self, target: &ActionTargetKind, value: &String) -> By { - match &target { - ActionTargetKind::Css => By::Css(value), - ActionTargetKind::Id => By::Id(value), - ActionTargetKind::Xpath => By::XPath(value) - } - } - -} \ No newline at end of file diff --git a/crates/services/engine/src/error.rs b/crates/services/engine/src/error.rs index def66c1..cf80d64 100644 --- a/crates/services/engine/src/error.rs +++ b/crates/services/engine/src/error.rs @@ -2,6 +2,7 @@ use sea_orm::DbErr; use serde_json::Error as SerdeJsonError; use thirtyfour::error::WebDriverError; use thiserror::Error; +use cerium::error::CeriumError; pub type EngineResult = Result; @@ -18,6 +19,8 @@ pub enum EngineError { #[error("Database error: {0}")] DatabaseError(#[from] DbErr), #[error("Json Serialization error: {0}")] - SerializerError(#[from] SerdeJsonError) + SerializerError(#[from] SerdeJsonError), + #[error("CeriumError: {0}")] + CeriumError(#[from] CeriumError) } diff --git a/crates/services/engine/src/lib.rs b/crates/services/engine/src/lib.rs index 3412533..e06a8e7 100644 --- a/crates/services/engine/src/lib.rs +++ b/crates/services/engine/src/lib.rs @@ -1,6 +1,5 @@ extern crate entity; -pub mod driver; pub mod ui; pub mod controller; pub mod server; diff --git a/crates/services/engine/src/server/driver.rs b/crates/services/engine/src/server/driver.rs deleted file mode 100644 index e733898..0000000 --- a/crates/services/engine/src/server/driver.rs +++ /dev/null @@ -1,58 +0,0 @@ -use thirtyfour::{By, DesiredCapabilities, WebDriver, WebElement}; - -use crate::error::{EngineError, EngineResult}; - -pub struct UIHelper { - pub driver: WebDriver, -} - -impl UIHelper { - /// new - will create new Helper object with the EngineResult Wrap around it - /// - /// # Example - /// ```no_run - /// use engine::error::EngineResult; - /// use thirtyfour::WebDriver; - /// fn main() -> EngineResult<()> { - /// use engine::server::driver::UIHelper; - /// let _driver = WebDriver::default(); - /// let driver = UIHelper::new(_driver)?; - /// } - /// ``` - /// - /// **NOTE:** If the webdriver appears to hang or give no response, please check that the - /// capabilities object is of the correct type for that webdriver. - pub fn new(driver: WebDriver) -> EngineResult { - let helper = UIHelper{driver}; - Ok(helper) - } - - pub async fn default() -> EngineResult { - let caps = DesiredCapabilities::firefox(); - let driver = WebDriver::new("http://localhost:4444/wd/hub/session", - caps).await.map_err(EngineError::WebdriverError)?; - Self::new(driver) - } - - - pub async fn open(&self, url: &str) -> EngineResult<()> { - self.driver.goto(url).await.map_err(EngineError::WebdriverError) - } - - pub async fn create_window(&self, name: &str) -> EngineResult<()> { - let win_handler = self.driver.new_window().await.map_err(EngineError::WebdriverError)?; - self.driver.switch_to_window(win_handler).await.map_err(EngineError::WebdriverError)?; - self.driver.set_window_name(name).await.map_err(EngineError::WebdriverError)?; - Ok(()) - } - - pub async fn find(&self, by: impl Into) -> EngineResult { - self.driver.find(by).await.map_err(EngineError::WebdriverError) - } - - - /// take_screenshot - will take screenshot and send png back to the requester - pub async fn take_screenshot(&self) -> EngineResult> { - self.driver.screenshot_as_png().await.map_err(EngineError::WebdriverError) - } -} diff --git a/crates/services/engine/src/server/mod.rs b/crates/services/engine/src/server/mod.rs index f0ce7f9..e69de29 100644 --- a/crates/services/engine/src/server/mod.rs +++ b/crates/services/engine/src/server/mod.rs @@ -1 +0,0 @@ -pub mod driver; \ No newline at end of file diff --git a/crates/services/engine/tests/controller.rs b/crates/services/engine/tests/controller.rs index eaa8d02..78aa60e 100644 --- a/crates/services/engine/tests/controller.rs +++ b/crates/services/engine/tests/controller.rs @@ -6,26 +6,28 @@ mod tests { use std::str::FromStr; - use log::info; - use sea_orm::Database; + use sea_orm::{Database, TransactionTrait}; use sea_orm::prelude::Uuid; + use tracing::{info, Level}; + use tracing_subscriber::fmt; + use cerium::client::driver::web::WebDriver; - use cerium::utils::init_logger; use engine::controller::case::CaseController; - use engine::server::driver::UIHelper; #[tokio::test] async fn dry_run_test_controller() { - init_logger(); - let case_id = "cd4ecfdd-628e-4288-b2a7-2eab2827673a".to_string(); + // init_logger(); + fmt().with_max_level(Level::DEBUG).init(); + let case_id = "731453aa-95a5-4180-be0d-c211a1e92aad".to_string(); let uri = Some("postgres://root:root@localhost:5432/orca".to_string()); let db = Database::connect(uri.unwrap()).await.expect("Error unable to connect DB"); + let trx = db.begin().await.expect("Error unable to connect DB"); info!("got the db"); - let ui_driver = UIHelper::default().await.expect("error"); + let ui_driver = WebDriver::default().await.expect("error"); info!("got the driver"); - let controller = CaseController::new(&db, &ui_driver); + let controller = CaseController::new(&trx, ui_driver.clone()); info!("got the controller"); controller.run_case(Uuid::from_str(case_id.as_str()).expect("")).await.expect("error"); ui_driver.driver.quit().await; diff --git a/docker-compose.yml b/docker-compose.yml index 1a3ec96..3dec343 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,7 @@ services: - SE_EVENT_BUS_PUBLISH_PORT=4442 - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 - SE_NODE_MAX_CONCURRENT_SESSIONS=5 + - SE_NODE_MAX_SESSIONS=5 # chrome_video: # image: selenium/video:ffmpeg-4.3.1-20221208 From 893965512e9d8134635095560ad4b8697c5d6605 Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Mon, 1 Jan 2024 08:37:29 +0530 Subject: [PATCH 6/8] Added History entity --- Makefile | 14 + crates/libs/cerium/src/client/cache.rs | 1 + crates/libs/cerium/src/client/db/mod.rs | 6 +- crates/libs/cerium/src/client/driver/mod.rs | 2 +- crates/libs/cerium/src/client/driver/web.rs | 9 +- crates/libs/cerium/src/client/mod.rs | 12 +- crates/libs/cerium/src/config.rs | 8 +- crates/libs/cerium/src/error/cerium.rs | 13 +- crates/libs/cerium/src/error/mod.rs | 17 +- crates/libs/cerium/src/lib.rs | 5 +- crates/libs/cerium/src/server/mod.rs | 33 +- crates/libs/cerium/src/server/request_id.rs | 2 +- crates/libs/cerium/src/server/utils.rs | 1 + crates/libs/cerium/src/utils/mod.rs | 3 - crates/libs/cerium/src/utils/uuid.rs | 2 +- crates/libs/cerium/tests/1_init.rs | 6 +- crates/libs/entity/Cargo.toml | 3 +- crates/libs/entity/src/admin/group.rs | 0 crates/libs/entity/src/admin/mod.rs | 2 +- crates/libs/entity/src/admin/user.rs | 1 - crates/libs/entity/src/app/app.rs | 1 - crates/libs/entity/src/app/mod.rs | 2 +- crates/libs/entity/src/auth/mod.rs | 1 + crates/libs/entity/src/command.rs | 2 +- crates/libs/entity/src/common/attachment.rs | 16 +- crates/libs/entity/src/common/mod.rs | 2 +- crates/libs/entity/src/common/tag.rs | 3 - crates/libs/entity/src/common/tag_entity.rs | 7 +- crates/libs/entity/src/core/mod.rs | 3 +- crates/libs/entity/src/lib.rs | 11 +- crates/libs/entity/src/prelude.rs | 18 +- crates/libs/entity/src/test/datatable.rs | 3 +- crates/libs/entity/src/test/field.rs | 10 +- crates/libs/entity/src/test/history.rs | 72 +++ crates/libs/entity/src/test/mod.rs | 5 +- crates/libs/entity/src/test/profile/data.rs | 4 - crates/libs/entity/src/test/profile/mod.rs | 2 +- .../libs/entity/src/test/profile/profile.rs | 4 +- .../libs/entity/src/test/ui/action/action.rs | 8 +- crates/libs/entity/src/test/ui/action/data.rs | 9 +- .../libs/entity/src/test/ui/action/group.rs | 10 +- crates/libs/entity/src/test/ui/action/mod.rs | 3 +- .../libs/entity/src/test/ui/action/target.rs | 9 +- crates/libs/entity/src/test/ui/case/case.rs | 4 +- .../entity/src/test/ui/case/case_block.rs | 13 +- .../entity/src/test/ui/case/data_binding.rs | 6 +- crates/libs/entity/src/test/ui/case/mod.rs | 4 +- crates/libs/entity/src/test/ui/elements.rs | 12 +- crates/libs/entity/src/test/ui/mod.rs | 6 +- crates/libs/entity/src/test/ui/screen.rs | 1 - crates/libs/entity/src/test/ui/suit/mod.rs | 2 +- crates/libs/entity/src/test/ui/suit/suite.rs | 7 +- .../entity/src/test/ui/suit/suite_block.rs | 18 +- crates/libs/migration/src/lib.rs | 9 +- crates/libs/migration/src/migration001.rs | 446 +++++++++++++----- crates/libs/migration/src/migration002.rs | 82 ++-- crates/libs/migration/src/migration003.rs | 100 ++-- crates/libs/migration/src/migration004.rs | 60 +++ crates/services/api/src/error.rs | 24 +- crates/services/api/src/main.rs | 22 +- crates/services/api/src/route/admin/user.rs | 48 +- crates/services/api/src/route/app/action.rs | 52 +- crates/services/api/src/route/app/case.rs | 86 ++-- .../services/api/src/route/app/datatable.rs | 136 ++++-- crates/services/api/src/route/app/group.rs | 42 +- crates/services/api/src/route/app/mod.rs | 48 +- crates/services/api/src/route/app/profile.rs | 69 +-- crates/services/api/src/route/app/suit.rs | 72 +-- crates/services/api/src/route/mod.rs | 10 +- crates/services/api/src/route/public.rs | 6 +- .../services/api/src/server/middleware/mod.rs | 12 +- .../api/src/server/middleware/orca.rs | 1 + crates/services/api/src/server/mod.rs | 2 +- crates/services/api/src/server/session.rs | 5 +- crates/services/api/src/service/admin/mod.rs | 2 +- crates/services/api/src/service/admin/user.rs | 36 +- crates/services/api/src/service/app/action.rs | 56 ++- crates/services/api/src/service/app/case.rs | 134 ++++-- .../services/api/src/service/app/datatable.rs | 139 ++++-- crates/services/api/src/service/app/group.rs | 42 +- crates/services/api/src/service/app/mod.rs | 14 +- .../services/api/src/service/app/profile.rs | 57 ++- crates/services/api/src/service/app/suit.rs | 85 ++-- crates/services/api/src/service/mod.rs | 5 +- crates/services/api/src/utils/mod.rs | 5 +- .../services/engine/src/controller/action.rs | 120 +++-- crates/services/engine/src/controller/case.rs | 71 ++- crates/services/engine/src/controller/mod.rs | 4 +- .../services/engine/src/controller/suite.rs | 1 + crates/services/engine/src/error.rs | 6 +- crates/services/engine/src/lib.rs | 5 +- crates/services/engine/src/server/mod.rs | 1 + crates/services/engine/src/ui/mod.rs | 2 - crates/services/engine/src/ui/step.rs | 2 - crates/services/engine/tests/controller.rs | 17 +- 95 files changed, 1647 insertions(+), 907 deletions(-) create mode 100644 Makefile delete mode 100644 crates/libs/entity/src/admin/group.rs create mode 100644 crates/libs/entity/src/test/history.rs create mode 100644 crates/libs/migration/src/migration004.rs diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ba3e279 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +help: + @echo "Make Commands:" + @echo "make help\n\tGive you the Help option supported" + @echo "make init\n\tInitialize Project (For Debian/Ubuntu)" + @echo "make dev\n\tStart with Hot Module Reload." + @echo "make prod\n\tStart with --release" + @echo "make stop\n\tKill running processes." + +init: + cargo install --bin api + +start: + cd backend && cargo watch -q -c -w src/ -x run & + cd frontend && trunk serve & \ No newline at end of file diff --git a/crates/libs/cerium/src/client/cache.rs b/crates/libs/cerium/src/client/cache.rs index e69de29..8b13789 100644 --- a/crates/libs/cerium/src/client/cache.rs +++ b/crates/libs/cerium/src/client/cache.rs @@ -0,0 +1 @@ + diff --git a/crates/libs/cerium/src/client/db/mod.rs b/crates/libs/cerium/src/client/db/mod.rs index 90302ea..c7e8a09 100644 --- a/crates/libs/cerium/src/client/db/mod.rs +++ b/crates/libs/cerium/src/client/db/mod.rs @@ -1,7 +1,3 @@ - - pub trait DatabaseTrait { - fn create() { - - } + fn create() {} } diff --git a/crates/libs/cerium/src/client/driver/mod.rs b/crates/libs/cerium/src/client/driver/mod.rs index d7cf837..fdd4603 100644 --- a/crates/libs/cerium/src/client/driver/mod.rs +++ b/crates/libs/cerium/src/client/driver/mod.rs @@ -1 +1 @@ -pub mod web; \ No newline at end of file +pub mod web; diff --git a/crates/libs/cerium/src/client/driver/web.rs b/crates/libs/cerium/src/client/driver/web.rs index 9efb008..f2f0e29 100644 --- a/crates/libs/cerium/src/client/driver/web.rs +++ b/crates/libs/cerium/src/client/driver/web.rs @@ -1,8 +1,7 @@ -use thirtyfour::{WebDriver as TFWebDriver}; +use thirtyfour::WebDriver as TFWebDriver; - -use thirtyfour::{By, DesiredCapabilities, WebElement}; use crate::error::CeriumResult; +use thirtyfour::{By, DesiredCapabilities, WebElement}; #[derive(Clone)] pub struct WebDriver { @@ -27,7 +26,7 @@ impl WebDriver { /// **NOTE:** If the webdriver appears to hang or give no response, please check that the /// capabilities object is of the correct type for that webdriver. pub fn new(driver: TFWebDriver) -> CeriumResult { - let helper = WebDriver{driver}; + let helper = WebDriver { driver }; Ok(helper) } @@ -37,7 +36,6 @@ impl WebDriver { Self::new(driver) } - pub async fn open(&self, url: &str) -> CeriumResult<()> { Ok(self.driver.goto(url).await?) } @@ -53,7 +51,6 @@ impl WebDriver { Ok(self.driver.find(by).await?) } - /// take_screenshot - will take screenshot and send png back to the requester pub async fn take_screenshot(&self) -> CeriumResult> { Ok(self.driver.screenshot_as_png().await?) diff --git a/crates/libs/cerium/src/client/mod.rs b/crates/libs/cerium/src/client/mod.rs index 81543cb..b8de7e3 100644 --- a/crates/libs/cerium/src/client/mod.rs +++ b/crates/libs/cerium/src/client/mod.rs @@ -6,15 +6,14 @@ pub mod cache; pub mod db; pub mod driver; - #[derive(Debug, Clone)] pub struct Client { - pub db: DatabaseConnection + pub db: DatabaseConnection, } impl Client { pub async fn new(db_uri: Option, redis_uri: Option) -> Self { - Client{ + Client { db: Self::db_client(db_uri).await, } } @@ -25,9 +24,8 @@ impl Client { /// db_uri will give the default uri if there is not config setup async fn db_client(mut uri: Option) -> DatabaseConnection { - if uri.is_none(){ + if uri.is_none() { uri = Some(std::env::var("DATABASE_URL").expect("DATABASE_URL must be set.")); - } let mut opt = ConnectOptions::new(uri.unwrap()); opt.max_connections(10) @@ -37,7 +35,9 @@ impl Client { .idle_timeout(Duration::from_secs(8)) .max_lifetime(Duration::from_secs(8)) .sqlx_logging(true); - Database::connect(opt).await.expect("Error unable to connect DB") + Database::connect(opt) + .await + .expect("Error unable to connect DB") // Database::connect(uri.unwrap()).await.expect("Error unable to connect DB") } } diff --git a/crates/libs/cerium/src/config.rs b/crates/libs/cerium/src/config.rs index b9ae200..0b031fd 100644 --- a/crates/libs/cerium/src/config.rs +++ b/crates/libs/cerium/src/config.rs @@ -1,6 +1,4 @@ -use std::time::Duration; - -use sea_orm::{ConnectOptions, Database, DatabaseConnection}; +use sea_orm::DatabaseConnection; use crate::env::Environment; @@ -8,13 +6,13 @@ use crate::env::Environment; #[allow(unused)] pub struct Config { pub env: Environment, - pub db: Option + pub db: Option, } impl Config { pub fn new() -> Self { let env = Environment::new(); - let config = Config{ env, db: None }; + let config = Config { env, db: None }; config } } diff --git a/crates/libs/cerium/src/error/cerium.rs b/crates/libs/cerium/src/error/cerium.rs index 2d141c2..57e6030 100644 --- a/crates/libs/cerium/src/error/cerium.rs +++ b/crates/libs/cerium/src/error/cerium.rs @@ -15,7 +15,11 @@ pub struct ErrorResponse { impl ErrorResponse { pub fn new(error: &str, message: String) -> Self { - Self { code: "".to_string(), error: error.to_string(), message } + Self { + code: "".to_string(), + error: error.to_string(), + message, + } } } @@ -48,9 +52,6 @@ impl CeriumError { } } fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!( - "An error occurred: \"{}\"", - self.to_string() - )) + f.write_fmt(format_args!("An error occurred: \"{}\"", self.to_string())) } -} \ No newline at end of file +} diff --git a/crates/libs/cerium/src/error/mod.rs b/crates/libs/cerium/src/error/mod.rs index 8088270..6afedb4 100644 --- a/crates/libs/cerium/src/error/mod.rs +++ b/crates/libs/cerium/src/error/mod.rs @@ -1,16 +1,16 @@ use axum::http::StatusCode; -use axum::Json; use axum::response::{IntoResponse, Response}; +use axum::Json; use sea_orm::DbErr; -use serde_json::{Error as SerdeJsonError, json}; +use serde_json::{json, Error as SerdeJsonError}; use thirtyfour::error::WebDriverError; use thiserror::Error; // pub use cerium::{CeriumError as OtherCeriumError, CeriumResult, ErrorResponse}; pub type CeriumResult = Result; -pub mod web; pub mod cerium; +pub mod web; /// Our app's top level error type. #[derive(Error, Debug)] @@ -27,13 +27,14 @@ pub enum CeriumError { impl IntoResponse for CeriumError { fn into_response(self) -> Response { let (status, error_message) = match self { - CeriumError::DataBaseError(err) =>{ - (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) - } + CeriumError::DataBaseError(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()), CeriumError::SerializerError(err) => { (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) } - _ => (StatusCode::INTERNAL_SERVER_ERROR, "Internal Error Not Specify".to_string()) + _ => ( + StatusCode::INTERNAL_SERVER_ERROR, + "Internal Error Not Specify".to_string(), + ), }; let body = Json(json!({ @@ -42,4 +43,4 @@ impl IntoResponse for CeriumError { (status, body).into_response() } -} \ No newline at end of file +} diff --git a/crates/libs/cerium/src/lib.rs b/crates/libs/cerium/src/lib.rs index f7d89cb..34a51a8 100644 --- a/crates/libs/cerium/src/lib.rs +++ b/crates/libs/cerium/src/lib.rs @@ -5,11 +5,10 @@ use crate::config::Config; pub mod client; pub mod config; +pub mod env; pub mod error; pub mod server; pub mod utils; -pub mod env; - // lazy_static! { // // AsyncOnce::new(async { @@ -22,4 +21,4 @@ pub mod env; lazy_static! { pub static ref CONFIG: AsyncOnce = AsyncOnce::new(async { Config::new() }); -} \ No newline at end of file +} diff --git a/crates/libs/cerium/src/server/mod.rs b/crates/libs/cerium/src/server/mod.rs index d90ea60..92f4ba4 100644 --- a/crates/libs/cerium/src/server/mod.rs +++ b/crates/libs/cerium/src/server/mod.rs @@ -1,27 +1,30 @@ -use std::sync::{Arc, Mutex}; -use axum::{Router, serve}; +use crate::client::Client; use axum::http::{HeaderName, Method}; +use axum::{serve, Router}; use chrono::Duration; use sea_orm::DatabaseConnection; +use std::sync::{Arc, Mutex}; use tokio::net::TcpListener; -use tower_http::{compression::CompressionLayer, cors::{Any, CorsLayer}}; use tower_http::catch_panic::CatchPanicLayer; use tower_http::classify::ServerErrorsFailureClass; use tower_http::request_id::{PropagateRequestIdLayer, SetRequestIdLayer}; use tower_http::trace::TraceLayer; +use tower_http::{ + compression::CompressionLayer, + cors::{Any, CorsLayer}, +}; use tracing::{error, info, Level, Span}; use tracing_subscriber::fmt; use tracing_subscriber::layer::SubscriberExt; -use crate::client::Client; use crate::server::request_id::OrcaRequestId; -mod utils; mod request_id; +mod utils; #[derive(Clone)] pub struct AppState { - pub db: Arc> + pub db: Arc>, } pub struct App { @@ -29,7 +32,7 @@ pub struct App { port: i32, log_level: Level, router: Router, - cli: Client + cli: Client, } impl App { @@ -39,18 +42,18 @@ impl App { port: 80, log_level: Level::INFO, router: Default::default(), - cli + cli, } } pub fn set_logger(&self, filter: Level) { - fmt() // .with(tracing_subscriber::fmt::layer()) // .with_target(true) // .with_timer(tracing_subscriber::fmt::time::uptime()) // .with_level(true) - .with_max_level(filter).init() + .with_max_level(filter) + .init() } pub fn set_port(&mut self, port: i32) { @@ -59,13 +62,11 @@ impl App { fn app_state(&mut self) -> AppState { AppState { - db: Arc::new(Mutex::new(self.cli.clone().db)) + db: Arc::new(Mutex::new(self.cli.clone().db)), } } - pub fn set_router(&mut self, router: Router) { - let x_request_id = HeaderName::from_static("x-request-id"); let cors = CorsLayer::new() .allow_methods([Method::GET, Method::POST]) @@ -85,10 +86,10 @@ impl App { } pub async fn run(self) { - let listener = TcpListener::bind(format!("0.0.0.0:{:?}", self.port)).await.unwrap(); + let listener = TcpListener::bind(format!("0.0.0.0:{:?}", self.port)) + .await + .unwrap(); info!("🚀 Starting Server "); serve(listener, self.router).await.unwrap(); } } - - diff --git a/crates/libs/cerium/src/server/request_id.rs b/crates/libs/cerium/src/server/request_id.rs index 9eca5cf..2eaf5ce 100644 --- a/crates/libs/cerium/src/server/request_id.rs +++ b/crates/libs/cerium/src/server/request_id.rs @@ -12,4 +12,4 @@ impl MakeRequestId for OrcaRequestId { info!("Request ID - {:?}", id); Some(RequestId::new(id.to_string().parse().unwrap())) } -} \ No newline at end of file +} diff --git a/crates/libs/cerium/src/server/utils.rs b/crates/libs/cerium/src/server/utils.rs index e69de29..8b13789 100644 --- a/crates/libs/cerium/src/server/utils.rs +++ b/crates/libs/cerium/src/server/utils.rs @@ -0,0 +1 @@ + diff --git a/crates/libs/cerium/src/utils/mod.rs b/crates/libs/cerium/src/utils/mod.rs index 81b2cee..c8d27ed 100644 --- a/crates/libs/cerium/src/utils/mod.rs +++ b/crates/libs/cerium/src/utils/mod.rs @@ -1,4 +1 @@ - - pub mod uuid; - diff --git a/crates/libs/cerium/src/utils/uuid.rs b/crates/libs/cerium/src/utils/uuid.rs index 2870229..599d473 100644 --- a/crates/libs/cerium/src/utils/uuid.rs +++ b/crates/libs/cerium/src/utils/uuid.rs @@ -7,4 +7,4 @@ // // pub fn request_uuid() -> String { // format!("Rid{}", Alphanumeric.sample_string(&mut rand::thread_rng(), 32)) -// } \ No newline at end of file +// } diff --git a/crates/libs/cerium/tests/1_init.rs b/crates/libs/cerium/tests/1_init.rs index 5ff33f0..5c6016f 100644 --- a/crates/libs/cerium/tests/1_init.rs +++ b/crates/libs/cerium/tests/1_init.rs @@ -1,6 +1,2 @@ - - #[cfg(test)] -mod tests { - -} \ No newline at end of file +mod tests {} diff --git a/crates/libs/entity/Cargo.toml b/crates/libs/entity/Cargo.toml index 1934289..1ed9144 100644 --- a/crates/libs/entity/Cargo.toml +++ b/crates/libs/entity/Cargo.toml @@ -15,4 +15,5 @@ rust-version.workspace = true serde.workspace = true serde_json.workspace = true sea-orm.workspace=true -sea-query.workspace=true \ No newline at end of file +sea-query.workspace=true +chrono.workspace=true \ No newline at end of file diff --git a/crates/libs/entity/src/admin/group.rs b/crates/libs/entity/src/admin/group.rs deleted file mode 100644 index e69de29..0000000 diff --git a/crates/libs/entity/src/admin/mod.rs b/crates/libs/entity/src/admin/mod.rs index 018ff2e..22d12a3 100644 --- a/crates/libs/entity/src/admin/mod.rs +++ b/crates/libs/entity/src/admin/mod.rs @@ -1 +1 @@ -pub mod user; \ No newline at end of file +pub mod user; diff --git a/crates/libs/entity/src/admin/user.rs b/crates/libs/entity/src/admin/user.rs index 6a03b19..536a920 100644 --- a/crates/libs/entity/src/admin/user.rs +++ b/crates/libs/entity/src/admin/user.rs @@ -20,5 +20,4 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} - impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/app/app.rs b/crates/libs/entity/src/app/app.rs index 7d112c1..602c0bd 100644 --- a/crates/libs/entity/src/app/app.rs +++ b/crates/libs/entity/src/app/app.rs @@ -18,5 +18,4 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} - impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/app/mod.rs b/crates/libs/entity/src/app/mod.rs index 02c0277..309be62 100644 --- a/crates/libs/entity/src/app/mod.rs +++ b/crates/libs/entity/src/app/mod.rs @@ -1 +1 @@ -pub mod app; \ No newline at end of file +pub mod app; diff --git a/crates/libs/entity/src/auth/mod.rs b/crates/libs/entity/src/auth/mod.rs index e69de29..8b13789 100644 --- a/crates/libs/entity/src/auth/mod.rs +++ b/crates/libs/entity/src/auth/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/libs/entity/src/command.rs b/crates/libs/entity/src/command.rs index e4e7f22..9e53479 100644 --- a/crates/libs/entity/src/command.rs +++ b/crates/libs/entity/src/command.rs @@ -11,7 +11,7 @@ pub struct Model { pub id: i32, pub kind: String, pub table_name: String, - pub command: Option + pub command: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/crates/libs/entity/src/common/attachment.rs b/crates/libs/entity/src/common/attachment.rs index a224017..87cc128 100644 --- a/crates/libs/entity/src/common/attachment.rs +++ b/crates/libs/entity/src/common/attachment.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(5))", enum_name = "storage_type")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(5))", + enum_name = "storage_type" +)] pub enum StorageType { #[sea_orm(string_value = "IB")] InBuild, @@ -16,7 +20,11 @@ pub enum StorageType { } #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(5))", enum_name = "storage_category")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(5))", + enum_name = "storage_category" +)] pub enum StorageCategory { #[sea_orm(string_value = "Evidence")] Evidence, @@ -26,7 +34,6 @@ pub enum StorageCategory { GCS, } - #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] #[sea_orm(table_name = "attachment")] pub struct Model { @@ -37,11 +44,10 @@ pub struct Model { pub path: String, pub name: String, pub desc: Option, - pub attachment: Option> + pub attachment: Option>, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} - impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/common/mod.rs b/crates/libs/entity/src/common/mod.rs index 534a265..7153134 100644 --- a/crates/libs/entity/src/common/mod.rs +++ b/crates/libs/entity/src/common/mod.rs @@ -1,3 +1,3 @@ pub mod attachment; pub mod tag; -pub mod tag_entity; \ No newline at end of file +pub mod tag_entity; diff --git a/crates/libs/entity/src/common/tag.rs b/crates/libs/entity/src/common/tag.rs index 94b91ef..0ad3088 100644 --- a/crates/libs/entity/src/common/tag.rs +++ b/crates/libs/entity/src/common/tag.rs @@ -4,8 +4,6 @@ use sea_orm::entity::prelude::*; use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; - - #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] #[sea_orm(table_name = "tag")] pub struct Model { @@ -19,5 +17,4 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} - impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/common/tag_entity.rs b/crates/libs/entity/src/common/tag_entity.rs index 50f4c43..01d8f80 100644 --- a/crates/libs/entity/src/common/tag_entity.rs +++ b/crates/libs/entity/src/common/tag_entity.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(5))", enum_name = "tag_entity_type")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(5))", + enum_name = "tag_entity_type" +)] pub enum EntityType { #[sea_orm(string_value = "AG")] ActionGroup, @@ -28,5 +32,4 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} - impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/core/mod.rs b/crates/libs/entity/src/core/mod.rs index f70ec86..b8caec4 100644 --- a/crates/libs/entity/src/core/mod.rs +++ b/crates/libs/entity/src/core/mod.rs @@ -4,5 +4,4 @@ pub trait OrcaModel: ActiveModelBehavior { fn new() -> Self { ::default() } - -} \ No newline at end of file +} diff --git a/crates/libs/entity/src/lib.rs b/crates/libs/entity/src/lib.rs index 17cc818..bfe3f2f 100644 --- a/crates/libs/entity/src/lib.rs +++ b/crates/libs/entity/src/lib.rs @@ -1,11 +1,10 @@ - // pub use sea_orm; // -pub mod prelude; -pub mod auth; -pub mod common; -pub mod test; +pub mod admin; pub mod app; +pub mod auth; pub mod command; +pub mod common; pub mod core; -pub mod admin; +pub mod prelude; +pub mod test; diff --git a/crates/libs/entity/src/prelude.rs b/crates/libs/entity/src/prelude.rs index 78cc95f..a291633 100644 --- a/crates/libs/entity/src/prelude.rs +++ b/crates/libs/entity/src/prelude.rs @@ -2,18 +2,12 @@ pub use super::common::attachment; pub use super::test::ui::{ - action::{ - group::Entity as ActionGroup, - target::Entity as ActionTarget - }, - case::{ - case::Entity as Case, - case_block::Entity as CaseBlock, - data_binding::Entity as DataBinding - } + action::{group, target}, + case::{case, case_block, data_binding}, }; pub use super::test::ui::{ - action::{group, target}, - case::{case, case_block, data_binding} + action::{group::Entity as ActionGroup, target::Entity as ActionTarget}, + case::{ + case::Entity as Case, case_block::Entity as CaseBlock, data_binding::Entity as DataBinding, + }, }; - diff --git a/crates/libs/entity/src/test/datatable.rs b/crates/libs/entity/src/test/datatable.rs index 193c704..a8a27e5 100644 --- a/crates/libs/entity/src/test/datatable.rs +++ b/crates/libs/entity/src/test/datatable.rs @@ -18,7 +18,7 @@ pub struct Model { pub app_id: Uuid, #[sea_orm(ignore)] - pub fields: Option> + pub fields: Option>, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -41,7 +41,6 @@ impl Related for Entity { } } - // `Related` trait has to be implemented by hand impl Related for Entity { fn to() -> RelationDef { diff --git a/crates/libs/entity/src/test/field.rs b/crates/libs/entity/src/test/field.rs index 8aa417b..b86e15c 100644 --- a/crates/libs/entity/src/test/field.rs +++ b/crates/libs/entity/src/test/field.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(5))", enum_name = "table_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(5))", + enum_name = "table_kind" +)] pub enum FieldDataKind { #[sea_orm(string_value = "S")] #[serde(rename = "S")] @@ -15,7 +19,7 @@ pub enum FieldDataKind { Int, #[sea_orm(string_value = "B")] #[serde(rename = "B")] - Bool + Bool, } #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] @@ -29,7 +33,7 @@ pub struct Model { pub table_id: i32, pub name: String, pub kind: FieldDataKind, - pub option: Option + pub option: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/crates/libs/entity/src/test/history.rs b/crates/libs/entity/src/test/history.rs new file mode 100644 index 0000000..29cfd33 --- /dev/null +++ b/crates/libs/entity/src/test/history.rs @@ -0,0 +1,72 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 + +use chrono::Utc; +use sea_orm::entity::prelude::*; +use sea_orm::EntityTrait; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(10))", + enum_name = "execution_type" +)] +pub enum ExecutionType { + #[sea_orm(string_value = "TestCase")] + #[serde(rename = "TestCase")] + TestCase, + #[sea_orm(string_value = "TestSuite")] + #[serde(rename = "TestSuite")] + TestSuite, +} + +#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(10))", + enum_name = "execution_kind" +)] +pub enum ExecutionKind { + #[sea_orm(string_value = "Scheduled")] + #[serde(rename = "Scheduled")] + Scheduled, + #[sea_orm(string_value = "Trigger")] + #[serde(rename = "Trigger")] + Trigger, +} + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] +#[sea_orm(table_name = "history")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub description: Option, + pub kind: ExecutionKind, + pub is_dry_run: bool, + pub reference: Uuid, + #[sea_orm(string_value = "type")] + #[serde(rename = "type")] + pub history_type: ExecutionType, + + pub args: Option, + pub triggered_by: Option, + pub triggered_on: Option>, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + // #[sea_orm( + // belongs_to = "super::datatable::Entity", + // from = "Column::TableId", + // to = "super::datatable::Column::Id" + // )] + // Table, +} + +// impl Related for Entity { +// fn to() -> RelationDef { +// Relation::Table.def() +// } +// } + +impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/test/mod.rs b/crates/libs/entity/src/test/mod.rs index c445da8..7ff88b6 100644 --- a/crates/libs/entity/src/test/mod.rs +++ b/crates/libs/entity/src/test/mod.rs @@ -1,4 +1,5 @@ -pub mod ui; pub mod datatable; pub mod field; -pub mod profile; \ No newline at end of file +pub mod history; +pub mod profile; +pub mod ui; diff --git a/crates/libs/entity/src/test/profile/data.rs b/crates/libs/entity/src/test/profile/data.rs index 1e08f2f..91c95ef 100644 --- a/crates/libs/entity/src/test/profile/data.rs +++ b/crates/libs/entity/src/test/profile/data.rs @@ -1,7 +1,5 @@ //! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - - use sea_orm::entity::prelude::*; use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; @@ -21,7 +19,6 @@ pub struct Model { pub profile_id: Uuid, } - #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( @@ -30,7 +27,6 @@ pub enum Relation { to = "super::profile::Column::Id" )] Profile, - } // `Related` trait has to be implemented by hand diff --git a/crates/libs/entity/src/test/profile/mod.rs b/crates/libs/entity/src/test/profile/mod.rs index 6c083b4..a62e8bd 100644 --- a/crates/libs/entity/src/test/profile/mod.rs +++ b/crates/libs/entity/src/test/profile/mod.rs @@ -1,2 +1,2 @@ pub mod data; -pub mod profile; \ No newline at end of file +pub mod profile; diff --git a/crates/libs/entity/src/test/profile/profile.rs b/crates/libs/entity/src/test/profile/profile.rs index b0eeaad..fefc725 100644 --- a/crates/libs/entity/src/test/profile/profile.rs +++ b/crates/libs/entity/src/test/profile/profile.rs @@ -1,7 +1,5 @@ //! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 - - use sea_orm::entity::prelude::*; use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; @@ -45,4 +43,4 @@ impl Related for Entity { } } -impl ActiveModelBehavior for ActiveModel {} \ No newline at end of file +impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/test/ui/action/action.rs b/crates/libs/entity/src/test/ui/action/action.rs index f0c050d..280afa5 100644 --- a/crates/libs/entity/src/test/ui/action/action.rs +++ b/crates/libs/entity/src/test/ui/action/action.rs @@ -8,7 +8,11 @@ use crate::prelude::target::ActionTargetKind; use crate::test::ui::action::data::ActionDataKind; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "action_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "action_kind" +)] pub enum ActionKind { #[sea_orm(string_value = "Click")] Click, @@ -44,7 +48,7 @@ pub struct Model { #[sea_orm(ignore)] pub data: Option, #[sea_orm(ignore)] - pub target: Option + pub target: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/crates/libs/entity/src/test/ui/action/data.rs b/crates/libs/entity/src/test/ui/action/data.rs index b10b8f5..d22b200 100644 --- a/crates/libs/entity/src/test/ui/action/data.rs +++ b/crates/libs/entity/src/test/ui/action/data.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "action_data_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "action_data_kind" +)] pub enum ActionDataKind { #[sea_orm(string_value = "Runtime")] Runtime, @@ -20,7 +24,7 @@ pub struct Model { pub id: Uuid, pub kind: ActionDataKind, pub value: String, - pub action_id: Uuid + pub action_id: Uuid, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -31,7 +35,6 @@ pub enum Relation { to = "super::action::Column::Id" )] Action, - } // `Related` trait has to be implemented by hand diff --git a/crates/libs/entity/src/test/ui/action/group.rs b/crates/libs/entity/src/test/ui/action/group.rs index 6cf0876..3445553 100644 --- a/crates/libs/entity/src/test/ui/action/group.rs +++ b/crates/libs/entity/src/test/ui/action/group.rs @@ -5,12 +5,16 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "action_group_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "action_group_kind" +)] pub enum ActionGroupKind { #[sea_orm(string_value = "ActionGroup")] ActionGroup, #[sea_orm(string_value = "Assertion")] - Assertion + Assertion, } #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] @@ -24,7 +28,7 @@ pub struct Model { #[sea_orm(column_name = "type")] pub type_field: ActionGroupKind, #[serde(skip_deserializing)] - pub app_id: Uuid + pub app_id: Uuid, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/crates/libs/entity/src/test/ui/action/mod.rs b/crates/libs/entity/src/test/ui/action/mod.rs index 0737f1d..608b447 100644 --- a/crates/libs/entity/src/test/ui/action/mod.rs +++ b/crates/libs/entity/src/test/ui/action/mod.rs @@ -1,5 +1,4 @@ - pub mod action; -pub mod target; pub mod data; pub mod group; +pub mod target; diff --git a/crates/libs/entity/src/test/ui/action/target.rs b/crates/libs/entity/src/test/ui/action/target.rs index 5dc8b48..0c4f292 100644 --- a/crates/libs/entity/src/test/ui/action/target.rs +++ b/crates/libs/entity/src/test/ui/action/target.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "action_target_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "action_target_kind" +)] pub enum ActionTargetKind { #[sea_orm(string_value = "Css")] Css, @@ -22,7 +26,7 @@ pub struct Model { pub id: Uuid, pub kind: ActionTargetKind, pub value: String, - pub action_id: Uuid + pub action_id: Uuid, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -33,7 +37,6 @@ pub enum Relation { to = "super::action::Column::Id" )] Action, - } // `Related` trait has to be implemented by hand diff --git a/crates/libs/entity/src/test/ui/case/case.rs b/crates/libs/entity/src/test/ui/case/case.rs index 1372e04..7c16307 100644 --- a/crates/libs/entity/src/test/ui/case/case.rs +++ b/crates/libs/entity/src/test/ui/case/case.rs @@ -12,7 +12,7 @@ pub struct Model { pub id: Uuid, pub name: String, pub description: Option, - + #[serde(skip_deserializing)] pub app_id: Uuid, @@ -24,7 +24,7 @@ pub struct Model { pub enum Relation { #[sea_orm(has_many = "super::case_block::Entity")] CaseBlock, - + #[sea_orm( belongs_to = "crate::app::app::Entity", from = "Column::AppId", diff --git a/crates/libs/entity/src/test/ui/case/case_block.rs b/crates/libs/entity/src/test/ui/case/case_block.rs index e2e8540..3b103aa 100644 --- a/crates/libs/entity/src/test/ui/case/case_block.rs +++ b/crates/libs/entity/src/test/ui/case/case_block.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "block_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "block_kind" +)] pub enum BlockKind { #[sea_orm(string_value = "Loop")] Loop, @@ -18,7 +22,11 @@ pub enum BlockKind { } #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "block_type")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "block_type" +)] pub enum BlockType { #[sea_orm(string_value = "InMemory")] InMemory, @@ -76,7 +84,6 @@ impl Related for Entity { impl ActiveModelBehavior for ActiveModel {} - pub struct SelfReferencingLink; impl Linked for SelfReferencingLink { diff --git a/crates/libs/entity/src/test/ui/case/data_binding.rs b/crates/libs/entity/src/test/ui/case/data_binding.rs index c8742fe..d48b0cd 100644 --- a/crates/libs/entity/src/test/ui/case/data_binding.rs +++ b/crates/libs/entity/src/test/ui/case/data_binding.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "data_binding_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "data_binding_kind" +)] pub enum DataBindingKind { #[sea_orm(string_value = "Data")] Data, diff --git a/crates/libs/entity/src/test/ui/case/mod.rs b/crates/libs/entity/src/test/ui/case/mod.rs index b045b13..3acf064 100644 --- a/crates/libs/entity/src/test/ui/case/mod.rs +++ b/crates/libs/entity/src/test/ui/case/mod.rs @@ -1,3 +1,3 @@ -pub mod data_binding; pub mod case; -pub mod case_block; \ No newline at end of file +pub mod case_block; +pub mod data_binding; diff --git a/crates/libs/entity/src/test/ui/elements.rs b/crates/libs/entity/src/test/ui/elements.rs index 793b9c0..2b3cf3e 100644 --- a/crates/libs/entity/src/test/ui/elements.rs +++ b/crates/libs/entity/src/test/ui/elements.rs @@ -7,7 +7,11 @@ use serde::{Deserialize, Serialize}; use crate::prelude::target::ActionTargetKind; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(5))", enum_name = "element_create_type")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(5))", + enum_name = "element_create_type" +)] pub enum ElementCreateType { #[sea_orm(string_value = "M")] Manual, @@ -29,7 +33,6 @@ pub struct Model { pub screen_id: i64, } - #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( @@ -47,9 +50,4 @@ impl Related for Entity { } } - - - - - impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/test/ui/mod.rs b/crates/libs/entity/src/test/ui/mod.rs index cb8c646..1e24055 100644 --- a/crates/libs/entity/src/test/ui/mod.rs +++ b/crates/libs/entity/src/test/ui/mod.rs @@ -1,5 +1,5 @@ -pub mod case; pub mod action; -pub mod suit; +pub mod case; pub mod elements; -pub mod screen; \ No newline at end of file +pub mod screen; +pub mod suit; diff --git a/crates/libs/entity/src/test/ui/screen.rs b/crates/libs/entity/src/test/ui/screen.rs index 9d157e4..49bfc61 100644 --- a/crates/libs/entity/src/test/ui/screen.rs +++ b/crates/libs/entity/src/test/ui/screen.rs @@ -15,5 +15,4 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} - impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/libs/entity/src/test/ui/suit/mod.rs b/crates/libs/entity/src/test/ui/suit/mod.rs index 66d6f17..6f1c38e 100644 --- a/crates/libs/entity/src/test/ui/suit/mod.rs +++ b/crates/libs/entity/src/test/ui/suit/mod.rs @@ -1,2 +1,2 @@ pub mod suite; -pub mod suite_block; \ No newline at end of file +pub mod suite_block; diff --git a/crates/libs/entity/src/test/ui/suit/suite.rs b/crates/libs/entity/src/test/ui/suit/suite.rs index 53edf9d..58f869d 100644 --- a/crates/libs/entity/src/test/ui/suit/suite.rs +++ b/crates/libs/entity/src/test/ui/suit/suite.rs @@ -18,7 +18,6 @@ pub struct Model { #[sea_orm(ignore)] pub suite_execution: Option, - } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -27,9 +26,9 @@ pub enum Relation { SuiteBlock, #[sea_orm( - belongs_to = "crate::app::app::Entity", - from = "Column::AppId", - to = "crate::app::app::Column::Id" + belongs_to = "crate::app::app::Entity", + from = "Column::AppId", + to = "crate::app::app::Column::Id" )] App, } diff --git a/crates/libs/entity/src/test/ui/suit/suite_block.rs b/crates/libs/entity/src/test/ui/suit/suite_block.rs index 280695a..b5a8a9e 100644 --- a/crates/libs/entity/src/test/ui/suit/suite_block.rs +++ b/crates/libs/entity/src/test/ui/suit/suite_block.rs @@ -5,7 +5,11 @@ use sea_orm::EntityTrait; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "block_kind")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "block_kind" +)] pub enum BlockKind { #[sea_orm(string_value = "Loop")] Loop, @@ -18,7 +22,11 @@ pub enum BlockKind { } #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] -#[sea_orm(rs_type = "String", db_type = "String(Some(15))", enum_name = "suit_block_type")] +#[sea_orm( + rs_type = "String", + db_type = "String(Some(15))", + enum_name = "suit_block_type" +)] pub enum SuiteBlockType { #[sea_orm(string_value = "TestCase")] TestCase, @@ -44,9 +52,9 @@ pub enum Relation { // #[sea_orm(belongs_to = "Entity", from = "Column::Id", to = "Column::ParentId")] // SelfReferencing, #[sea_orm( - belongs_to = "super::suite::Entity", - from = "Column::SuiteId", - to = "super::suite::Column::Id" + belongs_to = "super::suite::Entity", + from = "Column::SuiteId", + to = "super::suite::Column::Id" )] Suite, } diff --git a/crates/libs/migration/src/lib.rs b/crates/libs/migration/src/lib.rs index f8e0b53..bdc1071 100644 --- a/crates/libs/migration/src/lib.rs +++ b/crates/libs/migration/src/lib.rs @@ -3,14 +3,17 @@ pub use sea_orm_migration::prelude::*; mod migration001; mod migration002; mod migration003; +mod migration004; pub struct Migrator; #[async_trait::async_trait] impl MigratorTrait for Migrator { fn migrations() -> Vec> { - vec![Box::new(migration001::Migration), - Box::new(migration002::Migration), - Box::new(migration003::Migration)] + vec![ + Box::new(migration001::Migration), + Box::new(migration002::Migration), + Box::new(migration003::Migration), + ] } } diff --git a/crates/libs/migration/src/migration001.rs b/crates/libs/migration/src/migration001.rs index 410c235..f9af359 100644 --- a/crates/libs/migration/src/migration001.rs +++ b/crates/libs/migration/src/migration001.rs @@ -1,13 +1,16 @@ -use sea_orm_migration::prelude::*; use entity::admin::user; +use sea_orm_migration::prelude::*; +use crate::sea_orm::{ConnectionTrait, Statement}; use entity::app::app; use entity::command; use entity::prelude::{case, case_block, data_binding}; use entity::test::ui::action::{action, data, group as action_group, target}; -use entity::test::{profile::{data as profile_data, profile}, datatable, field}; use entity::test::ui::suit::{suite, suite_block}; -use crate::sea_orm::{ConnectionTrait, Statement}; +use entity::test::{ + datatable, field, + profile::{data as profile_data, profile}, +}; #[derive(DeriveMigrationName)] pub struct Migration; @@ -15,159 +18,278 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - //****************** Admin ****************** - - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(user::Entity) .if_not_exists() - .col(ColumnDef::new(user::Column::Id).integer().auto_increment().not_null().primary_key()) + .col( + ColumnDef::new(user::Column::Id) + .integer() + .auto_increment() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(user::Column::Name).string().not_null()) .col(ColumnDef::new(user::Column::FirstName).string().not_null()) .col(ColumnDef::new(user::Column::LastName).string()) .col(ColumnDef::new(user::Column::Email).string().not_null()) .to_owned(), - ).await?; + ) + .await?; //****************** Application ****************** - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(app::Entity) .if_not_exists() - .col(ColumnDef::new(app::Column::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(app::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(app::Column::Name).string().not_null()) .col(ColumnDef::new(app::Column::Description).string()) .to_owned(), - ).await?; + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(action_group::Entity) .if_not_exists() - .col(ColumnDef::new(action_group::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(action_group::Column::Name).string().not_null()) - .col(ColumnDef::new(action_group::Column::TypeField).string().not_null()) + .col( + ColumnDef::new(action_group::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(action_group::Column::Name) + .string() + .not_null(), + ) + .col( + ColumnDef::new(action_group::Column::TypeField) + .string() + .not_null(), + ) .col(ColumnDef::new(action_group::Column::Description).string()) - .col(ColumnDef::new(action_group::Column::AppId).uuid().not_null()) + .col( + ColumnDef::new(action_group::Column::AppId) + .uuid() + .not_null(), + ) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(action_group::Entity, action_group::Column::AppId) .to(app::Entity, app::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; - + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(action::Entity) .if_not_exists() - .col(ColumnDef::new(action::Column::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(action::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(action::Column::Kind).string().not_null()) - .col(ColumnDef::new(action::Column::ExecutionOrder).integer().not_null()) + .col( + ColumnDef::new(action::Column::ExecutionOrder) + .integer() + .not_null(), + ) .col(ColumnDef::new(action::Column::Description).string()) .col(ColumnDef::new(action::Column::TargetKind).string()) .col(ColumnDef::new(action::Column::TargetValue).string()) .col(ColumnDef::new(action::Column::DataKind).string()) .col(ColumnDef::new(action::Column::DataValue).string()) - .col(ColumnDef::new(action::Column::ActionGroupId).uuid().not_null()) + .col( + ColumnDef::new(action::Column::ActionGroupId) + .uuid() + .not_null(), + ) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(action::Entity, action::Column::ActionGroupId) .to(action_group::Entity, action_group::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(case::Entity) .if_not_exists() - .col(ColumnDef::new(case::Column::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(case::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(case::Column::Name).string().not_null()) .col(ColumnDef::new(case::Column::Description).string()) .col(ColumnDef::new(case::Column::AppId).uuid().not_null()) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(case::Entity, case::Column::AppId) .to(app::Entity, app::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(case_block::Entity) .if_not_exists() - .col(ColumnDef::new(case_block::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(case_block::Column::ExecutionOrder).integer().not_null()) - .col(ColumnDef::new(case_block::Column::TypeField).string().not_null()) + .col( + ColumnDef::new(case_block::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(case_block::Column::ExecutionOrder) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(case_block::Column::TypeField) + .string() + .not_null(), + ) .col(ColumnDef::new(case_block::Column::Kind).string().not_null()) .col(ColumnDef::new(case_block::Column::Reference).uuid()) .col(ColumnDef::new(case_block::Column::ParentId).uuid()) .col(ColumnDef::new(case_block::Column::CaseId).uuid().not_null()) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(case_block::Entity, case_block::Column::CaseId) .to(case::Entity, case::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(data_binding::Entity) .if_not_exists() - .col(ColumnDef::new(data_binding::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(data_binding::Column::Key).string().not_null()) - .col(ColumnDef::new(data_binding::Column::Value).string().not_null()) - .col(ColumnDef::new(data_binding::Column::Kind).string().not_null()) + .col( + ColumnDef::new(data_binding::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(data_binding::Column::Key) + .string() + .not_null(), + ) + .col( + ColumnDef::new(data_binding::Column::Value) + .string() + .not_null(), + ) + .col( + ColumnDef::new(data_binding::Column::Kind) + .string() + .not_null(), + ) .col(ColumnDef::new(data_binding::Column::BlockId).uuid()) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(data_binding::Entity, data_binding::Column::BlockId) .to(case_block::Entity, case_block::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; - + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(command::Entity) .if_not_exists() - .col(ColumnDef::new(command::Column::Id).integer().auto_increment().not_null().primary_key()) + .col( + ColumnDef::new(command::Column::Id) + .integer() + .auto_increment() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(command::Column::Kind).string().not_null()) - .col(ColumnDef::new(command::Column::TableName).string().not_null()) + .col( + ColumnDef::new(command::Column::TableName) + .string() + .not_null(), + ) .col(ColumnDef::new(command::Column::Command).string().not_null()) .to_owned(), - ).await?; - + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(datatable::Entity) .if_not_exists() - .col(ColumnDef::new(datatable::Column::Id).integer().not_null().primary_key().auto_increment()) + .col( + ColumnDef::new(datatable::Column::Id) + .integer() + .not_null() + .primary_key() + .auto_increment(), + ) .col(ColumnDef::new(datatable::Column::Name).string().not_null()) - .col(ColumnDef::new(datatable::Column::TableName).string().not_null()) + .col( + ColumnDef::new(datatable::Column::TableName) + .string() + .not_null(), + ) .col(ColumnDef::new(datatable::Column::Description).string()) .col(ColumnDef::new(datatable::Column::AppId).uuid().not_null()) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(datatable::Entity, datatable::Column::AppId) .to(app::Entity, app::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; + ) + .await?; - - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(field::Entity) .if_not_exists() .col(ColumnDef::new(field::Column::FieldId).string().not_null()) @@ -176,93 +298,153 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(field::Column::Kind).string().not_null()) .col(ColumnDef::new(field::Column::Option).json()) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(field::Entity, field::Column::TableId) .to(datatable::Entity, datatable::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; - manager.get_connection().execute( - Statement::from_string( + ) + .await?; + manager + .get_connection() + .execute(Statement::from_string( manager.get_database_backend(), - "alter table field add constraint com_key_id primary key (field_id, table_id)") - ) - .await?; - + "alter table field add constraint com_key_id primary key (field_id, table_id)", + )) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(profile::Entity) .if_not_exists() - .col(ColumnDef::new(profile::Column::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(profile::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(profile::Column::Name).string().not_null()) .col(ColumnDef::new(profile::Column::Description).string()) .col(ColumnDef::new(profile::Column::AppId).uuid().not_null()) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(profile::Entity, profile::Column::AppId) .to(app::Entity, app::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; - + ) + .await?; - manager.create_table(Table::create() + manager + .create_table( + Table::create() .table(profile_data::Entity) .if_not_exists() - .col(ColumnDef::new(profile_data::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(profile_data::Column::Key).string().not_null()) - .col(ColumnDef::new(profile_data::Column::Value).string().not_null()) - .col(ColumnDef::new(profile_data::Column::ValueType).string().not_null()) + .col( + ColumnDef::new(profile_data::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(profile_data::Column::Key) + .string() + .not_null(), + ) + .col( + ColumnDef::new(profile_data::Column::Value) + .string() + .not_null(), + ) + .col( + ColumnDef::new(profile_data::Column::ValueType) + .string() + .not_null(), + ) .col(ColumnDef::new(profile_data::Column::Description).string()) - .col(ColumnDef::new(profile_data::Column::ProfileId).uuid().not_null()) + .col( + ColumnDef::new(profile_data::Column::ProfileId) + .uuid() + .not_null(), + ) .foreign_key( - ForeignKey::create() + ForeignKey::create() .from(profile_data::Entity, profile_data::Column::ProfileId) .to(profile::Entity, profile::Column::Id) .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), ) .to_owned(), - ).await?; + ) + .await?; - manager.create_table(Table::create() - .table(suite::Entity) - .if_not_exists() - .col(ColumnDef::new(suite::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(suite::Column::Name).string().not_null()) - .col(ColumnDef::new(suite::Column::Description).string()) - .col(ColumnDef::new(suite::Column::AppId).uuid().not_null()) - .foreign_key( - ForeignKey::create() - .from(suite::Entity, suite::Column::AppId) - .to(app::Entity, app::Column::Id) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) - ) - .to_owned(), - ).await?; + manager + .create_table( + Table::create() + .table(suite::Entity) + .if_not_exists() + .col( + ColumnDef::new(suite::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(suite::Column::Name).string().not_null()) + .col(ColumnDef::new(suite::Column::Description).string()) + .col(ColumnDef::new(suite::Column::AppId).uuid().not_null()) + .foreign_key( + ForeignKey::create() + .from(suite::Entity, suite::Column::AppId) + .to(app::Entity, app::Column::Id) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await?; - manager.create_table(Table::create() - .table(suite_block::Entity) - .if_not_exists() - .col(ColumnDef::new(suite_block::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(suite_block::Column::ExecutionOrder).integer().not_null()) - .col(ColumnDef::new(suite_block::Column::TypeField).string().not_null()) - .col(ColumnDef::new(suite_block::Column::Reference).uuid()) - .col(ColumnDef::new(suite_block::Column::SuiteId).uuid().not_null()) - .foreign_key( - ForeignKey::create() - .from(suite_block::Entity, suite_block::Column::SuiteId) - .to(case::Entity, case::Column::Id) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) - ) - .to_owned(), - ).await?; + manager + .create_table( + Table::create() + .table(suite_block::Entity) + .if_not_exists() + .col( + ColumnDef::new(suite_block::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(suite_block::Column::ExecutionOrder) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(suite_block::Column::TypeField) + .string() + .not_null(), + ) + .col(ColumnDef::new(suite_block::Column::Reference).uuid()) + .col( + ColumnDef::new(suite_block::Column::SuiteId) + .uuid() + .not_null(), + ) + .foreign_key( + ForeignKey::create() + .from(suite_block::Entity, suite_block::Column::SuiteId) + .to(case::Entity, case::Column::Id) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await?; // manager.create_table(Table::create() // .table(target::Entity) @@ -301,14 +483,28 @@ impl MigrationTrait for Migration { } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager.drop_table(Table::drop().table(app::Entity).to_owned()).await?; - manager.drop_table(Table::drop().table(case::Entity).to_owned()).await?; - manager.drop_table(Table::drop().table(case_block::Entity).to_owned()).await?; - manager.drop_table(Table::drop().table(data_binding::Entity).to_owned()).await?; + manager + .drop_table(Table::drop().table(app::Entity).to_owned()) + .await?; + manager + .drop_table(Table::drop().table(case::Entity).to_owned()) + .await?; + manager + .drop_table(Table::drop().table(case_block::Entity).to_owned()) + .await?; + manager + .drop_table(Table::drop().table(data_binding::Entity).to_owned()) + .await?; - manager.drop_table(Table::drop().table(action::Entity).to_owned()).await?; - manager.drop_table(Table::drop().table(target::Entity).to_owned()).await?; - manager.drop_table(Table::drop().table(data::Entity).to_owned()).await?; + manager + .drop_table(Table::drop().table(action::Entity).to_owned()) + .await?; + manager + .drop_table(Table::drop().table(target::Entity).to_owned()) + .await?; + manager + .drop_table(Table::drop().table(data::Entity).to_owned()) + .await?; Ok(()) } diff --git a/crates/libs/migration/src/migration002.rs b/crates/libs/migration/src/migration002.rs index 258ed79..6bd27b4 100644 --- a/crates/libs/migration/src/migration002.rs +++ b/crates/libs/migration/src/migration002.rs @@ -4,16 +4,16 @@ use sea_orm_migration::prelude::*; use sea_orm_migration::sea_orm::ActiveValue::Set; use entity::app::app; -use entity::prelude::{case, case_block}; use entity::prelude::case_block::{BlockKind, BlockType}; use entity::prelude::group::ActionGroupKind; use entity::prelude::target::ActionTargetKind; -use entity::test::ui::action::{action, group as action_group}; +use entity::prelude::{case, case_block}; use entity::test::ui::action::action::ActionKind; use entity::test::ui::action::data::ActionDataKind; +use entity::test::ui::action::{action, group as action_group}; -use crate::sea_orm::{ActiveModelTrait, EntityTrait, InsertResult}; use crate::sea_orm::prelude::Uuid; +use crate::sea_orm::{ActiveModelTrait, EntityTrait, InsertResult}; #[derive(DeriveMigrationName)] pub struct Migration; @@ -33,8 +33,11 @@ impl MigrationTrait for Migration { let action_g_am = action_group::ActiveModel { id: Set(Uuid::new_v4()), name: Set("Wikipedia Searching".to_string()), - description: Set(Option::from("This is Seeding application \ - the will be created on application start".to_string())), + description: Set(Option::from( + "This is Seeding application \ + the will be created on application start" + .to_string(), + )), type_field: Set(ActionGroupKind::ActionGroup), app_id: Set(app.id.clone()), }; @@ -50,7 +53,9 @@ impl MigrationTrait for Migration { execution_order: Set(1), action_group_id: Set(app_g.clone().id), ..Default::default() - }.insert(db).await?, + } + .insert(db) + .await?, action::ActiveModel { id: Set(Uuid::new_v4()), description: Set(Some("Search for Ana de Armas".to_string())), @@ -62,51 +67,56 @@ impl MigrationTrait for Migration { execution_order: Set(2), action_group_id: Set(app_g.clone().id), ..Default::default() - }.insert(db).await?, + } + .insert(db) + .await?, action::ActiveModel { id: Set(Uuid::new_v4()), description: Set(Some("Search".to_string())), kind: Set(ActionKind::Click), target_kind: Set(Some(ActionTargetKind::Xpath)), - target_value: Set(Some("//form[@id='search-form']/fieldset/button/i".to_string())), + target_value: Set(Some( + "//form[@id='search-form']/fieldset/button/i".to_string(), + )), execution_order: Set(3), action_group_id: Set(app_g.clone().id), ..Default::default() - }.insert(db).await? + } + .insert(db) + .await?, ]; // let _action_m: InsertResult = // action::Entity::insert_many(action_ms).exec(db).await?; /// check assert - let assert_g_am = action_group::ActiveModel { id: Set(Uuid::new_v4()), name: Set("Wikipedia Assert".to_string()), - description: Set(Option::from("This is Seeding application \ - the will be created on application start".to_string())), + description: Set(Option::from( + "This is Seeding application \ + the will be created on application start" + .to_string(), + )), type_field: Set(ActionGroupKind::Assertion), app_id: Set(app.clone().id), }; let assert_g_m: action_group::Model = assert_g_am.insert(db).await?; - - let assert_action_ms = vec![ - action::ActiveModel { - id: Set(Uuid::new_v4()), - description: Set(Option::from("Verify the title".to_string())), - kind: Set(ActionKind::VerifyText), - data_kind: Set(Some(ActionDataKind::Static)), - data_value: Set(Some("Ana de Armas".to_string())), - target_kind: Set(Some(ActionTargetKind::Xpath)), - target_value: Set(Some("//*[@id='search-form']/fieldset/button".to_string())), - execution_order: Set(1), - action_group_id: Set(assert_g_m.clone().id), - ..Default::default() - } - ]; + let assert_action_ms = vec![action::ActiveModel { + id: Set(Uuid::new_v4()), + description: Set(Option::from("Verify the title".to_string())), + kind: Set(ActionKind::VerifyText), + data_kind: Set(Some(ActionDataKind::Static)), + data_value: Set(Some("Ana de Armas".to_string())), + target_kind: Set(Some(ActionTargetKind::Xpath)), + target_value: Set(Some("//*[@id='search-form']/fieldset/button".to_string())), + execution_order: Set(1), + action_group_id: Set(assert_g_m.clone().id), + ..Default::default() + }]; let _assert_action_m: InsertResult = - action::Entity::insert_many(assert_action_ms).exec(db).await?; - - + action::Entity::insert_many(assert_action_ms) + .exec(db) + .await?; let case_am = case::ActiveModel { id: Set(Uuid::new_v4()), @@ -117,7 +127,7 @@ impl MigrationTrait for Migration { let case_m: case::Model = case_am.insert(db).await?; let case_blocks = vec![ - case_block::ActiveModel{ + case_block::ActiveModel { id: Set(Uuid::new_v4()), execution_order: Set(1), kind: Set(BlockKind::Reference), @@ -125,8 +135,10 @@ impl MigrationTrait for Migration { reference: Set(Some(app_g.clone().id)), case_id: Set(case_m.clone().id), ..Default::default() - }.insert(db).await?, - case_block::ActiveModel{ + } + .insert(db) + .await?, + case_block::ActiveModel { id: Set(Uuid::new_v4()), execution_order: Set(2), kind: Set(BlockKind::Reference), @@ -134,7 +146,9 @@ impl MigrationTrait for Migration { reference: Set(Some(assert_g_m.clone().id)), case_id: Set(case_m.clone().id), ..Default::default() - }.insert(db).await?, + } + .insert(db) + .await?, ]; Ok(()) } diff --git a/crates/libs/migration/src/migration003.rs b/crates/libs/migration/src/migration003.rs index c305417..d555cd1 100644 --- a/crates/libs/migration/src/migration003.rs +++ b/crates/libs/migration/src/migration003.rs @@ -9,44 +9,82 @@ pub struct Migration; impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { //****************** Tag ****************** - manager.create_table(Table::create() - .table(tag::Entity) - .if_not_exists() - .col(ColumnDef::new(tag::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(tag::Column::Name).string().not_null()) - .col(ColumnDef::new(tag::Column::TagType).string().not_null()) - .to_owned(), - ).await?; + manager + .create_table( + Table::create() + .table(tag::Entity) + .if_not_exists() + .col( + ColumnDef::new(tag::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(tag::Column::Name).string().not_null()) + .col(ColumnDef::new(tag::Column::TagType).string().not_null()) + .to_owned(), + ) + .await?; //****************** Tag Entity Mapping ****************** - manager.create_table(Table::create() - .table(tag_entity::Entity) - .if_not_exists() - .col(ColumnDef::new(tag_entity::Column::Id).uuid().not_null().primary_key()) - .col(ColumnDef::new(tag_entity::Column::TagId).uuid().not_null()) - .col(ColumnDef::new(tag_entity::Column::EntityId).uuid().not_null()) - .col(ColumnDef::new(tag_entity::Column::EntityType).string().not_null()) - .to_owned(), - ).await?; - + manager + .create_table( + Table::create() + .table(tag_entity::Entity) + .if_not_exists() + .col( + ColumnDef::new(tag_entity::Column::Id) + .uuid() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(tag_entity::Column::TagId).uuid().not_null()) + .col( + ColumnDef::new(tag_entity::Column::EntityId) + .uuid() + .not_null(), + ) + .col( + ColumnDef::new(tag_entity::Column::EntityType) + .string() + .not_null(), + ) + .to_owned(), + ) + .await?; //****************** Application ****************** - manager.create_table(Table::create() - .table(attachment::Entity) - .if_not_exists() - .col(ColumnDef::new(attachment::Column::Id).integer().not_null().primary_key().auto_increment()) - .col(ColumnDef::new(attachment::Column::Name).string()) - .col(ColumnDef::new(attachment::Column::Desc).string().not_null()) - .col(ColumnDef::new(attachment::Column::Category).string().not_null()) - .col(ColumnDef::new(attachment::Column::Path).string().not_null()) - .col(ColumnDef::new(attachment::Column::ReferenceId).uuid()) - .col(ColumnDef::new(attachment::Column::Attachment).binary()) - .to_owned(), - ).await?; + manager + .create_table( + Table::create() + .table(attachment::Entity) + .if_not_exists() + .col( + ColumnDef::new(attachment::Column::Id) + .integer() + .not_null() + .primary_key() + .auto_increment(), + ) + .col(ColumnDef::new(attachment::Column::Name).string()) + .col(ColumnDef::new(attachment::Column::Desc).string().not_null()) + .col( + ColumnDef::new(attachment::Column::Category) + .string() + .not_null(), + ) + .col(ColumnDef::new(attachment::Column::Path).string().not_null()) + .col(ColumnDef::new(attachment::Column::ReferenceId).uuid()) + .col(ColumnDef::new(attachment::Column::Attachment).binary()) + .to_owned(), + ) + .await?; Ok(()) } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager.drop_table(Table::drop().table(attachment::Entity).to_owned()).await?; + manager + .drop_table(Table::drop().table(attachment::Entity).to_owned()) + .await?; Ok(()) } } diff --git a/crates/libs/migration/src/migration004.rs b/crates/libs/migration/src/migration004.rs new file mode 100644 index 0000000..272a707 --- /dev/null +++ b/crates/libs/migration/src/migration004.rs @@ -0,0 +1,60 @@ +use sea_orm_migration::prelude::*; + +use entity::test::history; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + //****************** Tag ****************** + manager + .create_table( + Table::create() + .table(history::Entity) + .if_not_exists() + .col( + ColumnDef::new(history::Column::Id) + .integer() + .auto_increment() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(history::Column::Description).string()) + .col(ColumnDef::new(history::Column::Kind).string().not_null()) + .col( + ColumnDef::new(history::Column::HistoryType) + .string() + .not_null(), + ) + .col( + ColumnDef::new(history::Column::IsDryRun) + .boolean() + .not_null(), + ) + .col(ColumnDef::new(history::Column::Args).json()) + .col(ColumnDef::new(history::Column::Reference).uuid()) + .col( + ColumnDef::new(history::Column::TriggeredOn) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(history::Column::TriggeredBy) + .date_time() + .not_null(), + ) + .to_owned(), + ) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(history::Entity).to_owned()) + .await?; + Ok(()) + } +} diff --git a/crates/services/api/src/error.rs b/crates/services/api/src/error.rs index c8cf9be..7be583f 100644 --- a/crates/services/api/src/error.rs +++ b/crates/services/api/src/error.rs @@ -4,9 +4,8 @@ use axum::response::{IntoResponse, Response}; use sea_orm::DbErr; use serde_json::{Error as SerdeJsonError, json}; use thiserror::Error; -use crate::error::OrcaError::RepoError; -// pub type OrcaResult = InternalResult; +use crate::error::OrcaError::RepoError; pub type InternalResult = Result; @@ -26,7 +25,7 @@ pub enum OrcaError { /// Something went wrong when calling the user repo. DataBaseError(DbErr), RepoError(OrcaRepoError), - SerializerError(SerdeJsonError) + SerializerError(SerdeJsonError), } /// This makes it possible to use `?` to automatically convert a `DbErr` @@ -56,16 +55,13 @@ impl From for OrcaError { impl IntoResponse for OrcaError { fn into_response(self) -> Response { let (status, error_message) = match self { - OrcaError::DataBaseError(err) =>{ - (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) - } - OrcaError::SerializerError(err) => { - (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) - } - RepoError(err) => { - (StatusCode::NOT_FOUND, err.to_string()) - } - _ => (StatusCode::INTERNAL_SERVER_ERROR, "Internal Error Not Specify".to_string()) + OrcaError::DataBaseError(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()), + OrcaError::SerializerError(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()), + RepoError(err) => (StatusCode::NOT_FOUND, err.to_string()), + _ => ( + StatusCode::INTERNAL_SERVER_ERROR, + "Internal Error Not Specify".to_string(), + ), }; let body = Json(json!({ @@ -74,4 +70,4 @@ impl IntoResponse for OrcaError { (status, body).into_response() } -} \ No newline at end of file +} diff --git a/crates/services/api/src/main.rs b/crates/services/api/src/main.rs index d9a6984..609e029 100644 --- a/crates/services/api/src/main.rs +++ b/crates/services/api/src/main.rs @@ -7,31 +7,37 @@ use cerium::client::Client; use cerium::server::App; use migration::MigratorTrait; -use crate::server::middleware::OrcaLayer; use crate::route::handle_router; +use crate::server::middleware::OrcaLayer; -pub(crate) mod route; pub(crate) mod error; -pub(crate) mod service; +pub(crate) mod route; pub(crate) mod server; +pub(crate) mod service; pub(crate) mod utils; - pub(crate) async fn run_migration(db: &DatabaseConnection) -> Result<(), DbErr> { - migration::Migrator::up(db, None).await.expect("TODO: panic message"); + migration::Migrator::up(db, None) + .await + .expect("TODO: panic message"); Ok(()) } - #[tokio::main] async fn main() { - let cli = Client::new(Some("postgres://root:root@localhost:5432/orca".to_string()), None).await; + let cli = Client::new( + Some("postgres://root:root@localhost:5432/orca".to_string()), + None, + ) + .await; let mut app = App::new("OrcaWeb", cli.clone()); app.set_logger(Level::DEBUG); app.set_port(8080); run_migration(cli.db()).await.expect("TODO: panic message"); - let routers = handle_router().layer(OrcaLayer { db: Arc::new(cli.db.clone()) }); + let routers = handle_router().layer(OrcaLayer { + db: Arc::new(cli.db.clone()), + }); app.set_router(routers); app.run().await; } diff --git a/crates/services/api/src/route/admin/user.rs b/crates/services/api/src/route/admin/user.rs index 161ce2a..ce5aca0 100644 --- a/crates/services/api/src/route/admin/user.rs +++ b/crates/services/api/src/route/admin/user.rs @@ -1,10 +1,10 @@ -use axum::{Extension, Json, Router}; use axum::extract::{Path, Query}; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post}; -use sea_orm::{IntoActiveModel}; +use axum::{Extension, Json, Router}; use sea_orm::ActiveValue::Set; +use sea_orm::IntoActiveModel; use serde_json::json; use tracing::info; @@ -18,36 +18,50 @@ use crate::service::admin::user::UserService; pub(crate) fn user_route() -> Router { Router::new() .route("/", post(create_user).get(list_user)) - .route("/:user_id",get(get_user_by_id) - .put(update_user_by_id) - .delete(delete_user_by_id) + .route( + "/:user_id", + get(get_user_by_id) + .put(update_user_by_id) + .delete(delete_user_by_id), ) } - - /// create_user - this will create new User in Orca -async fn create_user(Extension(session): Extension, Json(body): Json) -> InternalResult { - let result = UserService::new(session).create_user(body.into_active_model()).await?; - Ok((StatusCode::CREATED, Json(result))) +async fn create_user( + Extension(session): Extension, + Json(body): Json, +) -> InternalResult { + let result = UserService::new(session) + .create_user(body.into_active_model()) + .await?; + Ok((StatusCode::CREATED, Json(result))) } - /// list_user - this will list User in Orca -async fn list_user(Extension(session): Extension, page: Option>) -> InternalResult { +async fn list_user( + Extension(session): Extension, + page: Option>, +) -> InternalResult { let _page = page.unwrap_or_default().0; let result = UserService::new(session).list_users(_page).await?; Ok(Json(result)) } /// get_user - this will get User by ID in Orca -async fn get_user_by_id(Extension(session): Extension, Path(user_id): Path) -> InternalResult { +async fn get_user_by_id( + Extension(session): Extension, + Path(user_id): Path, +) -> InternalResult { let result = UserService::new(session).get_user_by_id(user_id).await?; Ok(Json(result)) } /// update_user_by_id - update user by user ID in Orca -async fn update_user_by_id(Extension(session): Extension, Path(user_id): Path, Json(body): Json) -> InternalResult { +async fn update_user_by_id( + Extension(session): Extension, + Path(user_id): Path, + Json(body): Json, +) -> InternalResult { let mut _user = body.clone().into_active_model(); _user.id = Set(user_id); let result = UserService::new(session).update_user(_user).await?; @@ -56,8 +70,10 @@ async fn update_user_by_id(Extension(session): Extension, Path(user } /// delete_user_by_id - delete user by User by ID in Orca -async fn delete_user_by_id(Extension(session): Extension, Path(user_id): Path) -> InternalResult { +async fn delete_user_by_id( + Extension(session): Extension, + Path(user_id): Path, +) -> InternalResult { UserService::new(session).delete_user_by_id(user_id).await?; Ok(Json(json!({"status": "success"}))) } - diff --git a/crates/services/api/src/route/app/action.rs b/crates/services/api/src/route/app/action.rs index 3e0de2b..25d9907 100644 --- a/crates/services/api/src/route/app/action.rs +++ b/crates/services/api/src/route/app/action.rs @@ -1,8 +1,8 @@ -use axum::{Extension, Json, Router}; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post, put}; +use axum::{Extension, Json, Router}; use sea_orm::prelude::Uuid; use serde_json::json; @@ -17,43 +17,59 @@ pub(crate) fn action_route() -> Router { Router::new() .route("/", get(get_action).post(create_action)) .route("/batch", post(batch_update_action)) - .route("/:action_id",put(update_action).delete(delete_action)) + .route("/:action_id", put(update_action).delete(delete_action)) } /// get_action - list all the Action Group in Specific Application in the Orca Application -async fn get_action(Extension(session): Extension, - Path((_app_id, group_id)): Path<(Uuid, Uuid)>) -> InternalResult { +async fn get_action( + Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>, +) -> InternalResult { let result = ActionService::new(session).get_actions(group_id).await?; Ok(Json(result)) } - /// create_action - this will create new Action Group in Application Application in Orca -async fn create_action(Extension(session): Extension, Path((_app_id, group_id)): Path<(Uuid, Uuid)>, - Json(body): Json) -> InternalResult { - let result = ActionService::new(session).create_action(group_id, body).await?; +async fn create_action( + Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>, + Json(body): Json, +) -> InternalResult { + let result = ActionService::new(session) + .create_action(group_id, body) + .await?; Ok((StatusCode::CREATED, Json(result))) } /// batch_update_action - This will update batch Action Group in Application in Orca -async fn batch_update_action(Extension(session): Extension, - Path((_app_id, group_id)): Path<(Uuid, Uuid)>, - Json(body): Json>) -> InternalResult { - let response = ActionService::new(session).batch_update_action(group_id, body).await?; +async fn batch_update_action( + Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>, + Json(body): Json>, +) -> InternalResult { + let response = ActionService::new(session) + .batch_update_action(group_id, body) + .await?; Ok(Json(response)) } /// update_action - this will create new Application in Orca -async fn update_action(Extension(session): Extension, - Path((_app_id, _group_id, action_id)): Path<(Uuid, Uuid, Uuid)>, - Json(body): Json) -> InternalResult { - let result = ActionService::new(session).update_action(action_id, body).await?; +async fn update_action( + Extension(session): Extension, + Path((_app_id, _group_id, action_id)): Path<(Uuid, Uuid, Uuid)>, + Json(body): Json, +) -> InternalResult { + let result = ActionService::new(session) + .update_action(action_id, body) + .await?; Ok(Json(result)) } /// delete_action - this will delete Action for Action Group in Application in Orca -async fn delete_action(Extension(session): Extension, - Path((_app_id, _group_id, action_id)): Path<(Uuid, Uuid, Uuid)>) -> InternalResult { +async fn delete_action( + Extension(session): Extension, + Path((_app_id, _group_id, action_id)): Path<(Uuid, Uuid, Uuid)>, +) -> InternalResult { ActionService::new(session).delete_action(action_id).await?; Ok(Json(json!({"status": "success"}))) } diff --git a/crates/services/api/src/route/app/case.rs b/crates/services/api/src/route/app/case.rs index 56d3015..aa6c61b 100644 --- a/crates/services/api/src/route/app/case.rs +++ b/crates/services/api/src/route/app/case.rs @@ -1,12 +1,11 @@ - -use axum::{Extension, Json, Router}; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post}; -use uuid::Uuid; +use axum::{Extension, Json, Router}; use entity::prelude::case::Model; use entity::prelude::case_block::Model as BlockModel; +use uuid::Uuid; use crate::error::InternalResult; use crate::server::session::OrcaSession; @@ -16,66 +15,80 @@ use crate::service::app::case::CaseService; pub(crate) fn test_case_route() -> Router { Router::new() .route("/", get(list_cases).post(create_case)) - .nest("/:case_id", - Router::new() - .route("/detail", get(get_case_info)) - .route("/run", post(dry_run)) - .nest( - "/block", - Router::new() - .route("/batch", post(update_block)) - .route("/", post(insert_block)) - ) + .nest( + "/:case_id", + Router::new() + .route("/detail", get(get_case_info)) + .route("/run", post(dry_run)) + .nest( + "/block", + Router::new() + .route("/batch", post(update_block)) + .route("/", post(insert_block)), + ), ) - } /// list_cases - list all the Case that is Bind with Current Application -async fn list_cases(Extension(session): Extension, - Path(app_id): Path) -> InternalResult { +async fn list_cases( + Extension(session): Extension, + Path(app_id): Path, +) -> InternalResult { let result = CaseService::new(session, app_id).list_cases().await?; Ok(Json(result)) } - /// create_case - This will New Test Case for the specific Application in Orca -async fn create_case(Extension(session): Extension, Path(app_id): Path, - Json(body): Json) -> InternalResult { +async fn create_case( + Extension(session): Extension, + Path(app_id): Path, + Json(body): Json, +) -> InternalResult { let result = CaseService::new(session, app_id).create_case(body).await?; Ok((StatusCode::CREATED, Json(result))) } - /// get_case_info - Get Case Info and the batch information with the list of block -async fn get_case_info(Extension(session): Extension, - Path((app_id, case_id)): Path<(Uuid, Uuid)>) -> InternalResult { - let result = CaseService::new(session, app_id).get_case_info(case_id).await?; +async fn get_case_info( + Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>, +) -> InternalResult { + let result = CaseService::new(session, app_id) + .get_case_info(case_id) + .await?; Ok(Json(result)) } - /// dry_run - Dry run the Test case -async fn dry_run(Extension(session): Extension, - Path((app_id, case_id)): Path<(Uuid, Uuid)>) -> InternalResult { +async fn dry_run( + Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>, +) -> InternalResult { let result = CaseService::new(session, app_id).run(case_id).await?; Ok(Json(result)) } - /// update_block - update test case Block -async fn update_block(Extension(session): Extension, - Path((app_id, case_id)): Path<(Uuid, Uuid)>, - Json(body): Json>) -> InternalResult { - let result = CaseService::new(session, app_id).batch_update_case_block(case_id, body).await?; +async fn update_block( + Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>, + Json(body): Json>, +) -> InternalResult { + let result = CaseService::new(session, app_id) + .batch_update_case_block(case_id, body) + .await?; Ok(Json(result)) } - /// insert_block - This will Append New Block to the code for spe -async fn insert_block(Extension(session): Extension, - Path((app_id, case_id)): Path<(Uuid, Uuid)>, - Json(body): Json) -> InternalResult { - let result = CaseService::new(session, app_id).push_block(case_id, body, None, None).await?; +async fn insert_block( + Extension(session): Extension, + Path((app_id, case_id)): Path<(Uuid, Uuid)>, + Json(body): Json, +) -> InternalResult { + let result = CaseService::new(session, app_id) + .push_block(case_id, body, None, None) + .await?; Ok(Json(result)) } @@ -86,4 +99,3 @@ async fn insert_block(Extension(session): Extension, // let result = CaseService::new(session, app_id).push_block(case_id, body, None).await?; // Ok(Json(result)) // } - diff --git a/crates/services/api/src/route/app/datatable.rs b/crates/services/api/src/route/app/datatable.rs index 927a235..22219c5 100644 --- a/crates/services/api/src/route/app/datatable.rs +++ b/crates/services/api/src/route/app/datatable.rs @@ -1,8 +1,8 @@ -use axum::{Extension, Json, Router}; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post}; +use axum::{Extension, Json, Router}; use sea_orm::prelude::Uuid; use serde_json::{json, Value}; use tracing::debug; @@ -18,93 +18,131 @@ use crate::service::app::datatable::{DatatableService, TableDataRequest}; pub(crate) fn datatable_route() -> Router { Router::new() .route("/", get(list_datatables).post(create_datatable)) - .nest("/:table_id", - Router::new() - .route("/batch", post(update_value)) - .route("/data/batch", post(update_value).get(get_data)) - .route("/field", post(create_field)) - .route("/", get(get_datatable).delete(delete_table).post(update_data)) - .route("/field/:field_id", post(delete_field)) + .nest( + "/:table_id", + Router::new() + .route("/batch", post(update_value)) + .route("/data/batch", post(update_value).get(get_data)) + .route("/field", post(create_field)) + .route( + "/", + get(get_datatable).delete(delete_table).post(update_data), + ) + .route("/field/:field_id", post(delete_field)), ) - } /// list_datatables - list all the DataTable in Specific Application -async fn list_datatables(Extension(session): Extension, - Path((app_id)): Path) -> InternalResult { - let result = DatatableService::new(session, app_id).list_datatables().await?; +async fn list_datatables( + Extension(session): Extension, + Path((app_id)): Path, +) -> InternalResult { + let result = DatatableService::new(session, app_id) + .list_datatables() + .await?; Ok(Json(result)) } - /// create_datatable - this will create new Datatable in Application -async fn create_datatable(Extension(session): Extension, Path(app_id): Path, - Json(body): Json) -> InternalResult { - let result = DatatableService::new(session, app_id).create_datatable(body).await?; +async fn create_datatable( + Extension(session): Extension, + Path(app_id): Path, + Json(body): Json, +) -> InternalResult { + let result = DatatableService::new(session, app_id) + .create_datatable(body) + .await?; Ok((StatusCode::CREATED, Json(result))) } /// get_datatable - Get the Basic Information for Datatable -async fn get_datatable(Extension(session): Extension, - Path((app_id, table_id)): Path<(Uuid, i32)>) -> InternalResult { - - let result = DatatableService::new(session, app_id).get_datatable_info(table_id).await?; +async fn get_datatable( + Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, +) -> InternalResult { + let result = DatatableService::new(session, app_id) + .get_datatable_info(table_id) + .await?; Ok(Json(result)) } - /// create_field - this will create field in Application -async fn create_field(Extension(session): Extension, Path((app_id, table_id)): Path<(Uuid, i32)>, - Json(body): Json) -> InternalResult { - let result = DatatableService::new(session, app_id).create_new_field(table_id, body).await?; +async fn create_field( + Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json, +) -> InternalResult { + let result = DatatableService::new(session, app_id) + .create_new_field(table_id, body) + .await?; Ok((StatusCode::CREATED, Json(result))) } - /// delete_field - this will delete field in Application -async fn delete_field(Extension(session): Extension, - Path((app_id, table_id, field_id)): Path<(Uuid, i32, String)>) - -> InternalResult { - DatatableService::new(session, app_id).drop_field(table_id, field_id).await?; +async fn delete_field( + Extension(session): Extension, + Path((app_id, table_id, field_id)): Path<(Uuid, i32, String)>, +) -> InternalResult { + DatatableService::new(session, app_id) + .drop_field(table_id, field_id) + .await?; Ok((StatusCode::NO_CONTENT, Json(json!({"status": "success"})))) } /// update_value - batch update the data in Datatable in Application -async fn update_value(Extension(session): Extension, - Path((app_id, table_id)): Path<(Uuid, i32)>, - Json(body): Json>) -> InternalResult { - DatatableService::new(session, app_id).batch_update_data(table_id, body).await?; +async fn update_value( + Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json>, +) -> InternalResult { + DatatableService::new(session, app_id) + .batch_update_data(table_id, body) + .await?; Ok(Json(json!({"status": "success"}))) } /// get_data - get data for specify Datatable in Application -async fn get_data(Extension(session): Extension, - Path((app_id, table_id)): Path<(Uuid, i32)>) -> InternalResult { - let response = DatatableService::new(session, app_id).get_data(table_id).await?; +async fn get_data( + Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, +) -> InternalResult { + let response = DatatableService::new(session, app_id) + .get_data(table_id) + .await?; Ok(Json(response)) } - /// update_data - update data for specify Datatable in Application -async fn update_data(Extension(session): Extension, - Path((app_id, table_id)): Path<(Uuid, i32)>, - Json(body): Json) -> InternalResult { - let response = DatatableService::new(session, app_id).update_data(table_id, body).await?; +async fn update_data( + Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json, +) -> InternalResult { + let response = DatatableService::new(session, app_id) + .update_data(table_id, body) + .await?; Ok(Json(response)) } - /// update_data - update data for specify Datatable in Application -async fn delete_table(Extension(session): Extension, - Path((app_id, table_id)): Path<(Uuid, i32)>) -> InternalResult { - let response = DatatableService::new(session, app_id).delete_table(table_id).await?; +async fn delete_table( + Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, +) -> InternalResult { + let response = DatatableService::new(session, app_id) + .delete_table(table_id) + .await?; Ok(Json(response)) } /// update_table - update data for specify Datatable in Application -async fn update_table(Extension(session): Extension, - Path((app_id, table_id)): Path<(Uuid, i32)>, - Json(body): Json) -> InternalResult { - let response = DatatableService::new(session, app_id).delete_table(table_id).await?; +async fn update_table( + Extension(session): Extension, + Path((app_id, table_id)): Path<(Uuid, i32)>, + Json(body): Json, +) -> InternalResult { + let response = DatatableService::new(session, app_id) + .delete_table(table_id) + .await?; Ok(Json(response)) } diff --git a/crates/services/api/src/route/app/group.rs b/crates/services/api/src/route/app/group.rs index 2f2fd2c..900d90a 100644 --- a/crates/services/api/src/route/app/group.rs +++ b/crates/services/api/src/route/app/group.rs @@ -1,8 +1,8 @@ -use axum::{Extension, Json, Router}; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, put}; +use axum::{Extension, Json, Router}; use sea_orm::prelude::Uuid; use entity::prelude::group::Model; @@ -15,34 +15,50 @@ use crate::service::app::group::GroupService; pub(crate) fn group_route() -> Router { Router::new() .route("/", get(get_groups).post(create_group)) - .route("/:group_id",put(update_action_group).delete(delete_action_group)) + .route( + "/:group_id", + put(update_action_group).delete(delete_action_group), + ) } /// get_groups - list all the Action Group in Specific Application in the Orca Application -async fn get_groups(Extension(session): Extension, - Path(app_id): Path) -> InternalResult { +async fn get_groups( + Extension(session): Extension, + Path(app_id): Path, +) -> InternalResult { let result = GroupService::new(session).get_groups(app_id).await?; Ok(Json(result)) } /// create_group - This will create new Action Group in Application in Orca -async fn create_group(Extension(session): Extension, Path(app_id): Path, - Json(body): Json) -> InternalResult { - let result = GroupService::new(session).create_group(app_id, body).await?; +async fn create_group( + Extension(session): Extension, + Path(app_id): Path, + Json(body): Json, +) -> InternalResult { + let result = GroupService::new(session) + .create_group(app_id, body) + .await?; Ok((StatusCode::CREATED, Json(result))) } /// update_action_group - this will create new Application in Orca -async fn update_action_group(Extension(session): Extension, - Path((_app_id, group_id)): Path<(Uuid, Uuid)>, - Json(body): Json) -> InternalResult { - let result = GroupService::new(session).update_action_group(group_id, body).await?; +async fn update_action_group( + Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>, + Json(body): Json, +) -> InternalResult { + let result = GroupService::new(session) + .update_action_group(group_id, body) + .await?; Ok(Json(result)) } /// delete_action_group - this will delete Action Group in Application Application in Orca -async fn delete_action_group(Extension(session): Extension, - Path((_app_id, group_id)): Path<(Uuid, Uuid)>) -> InternalResult { +async fn delete_action_group( + Extension(session): Extension, + Path((_app_id, group_id)): Path<(Uuid, Uuid)>, +) -> InternalResult { let result = GroupService::new(session).delete_group(group_id).await?; Ok(Json(result)) } diff --git a/crates/services/api/src/route/app/mod.rs b/crates/services/api/src/route/app/mod.rs index 3fa758a..d3c9236 100644 --- a/crates/services/api/src/route/app/mod.rs +++ b/crates/services/api/src/route/app/mod.rs @@ -1,8 +1,8 @@ -use axum::{Extension, Json, Router}; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, put}; +use axum::{Extension, Json, Router}; use uuid::Uuid; use entity::app::app::Model; @@ -18,12 +18,11 @@ use crate::server::session::OrcaSession; use crate::service::app::AppService; pub(crate) mod action; +pub(crate) mod case; +pub(crate) mod datatable; pub(crate) mod group; pub(crate) mod profile; -pub(crate) mod datatable; pub(crate) mod suit; -pub(crate) mod case; - pub fn app_route() -> Router { Router::new() @@ -34,31 +33,15 @@ pub fn app_route() -> Router { .route("/", put(update_app)) .nest( "/group", - group_route() - .merge( - Router::new().nest("/:group_id/action", action_route()) - ) - ) - .nest( - "/profile", - profile_route() - ) - .nest( - "/datatable", - datatable_route() - ) - .nest( - "/case", - test_case_route() - ) - .nest( - "/suite", - suite_route() + group_route().merge(Router::new().nest("/:group_id/action", action_route())), ) + .nest("/profile", profile_route()) + .nest("/datatable", datatable_route()) + .nest("/case", test_case_route()) + .nest("/suite", suite_route()), ) } - /// get_app - list all the Application in the Orca Application async fn get_app(Extension(session): Extension) -> InternalResult { println!("Heelo"); @@ -66,17 +49,20 @@ async fn get_app(Extension(session): Extension) -> InternalResult, - Json(body): Json) -> InternalResult { +async fn create_app( + Extension(session): Extension, + Json(body): Json, +) -> InternalResult { let result = AppService::new(session).create_app(body).await?; Ok((StatusCode::CREATED, Json(result))) } /// update_app - this will update Application in Orca -async fn update_app(Extension(session): Extension, - Path(_app_id): Path, - Json(body): Json) -> InternalResult { +async fn update_app( + Extension(session): Extension, + Path(_app_id): Path, + Json(body): Json, +) -> InternalResult { Ok(Json(body)) } diff --git a/crates/services/api/src/route/app/profile.rs b/crates/services/api/src/route/app/profile.rs index 2936b75..8a6a925 100644 --- a/crates/services/api/src/route/app/profile.rs +++ b/crates/services/api/src/route/app/profile.rs @@ -1,13 +1,11 @@ - -use axum::{Extension, Json, Router}; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{delete, get, post, put}; +use axum::{Extension, Json, Router}; +use entity::test::profile::profile::Model; use sea_orm::prelude::Uuid; use serde_json::json; -use entity::test::profile::profile::Model; - use crate::error::InternalResult; use crate::server::session::OrcaSession; @@ -17,49 +15,66 @@ use crate::service::app::profile::ProfileService; pub(crate) fn profile_route() -> Router { Router::new() .route("/", get(list_profile).post(create_profile)) - .nest("/:profile_id", - Router::new() - .route("/", put(update_profile).delete(delete_profile)) - .route("/data/batch", delete(update_profile)) - .route("/data/{data_id}", delete(delete_profile_data)) - + .nest( + "/:profile_id", + Router::new() + .route("/", put(update_profile).delete(delete_profile)) + .route("/data/batch", delete(update_profile)) + .route("/data/{data_id}", delete(delete_profile_data)), ) } /// list_profile - list all the Profile that is Binded with Current Application -async fn list_profile(Extension(session): Extension, - Path(app_id): Path) -> InternalResult { +async fn list_profile( + Extension(session): Extension, + Path(app_id): Path, +) -> InternalResult { let result = ProfileService::new(session, app_id).list_profile().await?; Ok(Json(result)) } - /// create_profile - This will New Profile for the specific Application in Orca -async fn create_profile(Extension(session): Extension, Path(app_id): Path, - Json(body): Json) -> InternalResult { - let result = ProfileService::new(session, app_id).create_profile(body).await?; +async fn create_profile( + Extension(session): Extension, + Path(app_id): Path, + Json(body): Json, +) -> InternalResult { + let result = ProfileService::new(session, app_id) + .create_profile(body) + .await?; Ok((StatusCode::CREATED, Json(result))) } /// update_profile - this will update the existing profile information in Orca -async fn update_profile(Extension(session): Extension, - Path((app_id, profile_id)): Path<(Uuid, Uuid)>, - Json(body): Json) -> InternalResult { - let result = ProfileService::new(session, app_id).update_profile(profile_id, body).await?; +async fn update_profile( + Extension(session): Extension, + Path((app_id, profile_id)): Path<(Uuid, Uuid)>, + Json(body): Json, +) -> InternalResult { + let result = ProfileService::new(session, app_id) + .update_profile(profile_id, body) + .await?; Ok(Json(result)) } /// delete_profile - this will delete existing profile in Application Application in Orca -async fn delete_profile(Extension(session): Extension, - Path((app_id, profile_id)): Path<(Uuid, Uuid)>) -> InternalResult { - let result = ProfileService::new(session, app_id).delete_profile(profile_id).await?; +async fn delete_profile( + Extension(session): Extension, + Path((app_id, profile_id)): Path<(Uuid, Uuid)>, +) -> InternalResult { + let _result = ProfileService::new(session, app_id) + .delete_profile(profile_id) + .await?; Ok(Json(json!({"status": "success"}))) } /// delete_profile_data - this will delete existing profile data in Application Application in Orca -async fn delete_profile_data(Extension(session): Extension, - Path((app_id, profile_id, data_id)): Path<(Uuid, Uuid, Uuid)>) -> InternalResult { - let result = ProfileService::new(session, app_id).delete_profile_data(data_id).await?; +async fn delete_profile_data( + Extension(session): Extension, + Path((app_id, _profile_id, data_id)): Path<(Uuid, Uuid, Uuid)>, +) -> InternalResult { + let _result = ProfileService::new(session, app_id) + .delete_profile_data(data_id) + .await?; Ok(Json(json!({"status": "success"}))) } - diff --git a/crates/services/api/src/route/app/suit.rs b/crates/services/api/src/route/app/suit.rs index 4a4d2e4..0a28863 100644 --- a/crates/services/api/src/route/app/suit.rs +++ b/crates/services/api/src/route/app/suit.rs @@ -165,15 +165,14 @@ // Ok(HttpResponse::NoContent().finish()) // } - -use axum::{Extension, Json, Router}; use axum::extract::Path; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post}; -use uuid::Uuid; +use axum::{Extension, Json, Router}; use entity::test::ui::suit::suite::Model; use entity::test::ui::suit::suite_block::Model as BlockModel; +use uuid::Uuid; use crate::error::InternalResult; use crate::server::session::OrcaSession; @@ -183,54 +182,67 @@ use crate::service::app::suit::SuitService; pub(crate) fn suite_route() -> Router { Router::new() .route("/", get(list_suites).post(create_suite)) - .nest("/:suite_id", - Router::new() - .route("/batch/update", post(update_block)) - .nest( - "/block", - Router::new() - .route("/", get(get_suite_info).post(insert_block)) - ) + .nest( + "/:suite_id", + Router::new() + .route("/batch/update", post(update_block)) + .nest( + "/block", + Router::new().route("/", get(get_suite_info).post(insert_block)), + ), ) - } /// list_suites - list all the Suites that is Bind with Current Application -async fn list_suites(Extension(session): Extension, - Path(app_id): Path) -> InternalResult { +async fn list_suites( + Extension(session): Extension, + Path(app_id): Path, +) -> InternalResult { let result = SuitService::new(session, app_id).list_suites().await?; Ok(Json(result)) } - /// create_profile - This will New Profile for the specific Application in Orca -async fn create_suite(Extension(session): Extension, Path(app_id): Path, - Json(body): Json) -> InternalResult { +async fn create_suite( + Extension(session): Extension, + Path(app_id): Path, + Json(body): Json, +) -> InternalResult { let result = SuitService::new(session, app_id).create_suit(body).await?; Ok((StatusCode::CREATED, Json(result))) } - /// get_suits_info - Get Suite Info and the batch information with the list of block -async fn get_suite_info(Extension(session): Extension, - Path((app_id, suite_id)): Path<(Uuid, Uuid)>) -> InternalResult { - let result = SuitService::new(session, app_id).get_suite_info(suite_id).await?; +async fn get_suite_info( + Extension(session): Extension, + Path((app_id, suite_id)): Path<(Uuid, Uuid)>, +) -> InternalResult { + let result = SuitService::new(session, app_id) + .get_suite_info(suite_id) + .await?; Ok(Json(result)) } /// insert_block - This will Append New Block to the code for spe -async fn insert_block(Extension(session): Extension, - Path((app_id, suite_id)): Path<(Uuid, Uuid)>, - Json(body): Json) -> InternalResult { - let result = SuitService::new(session, app_id).push_block(suite_id, body, None).await?; +async fn insert_block( + Extension(session): Extension, + Path((app_id, suite_id)): Path<(Uuid, Uuid)>, + Json(body): Json, +) -> InternalResult { + let result = SuitService::new(session, app_id) + .push_block(suite_id, body, None) + .await?; Ok(Json(result)) } - /// update_block - update suite Block -async fn update_block(Extension(session): Extension, - Path((app_id, suite_id)): Path<(Uuid, Uuid)>, - Json(body): Json>) -> InternalResult { - let result = SuitService::new(session, app_id).batch_update_suite_block(suite_id, body).await?; +async fn update_block( + Extension(session): Extension, + Path((app_id, suite_id)): Path<(Uuid, Uuid)>, + Json(body): Json>, +) -> InternalResult { + let result = SuitService::new(session, app_id) + .batch_update_suite_block(suite_id, body) + .await?; Ok(Json(result)) } diff --git a/crates/services/api/src/route/mod.rs b/crates/services/api/src/route/mod.rs index a990777..fe86379 100644 --- a/crates/services/api/src/route/mod.rs +++ b/crates/services/api/src/route/mod.rs @@ -1,10 +1,10 @@ +use crate::route::public::local_route; use axum::Router; use serde::Deserialize; -use crate::route::public::local_route; -pub(crate) mod public; pub(crate) mod admin; pub(crate) mod app; +pub(crate) mod public; fn v1_route() -> Router { Router::new() @@ -12,7 +12,6 @@ fn v1_route() -> Router { .nest("/app", app::app_route()) } - pub fn handle_router() -> Router { let api_routes = Router::new().nest("/v1", v1_route()); let routes = Router::new() @@ -34,14 +33,13 @@ impl Pagination { pub fn limit(&self) -> u64 { self.limit } - } impl Default for Pagination { fn default() -> Self { Self { offset: 1, - limit: 10 + limit: 10, } } -} \ No newline at end of file +} diff --git a/crates/services/api/src/route/public.rs b/crates/services/api/src/route/public.rs index 8bb8e3b..c05c09d 100644 --- a/crates/services/api/src/route/public.rs +++ b/crates/services/api/src/route/public.rs @@ -1,12 +1,12 @@ -use axum::Router; use axum::response::IntoResponse; use axum::routing::get; +use axum::Router; -pub fn local_route() -> Router<> { +pub fn local_route() -> Router { Router::new().route("/ping", get(health_checker_handler)) } async fn health_checker_handler() -> impl IntoResponse { const MESSAGE: &str = "Pong"; MESSAGE -} \ No newline at end of file +} diff --git a/crates/services/api/src/server/middleware/mod.rs b/crates/services/api/src/server/middleware/mod.rs index d164e49..440880a 100644 --- a/crates/services/api/src/server/middleware/mod.rs +++ b/crates/services/api/src/server/middleware/mod.rs @@ -1,27 +1,29 @@ use std::sync::Arc; use std::task::{Context, Poll}; +use crate::server::session::OrcaSession; use axum::{async_trait, extract::Request, response::Response}; use futures::executor::block_on; use futures_util::future::BoxFuture; use sea_orm::{DatabaseConnection, TransactionTrait}; use tower::{Layer, Service}; use tracing::info; -use crate::server::session::OrcaSession; pub mod orca; - #[derive(Clone)] pub struct OrcaLayer { - pub db: Arc + pub db: Arc, } impl Layer for OrcaLayer { type Service = OrcaMiddleware; fn layer(&self, inner: S) -> Self::Service { - OrcaMiddleware { db: self.db.clone(), inner } + OrcaMiddleware { + db: self.db.clone(), + inner, + } } } @@ -59,4 +61,4 @@ where Ok(response) }) } -} \ No newline at end of file +} diff --git a/crates/services/api/src/server/middleware/orca.rs b/crates/services/api/src/server/middleware/orca.rs index e69de29..8b13789 100644 --- a/crates/services/api/src/server/middleware/orca.rs +++ b/crates/services/api/src/server/middleware/orca.rs @@ -0,0 +1 @@ + diff --git a/crates/services/api/src/server/mod.rs b/crates/services/api/src/server/mod.rs index 7322c0b..06508e5 100644 --- a/crates/services/api/src/server/mod.rs +++ b/crates/services/api/src/server/mod.rs @@ -1,2 +1,2 @@ -pub(crate) mod session; pub(crate) mod middleware; +pub(crate) mod session; diff --git a/crates/services/api/src/server/session.rs b/crates/services/api/src/server/session.rs index 4838361..c48f44d 100644 --- a/crates/services/api/src/server/session.rs +++ b/crates/services/api/src/server/session.rs @@ -1,16 +1,13 @@ use sea_orm::DatabaseTransaction; - #[derive(Clone)] pub struct OrcaSession(DatabaseTransaction); impl OrcaSession { - pub fn new(trx: DatabaseTransaction) -> Self{ + pub fn new(trx: DatabaseTransaction) -> Self { OrcaSession(trx) } pub fn trx(&self) -> &DatabaseTransaction { &self.0 } - } - diff --git a/crates/services/api/src/service/admin/mod.rs b/crates/services/api/src/service/admin/mod.rs index 41e4ecf..68a79f5 100644 --- a/crates/services/api/src/service/admin/mod.rs +++ b/crates/services/api/src/service/admin/mod.rs @@ -1 +1 @@ -pub(crate) mod user; \ No newline at end of file +pub(crate) mod user; diff --git a/crates/services/api/src/service/admin/user.rs b/crates/services/api/src/service/admin/user.rs index 1d94b52..3333e6f 100644 --- a/crates/services/api/src/service/admin/user.rs +++ b/crates/services/api/src/service/admin/user.rs @@ -1,10 +1,12 @@ -use sea_orm::{ActiveModelTrait, DatabaseTransaction, EntityTrait, NotSet, QuerySelect, TryIntoModel}; -use tracing::info; -use entity::admin::user; -use entity::admin::user::{ActiveModel, Model}; use crate::error::{InternalResult, OrcaRepoError}; use crate::route::Pagination; use crate::server::session::OrcaSession; +use entity::admin::user; +use entity::admin::user::{ActiveModel, Model}; +use sea_orm::{ + ActiveModelTrait, DatabaseTransaction, EntityTrait, NotSet, QuerySelect, TryIntoModel, +}; +use tracing::info; pub(crate) struct UserService(OrcaSession); @@ -25,15 +27,20 @@ impl UserService { pub async fn list_users(&self, page: Pagination) -> InternalResult> { let users = user::Entity::find() - .offset((page.offset() - 1) * page.limit()).limit(page.limit()) - .all(self.trx()).await?; + .offset((page.offset() - 1) * page.limit()) + .limit(page.limit()) + .all(self.trx()) + .await?; Ok(users) } pub async fn get_user_by_id(&self, id: i32) -> InternalResult { let user = user::Entity::find_by_id(id).one(self.trx()).await?; - if user.is_none(){ - return Err(OrcaRepoError::ModelNotFound("User".to_string(), id.to_string()))?; + if user.is_none() { + return Err(OrcaRepoError::ModelNotFound( + "User".to_string(), + id.to_string(), + ))?; } return Ok(user.unwrap()); } @@ -46,10 +53,15 @@ impl UserService { pub async fn delete_user_by_id(&self, id: i32) -> InternalResult<()> { let result = user::Entity::delete_by_id(id).exec(self.trx()).await?; if result.rows_affected == 0 { - return Err(OrcaRepoError::ModelNotFound("User".to_string(), id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "User".to_string(), + id.to_string(), + ))?; } - info!("User Got deleted - {:?}, status - {:?}", id, result.rows_affected); + info!( + "User Got deleted - {:?}, status - {:?}", + id, result.rows_affected + ); return Ok(()); } - -} \ No newline at end of file +} diff --git a/crates/services/api/src/service/app/action.rs b/crates/services/api/src/service/app/action.rs index a5b3843..d287e5b 100644 --- a/crates/services/api/src/service/app/action.rs +++ b/crates/services/api/src/service/app/action.rs @@ -1,6 +1,9 @@ -use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, NotSet, QueryFilter, QueryOrder, TryIntoModel}; -use sea_orm::ActiveValue::Set; use sea_orm::prelude::Uuid; +use sea_orm::ActiveValue::Set; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, NotSet, + QueryFilter, QueryOrder, TryIntoModel, +}; use sea_query::Expr; use tracing::info; @@ -23,8 +26,11 @@ impl ActionService { /// get_actions - list all the Action Group in Specific Application in the Orca Application pub async fn get_actions(&self, group_id: Uuid) -> InternalResult> { - let actions = action::Entity::find().filter(action::Column::ActionGroupId.eq(group_id)) - .order_by_asc(action::Column::ExecutionOrder).all(self.trx()).await?; + let actions = action::Entity::find() + .filter(action::Column::ActionGroupId.eq(group_id)) + .order_by_asc(action::Column::ExecutionOrder) + .all(self.trx()) + .await?; Ok(actions) } @@ -39,9 +45,14 @@ impl ActionService { /// update_action - this will update existing Action in Application in Orca pub async fn update_action(&self, action_id: Uuid, mut action: Model) -> InternalResult { - let mut _action = action::Entity::find_by_id(action_id).one(self.trx()).await?; + let mut _action = action::Entity::find_by_id(action_id) + .one(self.trx()) + .await?; if _action.is_none() { - return Err(OrcaRepoError::ModelNotFound("Action".to_string(), action_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Action".to_string(), + action_id.to_string(), + ))?; } let exist_action = _action.unwrap(); let mut action = action.into_active_model(); @@ -51,36 +62,49 @@ impl ActionService { Ok(result) } - /// delete_action - this will delete Action for Action Group in Application in Orca pub async fn delete_action(&self, action_id: Uuid) -> InternalResult<()> { - let action = action::Entity::find_by_id(action_id).one(self.trx()).await?; + let action = action::Entity::find_by_id(action_id) + .one(self.trx()) + .await?; if action.is_none() { - return Err(OrcaRepoError::ModelNotFound("Action".to_string(), action_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Action".to_string(), + action_id.to_string(), + ))?; } let _action = action.unwrap(); let action_obj: action::ActiveModel = _action.into(); let action_order = action_obj.clone().execution_order.unwrap(); action_obj.delete(self.trx()).await?; let update_result = action::Entity::update_many() - .col_expr(action::Column::ExecutionOrder, Expr::expr(Expr::col(action::Column::ExecutionOrder).if_null(0)).add(1)) + .col_expr( + action::Column::ExecutionOrder, + Expr::expr(Expr::col(action::Column::ExecutionOrder).if_null(0)).add(1), + ) .filter(action::Column::ExecutionOrder.gt(action_order)) .exec(self.trx()) .await?; - info!("Updated the Action which have execution order gt {:?}, count - {:?}", action_order, update_result.rows_affected); + info!( + "Updated the Action which have execution order gt {:?}, count - {:?}", + action_order, update_result.rows_affected + ); Ok(()) } /// batch_update_action - This will update batch Action Group in Application in Orca - pub async fn batch_update_action(&self, group_id: Uuid, mut actions: Vec) -> InternalResult> { + pub async fn batch_update_action( + &self, + group_id: Uuid, + mut actions: Vec, + ) -> InternalResult> { let mut result: Vec = vec![]; for item in actions { - let mut _item = item.into_active_model().reset_all(); + let mut _item = item.into_active_model().reset_all(); info!("For Input update for {:?}", _item); - let item =_item.save(self.trx()).await?.try_into_model()?; - result.push( item); + let item = _item.save(self.trx()).await?.try_into_model()?; + result.push(item); } Ok(result) } - } diff --git a/crates/services/api/src/service/app/case.rs b/crates/services/api/src/service/app/case.rs index 93af954..4f08e9c 100644 --- a/crates/services/api/src/service/app/case.rs +++ b/crates/services/api/src/service/app/case.rs @@ -1,13 +1,19 @@ -use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, QuerySelect, TryIntoModel}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, + QueryOrder, QuerySelect, TryIntoModel, +}; use sea_orm::ActiveValue::Set; use sea_query::{Condition, Expr}; use tracing::{debug, info}; use uuid::Uuid; + use cerium::client::driver::web::WebDriver; use engine::controller::case::CaseController; - use entity::prelude::case::{Column, Entity, Model}; -use entity::prelude::case_block::{ActiveModel as BlockActiveModel, Column as BlockColumn, Entity as BlockEntity, Model as BlockModel}; +use entity::prelude::case_block::{ + ActiveModel as BlockActiveModel, Column as BlockColumn, Entity as BlockEntity, + Model as BlockModel, +}; use crate::error::{InternalResult, OrcaRepoError}; use crate::server::session::OrcaSession; @@ -25,9 +31,11 @@ impl CaseService { /// list all the test suites in the Orca Application pub(crate) async fn list_cases(&self) -> InternalResult> { - let cases = Entity::find().filter(Column::AppId.eq(self.1)) + let cases = Entity::find() + .filter(Column::AppId.eq(self.1)) .order_by_asc(Column::Name) - .all(self.trx()).await?; + .all(self.trx()) + .await?; Ok(cases) } @@ -44,38 +52,58 @@ impl CaseService { pub async fn get_case_info(&self, case_id: Uuid) -> InternalResult { let case = Entity::find_by_id(case_id).one(self.trx()).await?; if case.is_none() { - return Err(OrcaRepoError::ModelNotFound("Test Case".to_string(), case_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Test Case".to_string(), + case_id.to_string(), + ))?; } let mut case = case.unwrap(); - let case_blocks = BlockEntity::find().filter(BlockColumn::CaseId.eq(case_id)) - .order_by_asc(BlockColumn::ExecutionOrder).all(self.trx()).await?; + let case_blocks = BlockEntity::find() + .filter(BlockColumn::CaseId.eq(case_id)) + .order_by_asc(BlockColumn::ExecutionOrder) + .all(self.trx()) + .await?; case.case_execution = Some(serde_json::to_value(case_blocks)?); Ok(case) } /// batch_update_case_block - update Case Block - pub async fn batch_update_case_block(&self, case_id: Uuid, - mut body: Vec) -> InternalResult<()> { - let case_blocks : Vec = body.into_iter().map(|mut block| { - block.case_id = case_id.clone(); - block.into_active_model() - }).collect(); + pub async fn batch_update_case_block( + &self, + case_id: Uuid, + mut body: Vec, + ) -> InternalResult<()> { + let case_blocks: Vec = body + .into_iter() + .map(|mut block| { + block.case_id = case_id.clone(); + block.into_active_model() + }) + .collect(); let blocks = BlockEntity::insert_many(case_blocks) - .exec(self.trx()).await?; + .exec(self.trx()) + .await?; Ok(()) } /// update_case_block - this will update the single case block - async fn update_case_block(&self, case_id: Uuid, case_block_id: Uuid, - mut body: BlockModel) -> InternalResult { + async fn update_case_block( + &self, + _case_id: Uuid, + case_block_id: Uuid, + body: BlockModel, + ) -> InternalResult { let case_block = BlockEntity::find_by_id(case_block_id) - .one(self.trx()).await?; + .one(self.trx()) + .await?; if case_block.is_none() { - return Err(OrcaRepoError::ModelNotFound("Test Case Block".to_string(), case_block_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Test Case Block".to_string(), + case_block_id.to_string(), + ))?; } let mut _block = case_block.unwrap().into_active_model(); _block.kind = Set(body.kind.to_owned()); - // _block.execution_order = Set(body.execution_order.to_owned()); _block.type_field = Set(body.type_field.to_owned()); _block.reference = Set(body.reference.to_owned()); _block.parent_id = Set(body.parent_id.to_owned()); @@ -85,10 +113,12 @@ impl CaseService { /// run - this will run the single tes case pub async fn run(&self, case_id: Uuid) -> InternalResult<()> { - let case = Entity::find_by_id(case_id) - .one(self.trx()).await?; + let case = Entity::find_by_id(case_id).one(self.trx()).await?; if case.is_none() { - return Err(OrcaRepoError::ModelNotFound("Test Case".to_string(), case_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Test Case".to_string(), + case_id.to_string(), + ))?; } let ui_driver = WebDriver::default().await.expect("error"); @@ -101,21 +131,27 @@ impl CaseService { } /// push_into_index - This will Append New Block to the code for spe - async fn push_into_index(&self, case_id: Uuid, mut body: BlockModel, - parent: Option, index: Option) -> InternalResult { - + async fn push_into_index( + &self, + case_id: Uuid, + mut body: BlockModel, + parent: Option, + index: Option, + ) -> InternalResult { let mut _filter = Condition::all().add(BlockColumn::CaseId.eq(case_id)); if parent.is_some() { _filter = _filter.add(BlockColumn::ParentId.eq(parent.unwrap())); } - let _index : i32 = match index { + let _index: i32 = match index { Some(x) => x, _ => { let mut i = 1; - let blocks = BlockEntity::find().filter(_filter.clone()) - .all(self.trx()).await?; + let blocks = BlockEntity::find() + .filter(_filter.clone()) + .all(self.trx()) + .await?; if let Some(b) = blocks.last() { i = b.execution_order + 1; } @@ -125,11 +161,14 @@ impl CaseService { _filter = _filter.add(BlockColumn::ExecutionOrder.gte(index)); let update_result = BlockEntity::update_many() - .col_expr(BlockColumn::ExecutionOrder, Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1)) + .col_expr( + BlockColumn::ExecutionOrder, + Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1), + ) .filter(_filter) .exec(self.trx()) .await?; - + info!(" Updated result - {:?}", update_result.rows_affected); body.id = Uuid::new_v4(); body.case_id = case_id; let _case = body.clone().into_active_model(); @@ -139,31 +178,41 @@ impl CaseService { } /// push_block - This will Append New Case - pub(crate) async fn push_block(&self, case_id: Uuid, mut body: BlockModel, - index: Option, parent: Option) -> InternalResult { - + pub(crate) async fn push_block( + &self, + case_id: Uuid, + mut body: BlockModel, + index: Option, + parent: Option, + ) -> InternalResult { let mut _filter = Condition::all().add(BlockColumn::CaseId.eq(case_id)); if parent.is_some() { _filter = _filter.add(BlockColumn::ParentId.eq(parent.unwrap())); } - let blocks = BlockEntity::find().filter(_filter.clone()) - .order_by_desc(BlockColumn::ExecutionOrder).limit(1) - .all(self.trx()).await?; + let blocks = BlockEntity::find() + .filter(_filter.clone()) + .order_by_desc(BlockColumn::ExecutionOrder) + .limit(1) + .all(self.trx()) + .await?; let mut last_index = 1; if let Some(last_item) = blocks.last() { last_index = last_item.execution_order + 1; } - let _index : i32 = match index { + let _index: i32 = match index { Some(x) => { - let i = if x > last_index { last_index } else {x}; + let i = if x > last_index { last_index } else { x }; i - }, - _ => last_index + } + _ => last_index, }; _filter = _filter.add(BlockColumn::ExecutionOrder.gte(_index)); let update_result = BlockEntity::update_many() - .col_expr(BlockColumn::ExecutionOrder, Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1)) + .col_expr( + BlockColumn::ExecutionOrder, + Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1), + ) .filter(_filter) .exec(self.trx()) .await?; @@ -175,5 +224,4 @@ impl CaseService { let result = _case.insert(self.trx()).await?; Ok(result) } - } diff --git a/crates/services/api/src/service/app/datatable.rs b/crates/services/api/src/service/app/datatable.rs index 1bb9392..a715281 100644 --- a/crates/services/api/src/service/app/datatable.rs +++ b/crates/services/api/src/service/app/datatable.rs @@ -1,11 +1,17 @@ use chrono::Utc; use futures_util::StreamExt; -use sea_orm::{ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseBackend, DatabaseTransaction, EntityTrait, IntoActiveModel, JsonValue, ModelTrait, NotSet, QueryFilter, QueryOrder, QueryResult, Statement, TryIntoModel}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseBackend, DatabaseTransaction, + EntityTrait, IntoActiveModel, JsonValue, ModelTrait, NotSet, QueryFilter, QueryOrder + , Statement, TryIntoModel, +}; use sea_orm::ActiveValue::Set; use sea_orm_migration::SchemaManager; -use sea_query::{Alias, Asterisk, ColumnDef, Condition, Expr, Order, PostgresQueryBuilder, Query, Table}; +use sea_query::{ + Alias, Asterisk, ColumnDef, Condition, Expr, Order, PostgresQueryBuilder, Query, Table, +}; use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; +use serde_json::Value; use tracing::info; use uuid::Uuid; @@ -20,7 +26,7 @@ use crate::utils::replace_special_chars; pub(crate) struct TableDataRequest { pub row_id: i32, pub field_id: String, - pub data: String + pub data: String, } pub(crate) struct DatatableService(OrcaSession, Uuid); @@ -36,8 +42,11 @@ impl DatatableService { /// list_datatables - list all the DataTable in Specific Application in the Orca pub async fn list_datatables(&self) -> InternalResult> { - let tables = Entity::find().filter(Column::AppId.eq(self.1)) - .order_by_asc(Column::Name).all(self.trx()).await?; + let tables = Entity::find() + .filter(Column::AppId.eq(self.1)) + .order_by_asc(Column::Name) + .all(self.trx()) + .await?; Ok(tables) } @@ -45,12 +54,14 @@ impl DatatableService { pub async fn get_datatable(&self, id: i32) -> InternalResult { let tables = Entity::find_by_id(id).one(self.trx()).await?; if tables.is_none() { - return Err(OrcaRepoError::ModelNotFound("Datatable".to_string(), id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Datatable".to_string(), + id.to_string(), + ))?; } Ok(tables.unwrap()) } - /// get_datatable - Get the datatable by id in application pub async fn get_datatable_info(&self, id: i32) -> InternalResult { let mut table = self.get_datatable(id).await?; @@ -59,7 +70,6 @@ impl DatatableService { Ok(table) } - /// create_datatable - this will create new DataTable in Application in Orca pub async fn create_datatable(&self, mut table: Model) -> InternalResult { table.app_id = self.1; @@ -67,14 +77,24 @@ impl DatatableService { let mut _table = table.into_active_model(); _table.id = NotSet; let result = _table.insert(self.trx()).await?; - let stm = format!(r#"CREATE TABLE IF NOT EXISTS {} (id SERIAL NOT NULL PRIMARY KEY )"#, result.table_name); - let exec_res= self.trx().execute(Statement::from_string(DatabaseBackend::Postgres, stm)).await?; + let stm = format!( + r#"CREATE TABLE IF NOT EXISTS {} (id SERIAL NOT NULL PRIMARY KEY )"#, + result.table_name + ); + let exec_res = self + .trx() + .execute(Statement::from_string(DatabaseBackend::Postgres, stm)) + .await?; info!("Created the Table - {:?}", exec_res); Ok(result) } /// create_new_field - this will create new Field in Data Application in Orca - pub async fn create_new_field(&self, mut table_id: i32, mut field: FieldModel) -> InternalResult { + pub async fn create_new_field( + &self, + mut table_id: i32, + mut field: FieldModel, + ) -> InternalResult { let table = self.get_datatable(table_id).await?; field.table_id = table_id; let mut field = field.into_active_model(); @@ -84,18 +104,21 @@ impl DatatableService { loop { field.field_id = Set(field_id.clone()); let result = field.clone().insert(self.trx()).await; - if !result.is_err(){ - break + if !result.is_err() { + break; } iter += 1; field_id = format!("{_field_id}_{iter}"); } let manager = SchemaManager::new(self.trx()); - let res = manager.alter_table( - Table::alter().table(Alias::new(table.table_name)) - .add_column(ColumnDef::new(Alias::new(field_id.clone())).string()) - .to_owned() - ).await?; + let res = manager + .alter_table( + Table::alter() + .table(Alias::new(table.table_name)) + .add_column(ColumnDef::new(Alias::new(field_id.clone())).string()) + .to_owned(), + ) + .await?; Ok(field.try_into_model()?) } @@ -103,23 +126,33 @@ impl DatatableService { /// drop_field - this will drop Field in Data Application in Orca pub async fn drop_field(&self, table_id: i32, field_id: String) -> InternalResult<()> { let _filter = Condition::all() - .add(FieldColumn::FieldId.eq(field_id.clone())) - .add(FieldColumn::TableId.eq(table_id)); + .add(FieldColumn::FieldId.eq(field_id.clone())) + .add(FieldColumn::TableId.eq(table_id)); let manager = SchemaManager::new(self.trx()); - manager.alter_table( - Table::alter().table(FieldEntity) - .drop_column(Alias::new(field_id.clone())).to_owned() - ).await?; - let result = FieldEntity::delete_many().filter(_filter).exec(self.trx()).await?; + manager + .alter_table( + Table::alter() + .table(FieldEntity) + .drop_column(Alias::new(field_id.clone())) + .to_owned(), + ) + .await?; + let result = FieldEntity::delete_many() + .filter(_filter) + .exec(self.trx()) + .await?; info!("Deleted Column({:?}) from Table ({:?})", field_id, table_id); info!("field Removed {:?}", result.rows_affected); Ok(()) } /// batch_update_data - this will Batch update data in Application Datatable - pub async fn batch_update_data(&self, table_id: i32, - mut table_datas: Vec) -> InternalResult<()> { + pub async fn batch_update_data( + &self, + table_id: i32, + mut table_datas: Vec, + ) -> InternalResult<()> { let table = self.get_datatable(table_id).await?; // let result = table_datas.iter_mut().map(|item| { // return 1; @@ -129,9 +162,11 @@ impl DatatableService { .table(Alias::new(table.table_name.clone())) .values([(Alias::new(data.field_id), data.data.into())]) .and_where(Expr::col(Alias::new("id")).eq(data.row_id)) - .to_owned().to_string(PostgresQueryBuilder); - self.trx().execute(Statement::from_string(DatabaseBackend::Postgres, - query)).await?; + .to_owned() + .to_string(PostgresQueryBuilder); + self.trx() + .execute(Statement::from_string(DatabaseBackend::Postgres, query)) + .await?; } Ok(()) } @@ -143,41 +178,47 @@ impl DatatableService { .from(Alias::new(table.table_name.clone())) .expr(Expr::col(Asterisk)) .order_by(Alias::new("id"), Order::Asc) - .to_owned().to_string(PostgresQueryBuilder); + .to_owned() + .to_string(PostgresQueryBuilder); let data = Entity::find() - .from_raw_sql(Statement::from_string( - DatabaseBackend::Postgres, - query - )) - .into_model::() - .all(self.trx()) - .await?; + .from_raw_sql(Statement::from_string(DatabaseBackend::Postgres, query)) + .into_model::() + .all(self.trx()) + .await?; Ok(data) } /// update_data - get data for specify Datatable in Application pub async fn update_data(&self, table_id: i32, value: Value) -> InternalResult<()> { let table = self.get_datatable(table_id).await?; let query = Query::insert() - .into_table(Alias::new(table.table_name.clone())).or_default_values() - .to_owned().to_string(PostgresQueryBuilder); - self.trx().execute(Statement::from_string(DatabaseBackend::Postgres, - query)).await?; + .into_table(Alias::new(table.table_name.clone())) + .or_default_values() + .to_owned() + .to_string(PostgresQueryBuilder); + self.trx() + .execute(Statement::from_string(DatabaseBackend::Postgres, query)) + .await?; Ok(()) } - /// delete_action - this will delete Action for Action Group in Application in Orca pub async fn delete_table(&self, table_id: i32) -> InternalResult<()> { let table = Entity::find_by_id(table_id).one(self.trx()).await?; if table.is_none() { - return Err(OrcaRepoError::ModelNotFound("Table".to_string(), table_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Table".to_string(), + table_id.to_string(), + ))?; } let table = table.unwrap(); let manager = SchemaManager::new(self.trx()); - let res = manager.drop_table( - Table::drop().table(Alias::new(table.table_name.clone())) - .to_owned() - ).await?; + let _res = manager + .drop_table( + Table::drop() + .table(Alias::new(table.table_name.clone())) + .to_owned(), + ) + .await?; table.delete(self.trx()).await?; Ok(()) } diff --git a/crates/services/api/src/service/app/group.rs b/crates/services/api/src/service/app/group.rs index 1796aef..1073851 100644 --- a/crates/services/api/src/service/app/group.rs +++ b/crates/services/api/src/service/app/group.rs @@ -1,4 +1,7 @@ -use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, TryIntoModel}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, + QueryOrder, TryIntoModel, +}; use sea_query::Condition; use tracing::info; use uuid::Uuid; @@ -19,19 +22,21 @@ impl GroupService { self.0.trx() } - /// get_groups - list all the Action Group in Specific Application in the Orca Application pub async fn get_groups(&self, app_id: Uuid) -> InternalResult> { let _filter = Condition::all() - .add(Column::AppId.eq(app_id)) - .add(Column::TypeField.eq(ActionGroupKind::ActionGroup)); - let groups = Entity::find().filter(_filter) - .order_by_asc(Column::Name).all(self.trx()).await?; + .add(Column::AppId.eq(app_id)) + .add(Column::TypeField.eq(ActionGroupKind::ActionGroup)); + let groups = Entity::find() + .filter(_filter) + .order_by_asc(Column::Name) + .all(self.trx()) + .await?; Ok(groups) } /// create_group - This will create new Action Group in Application in Orca - pub async fn create_group(&self, app_id: Uuid, mut group: Model) -> InternalResult { + pub async fn create_group(&self, app_id: Uuid, mut group: Model) -> InternalResult { group.id = Uuid::new_v4(); group.app_id = app_id; let app = group.into_active_model(); @@ -40,11 +45,17 @@ impl GroupService { } /// update_action_group - this will create new Application in Orca - pub async fn update_action_group(&self, group_id: Uuid, mut group: Model) -> InternalResult { - let _group = Entity::find_by_id(group_id) - .one(self.trx()).await?; + pub async fn update_action_group( + &self, + group_id: Uuid, + group: Model, + ) -> InternalResult { + let _group = Entity::find_by_id(group_id).one(self.trx()).await?; if _group.is_none() { - return Err(OrcaRepoError::ModelNotFound("Action Group".to_string(), group_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Action Group".to_string(), + group_id.to_string(), + ))?; } let group = group.into_active_model(); let result = group.save(self.trx()).await?; @@ -55,13 +66,12 @@ impl GroupService { pub async fn delete_group(&self, group_id: Uuid) -> InternalResult<()> { let result = Entity::delete_by_id(group_id).exec(self.trx()).await?; if result.rows_affected == 0 { - return Err(OrcaRepoError::ModelNotFound("Action Group".to_string(), group_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Action Group".to_string(), + group_id.to_string(), + ))?; } info!("Deleting Action group - {:?}", group_id); Ok(()) } - } - - - diff --git a/crates/services/api/src/service/app/mod.rs b/crates/services/api/src/service/app/mod.rs index 03a6bfd..ffc450c 100644 --- a/crates/services/api/src/service/app/mod.rs +++ b/crates/services/api/src/service/app/mod.rs @@ -1,16 +1,17 @@ use sea_orm::{ActiveModelTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryOrder}; use uuid::Uuid; + use entity::app::app::{Column, Entity, Model}; + use crate::error::InternalResult; use crate::server::session::OrcaSession; pub(crate) mod action; +pub(crate) mod case; +pub(crate) mod datatable; pub(crate) mod group; pub(crate) mod profile; -pub(crate) mod datatable; pub(crate) mod suit; -pub(crate) mod case; - pub(crate) struct AppService(OrcaSession); @@ -26,7 +27,9 @@ impl AppService { /// list all the Application in the Orca Application pub async fn list_apps(&self) -> InternalResult> { let actions = Entity::find() - .order_by_asc(Column::Name).all(self.trx()).await?; + .order_by_asc(Column::Name) + .all(self.trx()) + .await?; Ok(actions) } @@ -45,7 +48,4 @@ impl AppService { let result = app.insert(self.trx()).await?; Ok(result) } - } - - diff --git a/crates/services/api/src/service/app/profile.rs b/crates/services/api/src/service/app/profile.rs index b5b20a9..23ed628 100644 --- a/crates/services/api/src/service/app/profile.rs +++ b/crates/services/api/src/service/app/profile.rs @@ -1,9 +1,14 @@ -use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, + QueryOrder, +}; use sea_query::Condition; use tracing::info; use uuid::Uuid; -use entity::test::profile::data::{Column as DataColumn, Entity as DataEntity, Model as DataModel}; + +use entity::test::profile::data::{Column as DataColumn, Entity as DataEntity}; use entity::test::profile::profile::{Column, Entity, Model}; + use crate::error::{InternalResult, OrcaRepoError}; use crate::server::session::OrcaSession; @@ -20,8 +25,12 @@ impl ProfileService { /// list_profile - list all the Profile that is Bound with Current Application pub async fn list_profile(&self) -> InternalResult> { - let _filter = Condition::all().add(Column::AppId.eq(self.1)); - let profiles = Entity::find().filter(_filter).order_by_asc(Column::Name).all(self.trx()).await?; + let _filter = Condition::all().add(Column::AppId.eq(self.1)); + let profiles = Entity::find() + .filter(_filter) + .order_by_asc(Column::Name) + .all(self.trx()) + .await?; Ok(profiles) } @@ -35,10 +44,17 @@ impl ProfileService { } /// update_profile - this will update the existing profile information in Orca - pub async fn update_profile(&self, profile_id: Uuid, mut profile: Model) -> InternalResult { + pub async fn update_profile( + &self, + profile_id: Uuid, + mut profile: Model, + ) -> InternalResult { let _profile = Entity::find_by_id(profile_id).one(self.trx()).await?; if _profile.is_none() { - return Err(OrcaRepoError::ModelNotFound("Profile".to_string(), profile_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Profile".to_string(), + profile_id.to_string(), + ))?; } profile.id = profile_id; profile.app_id = self.1.clone(); @@ -51,14 +67,24 @@ impl ProfileService { pub async fn delete_profile(&self, profile_id: Uuid) -> InternalResult<()> { let result = Entity::delete_by_id(profile_id).exec(self.trx()).await?; if result.rows_affected == 0 { - return Err(OrcaRepoError::ModelNotFound("Profile".to_string(), profile_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Profile".to_string(), + profile_id.to_string(), + ))?; } info!("Deleted Application Profile - {:?}", profile_id); - info!("Deleting Application Profile Data of ProfileID- {:?}", profile_id); + info!( + "Deleting Application Profile Data of ProfileID- {:?}", + profile_id + ); let result = DataEntity::delete_many() .filter(DataColumn::ProfileId.eq(profile_id)) - .exec(self.trx()).await?; - info!("Deleted Application Profile Data of ProfileID- {:?}, count - {:?}", profile_id, result.rows_affected); + .exec(self.trx()) + .await?; + info!( + "Deleted Application Profile Data of ProfileID- {:?}, count - {:?}", + profile_id, result.rows_affected + ); Ok(()) } @@ -66,7 +92,10 @@ impl ProfileService { pub async fn delete_profile_data(&self, _data_id: Uuid) -> InternalResult<()> { let result = DataEntity::delete_by_id(_data_id).exec(self.trx()).await?; if result.rows_affected == 0 { - return Err(OrcaRepoError::ModelNotFound("Profile Item Data".to_string(), _data_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Profile Item Data".to_string(), + _data_id.to_string(), + ))?; } info!("Deleted Application Profile Data - {:?}", _data_id); Ok(()) @@ -76,10 +105,12 @@ impl ProfileService { pub async fn batch_update_action(&self, _data_id: Uuid) -> InternalResult<()> { let result = DataEntity::delete_by_id(_data_id).exec(self.trx()).await?; if result.rows_affected == 0 { - return Err(OrcaRepoError::ModelNotFound("Profile Item Data".to_string(), _data_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Profile Item Data".to_string(), + _data_id.to_string(), + ))?; } info!("Deleted Application Profile Data - {:?}", _data_id); Ok(()) } - } diff --git a/crates/services/api/src/service/app/suit.rs b/crates/services/api/src/service/app/suit.rs index 3a74a6f..575a493 100644 --- a/crates/services/api/src/service/app/suit.rs +++ b/crates/services/api/src/service/app/suit.rs @@ -1,10 +1,15 @@ -use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, QueryOrder, QuerySelect}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, + QueryOrder, QuerySelect, +}; use sea_query::{Condition, Expr}; use tracing::info; use uuid::Uuid; use entity::test::ui::suit::suite::{Column, Entity, Model}; -use entity::test::ui::suit::suite_block::{ActiveModel, Column as BlockColumn, Entity as BlockEntity, Model as BlockModel}; +use entity::test::ui::suit::suite_block::{ + ActiveModel, Column as BlockColumn, Entity as BlockEntity, Model as BlockModel, +}; use crate::error::{InternalResult, OrcaRepoError}; use crate::server::session::OrcaSession; @@ -22,9 +27,11 @@ impl SuitService { /// list all the test suites in the Orca Application pub(crate) async fn list_suites(&self) -> InternalResult> { - let suites = Entity::find().filter(Column::AppId.eq(self.1)) + let suites = Entity::find() + .filter(Column::AppId.eq(self.1)) .order_by_asc(Column::Name) - .all(self.trx()).await?; + .all(self.trx()) + .await?; Ok(suites) } @@ -33,62 +40,82 @@ impl SuitService { body.app_id = self.1; let _case = body.into_active_model(); let result = _case.insert(self.trx()).await?; - return Ok(result) + return Ok(result); } /// batch_update_suite_block - update suite Block - pub(crate) async fn batch_update_suite_block(&self, suite_id: Uuid, - mut body: Vec) -> InternalResult<()> { - let suit_blocks: Vec = body.into_iter().map(|mut block|{ - block.suite_id = suite_id.clone(); - block.into_active_model() - }).collect(); - let blocks = BlockEntity::insert_many(suit_blocks) - .exec(self.trx()).await?; + pub(crate) async fn batch_update_suite_block( + &self, + suite_id: Uuid, + body: Vec, + ) -> InternalResult<()> { + let suit_blocks: Vec = body + .into_iter() + .map(|mut block| { + block.suite_id = suite_id.clone(); + block.into_active_model() + }) + .collect(); + let _blocks = BlockEntity::insert_many(suit_blocks) + .exec(self.trx()) + .await?; Ok(()) } /// get_suits_info - Get Suite Info and the batch information with the list of block pub(crate) async fn get_suite_info(&self, suite_id: Uuid) -> InternalResult { - let suite = Entity::find_by_id(suite_id) - .one(self.trx()).await?; + let suite = Entity::find_by_id(suite_id).one(self.trx()).await?; if suite.is_none() { - return Err(OrcaRepoError::ModelNotFound("Test Suite".to_string(), suite_id.to_string()))?; + return Err(OrcaRepoError::ModelNotFound( + "Test Suite".to_string(), + suite_id.to_string(), + ))?; } let mut suite = suite.unwrap(); let suite_blocks = BlockEntity::find() .filter(BlockColumn::SuiteId.eq(suite_id)) .order_by_asc(BlockColumn::ExecutionOrder) - .all(self.trx()).await?; + .all(self.trx()) + .await?; suite.suite_execution = Some(serde_json::to_value(suite_blocks)?); Ok(suite) } /// push_block - This will Append New Block to the code for spe - pub(crate) async fn push_block(&self, suite_id: Uuid, mut body: BlockModel, index: Option) -> InternalResult { - + pub(crate) async fn push_block( + &self, + suite_id: Uuid, + mut body: BlockModel, + index: Option, + ) -> InternalResult { let mut _filter = Condition::all().add(BlockColumn::SuiteId.eq(suite_id)); // if param.parent.is_some() { // _filter = _filter.add(case_block::Column::ParentId.eq(param.parent.unwrap())); // } - let blocks = BlockEntity::find().filter(_filter.clone()) - .order_by_desc(BlockColumn::ExecutionOrder).limit(1) - .all(self.trx()).await?; + let blocks = BlockEntity::find() + .filter(_filter.clone()) + .order_by_desc(BlockColumn::ExecutionOrder) + .limit(1) + .all(self.trx()) + .await?; let mut last_index = 1; if let Some(last_item) = blocks.last() { last_index = last_item.execution_order + 1; } - let _index : i32 = match index { + let _index: i32 = match index { Some(x) => { - let i = if x > last_index { last_index } else {x}; + let i = if x > last_index { last_index } else { x }; i - }, - _ => last_index + } + _ => last_index, }; _filter = _filter.add(BlockColumn::ExecutionOrder.gte(_index)); - let update_result = BlockEntity::update_many() - .col_expr(BlockColumn::ExecutionOrder, Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1)) + let _update_result = BlockEntity::update_many() + .col_expr( + BlockColumn::ExecutionOrder, + Expr::expr(Expr::col(BlockColumn::ExecutionOrder).if_null(0)).add(1), + ) .filter(_filter) .exec(self.trx()) .await?; @@ -100,4 +127,4 @@ impl SuitService { let result = _suite.insert(self.trx()).await?; Ok(result) } -} \ No newline at end of file +} diff --git a/crates/services/api/src/service/mod.rs b/crates/services/api/src/service/mod.rs index ee12753..514a601 100644 --- a/crates/services/api/src/service/mod.rs +++ b/crates/services/api/src/service/mod.rs @@ -1,11 +1,10 @@ +use crate::error::InternalResult; use axum::async_trait; use sea_orm::{ActiveModelBehavior, ActiveModelTrait, DatabaseTransaction, ModelTrait}; -use crate::error::InternalResult; pub(crate) mod admin; pub(crate) mod app; - // #[async_trait] // pub trait CrudService { // @@ -19,4 +18,4 @@ pub(crate) mod app; // let result = am.insert(self.trx()).await?; // // Ok(result) // } -// } \ No newline at end of file +// } diff --git a/crates/services/api/src/utils/mod.rs b/crates/services/api/src/utils/mod.rs index 7e4d31a..eb21af1 100644 --- a/crates/services/api/src/utils/mod.rs +++ b/crates/services/api/src/utils/mod.rs @@ -1,6 +1,3 @@ - - - pub fn replace_special_chars(input: &str, replace_with: char) -> String { let mut result = String::with_capacity(input.len()); @@ -12,4 +9,4 @@ pub fn replace_special_chars(input: &str, replace_with: char) -> String { } } result -} \ No newline at end of file +} diff --git a/crates/services/engine/src/controller/action.rs b/crates/services/engine/src/controller/action.rs index b818018..6691816 100644 --- a/crates/services/engine/src/controller/action.rs +++ b/crates/services/engine/src/controller/action.rs @@ -1,10 +1,13 @@ +use cerium::client::driver::web::WebDriver; +use sea_orm::prelude::Uuid; +use sea_orm::{ + ColumnTrait, DatabaseConnection, DatabaseTransaction, EntityTrait, ModelTrait, PaginatorTrait, + QueryFilter, QueryOrder, +}; use std::fs; use std::io::Write; -use sea_orm::{ColumnTrait, DatabaseConnection, DatabaseTransaction, EntityTrait, ModelTrait, PaginatorTrait, QueryFilter, QueryOrder}; -use sea_orm::prelude::Uuid; -use tracing::info; use thirtyfour::By; -use cerium::client::driver::web::WebDriver; +use tracing::info; use entity::prelude::target::ActionTargetKind; use entity::test::ui::action::action; @@ -12,9 +15,9 @@ use entity::test::ui::action::action::ActionKind; use crate::error::{EngineError, EngineResult}; -pub struct ActionController<'ccl>{ +pub struct ActionController<'ccl> { db: &'ccl DatabaseTransaction, - driver: WebDriver + driver: WebDriver, } impl<'ccl> ActionController<'ccl> { @@ -39,9 +42,9 @@ impl<'ccl> ActionController<'ccl> { /// let controller = ActionController::new(&db, driver); /// ``` pub fn new(db: &'ccl DatabaseTransaction, driver: WebDriver) -> ActionController<'ccl> { - Self{db, driver} + Self { db, driver } } - + /// Asynchronous method that handles the logic for executing the "Open" action in a test case. /// /// # Arguments @@ -70,10 +73,13 @@ impl<'ccl> ActionController<'ccl> { pub async fn command_open(&self, action: &action::Model) -> EngineResult<()> { match action.data_value.clone() { Some(value) => Ok(self.driver.open(value.as_str()).await?), - None => Err(EngineError::MissingParameter("url".to_string(), "".to_string())) + None => Err(EngineError::MissingParameter( + "url".to_string(), + "".to_string(), + )), } } - + /// Asynchronously enters data into a target element on a web page using a WebDriver. /// /// # Arguments @@ -99,18 +105,28 @@ impl<'ccl> ActionController<'ccl> { /// /// Returns `Ok(())` if the action of entering data into the target element is successful. async fn command_enter(&self, action: &action::Model) -> EngineResult<()> { - let data_value = action.data_value.clone().ok_or_else(|| EngineError::MissingParameter("action.data_value".to_string(), "".to_string()))?; - let target_value = action.target_value.clone().ok_or_else(|| EngineError::MissingParameter("action.target_value".to_string(), "".to_string()))?; - let target_kind = action.target_kind.clone().ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; + let data_value = action.data_value.clone().ok_or_else(|| { + EngineError::MissingParameter("action.data_value".to_string(), "".to_string()) + })?; + let target_value = action.target_value.clone().ok_or_else(|| { + EngineError::MissingParameter("action.target_value".to_string(), "".to_string()) + })?; + let target_kind = action.target_kind.clone().ok_or_else(|| { + EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()) + })?; let by_kind = match target_kind { ActionTargetKind::Css => By::Css(target_value.as_str()), ActionTargetKind::Id => By::Id(target_value.as_str()), - ActionTargetKind::Xpath => By::XPath(target_value.as_str()) + ActionTargetKind::Xpath => By::XPath(target_value.as_str()), }; - self.driver.find(by_kind).await?.send_keys(data_value).await?; + self.driver + .find(by_kind) + .await? + .send_keys(data_value) + .await?; Ok(()) } - + /// Performs a click action on a web element based on the provided target value and target kind. /// /// # Arguments @@ -132,50 +148,67 @@ impl<'ccl> ActionController<'ccl> { /// /// Returns `Ok(())` if the click action is performed successfully. async fn command_click(&self, action: &action::Model) -> EngineResult<()> { - let target_value = action.target_value.clone() - .ok_or_else(|| EngineError::MissingParameter("command_click.action.target_value".to_string(), "".to_string()))?; - let target_kind = action.target_kind.clone() - .ok_or_else(|| EngineError::MissingParameter("command_click.action.target_kind".to_string(), "".to_string()))?; + let target_value = action.target_value.clone().ok_or_else(|| { + EngineError::MissingParameter( + "command_click.action.target_value".to_string(), + "".to_string(), + ) + })?; + let target_kind = action.target_kind.clone().ok_or_else(|| { + EngineError::MissingParameter( + "command_click.action.target_kind".to_string(), + "".to_string(), + ) + })?; let by_kind = match target_kind { ActionTargetKind::Css => By::Css(target_value.as_str()), ActionTargetKind::Id => By::Id(target_value.as_str()), - ActionTargetKind::Xpath => By::XPath(target_value.as_str()) + ActionTargetKind::Xpath => By::XPath(target_value.as_str()), }; self.driver.find(by_kind).await?.click().await?; Ok(()) } - + async fn command_verify_text(&self, action: &action::Model) -> EngineResult<()> { - let data_value = action.data_value.clone() - .ok_or_else(|| EngineError::MissingParameter("action.data_value".to_string(), "".to_string()))?; - let target_value = action.target_value.clone() - .ok_or_else(|| EngineError::MissingParameter("command_verify_text.action.target_value".to_string(), "".to_string()))?; - let target_kind = action.target_kind.clone() - .ok_or_else(|| EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()))?; + let data_value = action.data_value.clone().ok_or_else(|| { + EngineError::MissingParameter("action.data_value".to_string(), "".to_string()) + })?; + let target_value = action.target_value.clone().ok_or_else(|| { + EngineError::MissingParameter( + "command_verify_text.action.target_value".to_string(), + "".to_string(), + ) + })?; + let target_kind = action.target_kind.clone().ok_or_else(|| { + EngineError::MissingParameter("action.target_kind".to_string(), "".to_string()) + })?; let by_kind = match target_kind { ActionTargetKind::Css => By::Css(target_value.as_str()), ActionTargetKind::Id => By::Id(target_value.as_str()), - ActionTargetKind::Xpath => By::XPath(target_value.as_str()) + ActionTargetKind::Xpath => By::XPath(target_value.as_str()), }; let we = self.driver.find(by_kind).await?; let text = we.inner_html().await?; info!(text); if text != data_value { info!("Verify text is failed {}", data_value); - return Err(EngineError::MissingParameter("action.data_value".to_string(), data_value)); + return Err(EngineError::MissingParameter( + "action.data_value".to_string(), + data_value, + )); } info!("Verify text is Success {}", data_value); Ok(()) } - + pub async fn step_executor(&self, action: &action::Model) -> EngineResult<()> { let set_response = match action.kind.clone() { ActionKind::Open => self.command_open(action).await?, ActionKind::Enter => self.command_enter(action).await?, ActionKind::Click => self.command_click(action).await?, - ActionKind::DoubleClick => {}, - - ActionKind::VerifyText => self.command_verify_text(action).await?, + ActionKind::DoubleClick => {} + + ActionKind::VerifyText => self.command_verify_text(action).await?, _ => {} }; Ok(()) @@ -187,23 +220,28 @@ impl<'ccl> ActionController<'ccl> { file.write_all(&*result).expect("error"); Ok(()) } - + /// run_case - will execute the test case by the case ID pub async fn execute(&self, id: Uuid) -> EngineResult<()> { - info!("Starting processing {action_id}", action_id=id); + info!("Starting processing {action_id}", action_id = id); let mut action_page = action::Entity::find() .filter(action::Column::ActionGroupId.eq(id)) - .order_by_asc(action::Column::ExecutionOrder).paginate(self.db, 50); + .order_by_asc(action::Column::ExecutionOrder) + .paginate(self.db, 50); while let Some(actions) = action_page.fetch_and_next().await? { for action in actions.into_iter() { - info!("Executing step == [id] {:?}, [desc] {:?}", action.id, action.description); + info!( + "Executing step == [id] {:?}, [desc] {:?}", + action.id, action.description + ); self.step_executor(&action).await?; self.take_screenshot(action.id.to_string()).await?; - info!("Done step == [id] {:?}, [desc] {:?}", action.id, action.description); + info!( + "Done step == [id] {:?}, [desc] {:?}", + action.id, action.description + ); } } Ok(()) } - } - diff --git a/crates/services/engine/src/controller/case.rs b/crates/services/engine/src/controller/case.rs index ca40632..7a6edd1 100644 --- a/crates/services/engine/src/controller/case.rs +++ b/crates/services/engine/src/controller/case.rs @@ -1,5 +1,7 @@ -use sea_orm::{ColumnTrait, DatabaseTransaction, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder}; use sea_orm::prelude::Uuid; +use sea_orm::{ + ColumnTrait, DatabaseTransaction, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder, +}; use tracing::{error, info}; use cerium::client::driver::web::WebDriver; @@ -11,14 +13,14 @@ use entity::test::ui::case::case; use crate::controller::action::ActionController; use crate::error::EngineResult; -pub struct CaseController<'ccl>{ +pub struct CaseController<'ccl> { db: &'ccl DatabaseTransaction, - drive: WebDriver + drive: WebDriver, } impl<'ccl> CaseController<'ccl> { pub fn new(db: &'ccl DatabaseTransaction, drive: WebDriver) -> CaseController<'ccl> { - Self{db, drive } + Self { db, drive } } /// run_case - will execute the test case by the case ID pub async fn run_case(&self, id: Uuid) -> EngineResult<()> { @@ -28,7 +30,11 @@ impl<'ccl> CaseController<'ccl> { return Ok(()); } let case: &case::Model = &case_res.unwrap(); - info!("Start Processing Case - [[ {name} || {id} ]]", name=case.name, id=case.id); + info!( + "Start Processing Case - [[ {name} || {id} ]]", + name = case.name, + id = case.id + ); self.process(case).await?; Ok(()) } @@ -37,7 +43,8 @@ impl<'ccl> CaseController<'ccl> { pub async fn process(&self, case: &case::Model) -> EngineResult<()> { let mut block_page = case_block::Entity::find() .filter(case_block::Column::CaseId.eq(case.id)) - .order_by_asc(case_block::Column::ExecutionOrder).paginate(self.db, 10); + .order_by_asc(case_block::Column::ExecutionOrder) + .paginate(self.db, 10); while let Some(blocks) = block_page.fetch_and_next().await? { for block in blocks.into_iter() { self.switch_block(&block).await?; @@ -47,30 +54,24 @@ impl<'ccl> CaseController<'ccl> { } /// switch_block - function to switch the block based on the type and kind of the block - async fn switch_block(&self, block: &case_block::Model) -> EngineResult<()>{ + async fn switch_block(&self, block: &case_block::Model) -> EngineResult<()> { let result = match block.kind { - BlockKind::Loop => { - match block.type_field { - BlockType::InMemory => self.process_action_group(block), - BlockType::DataTable => self.process_action_group(block), - _ => todo!("Need to raise a error from here since non other supported") - } - - } - BlockKind::Condition => { - match block.type_field { - BlockType::InMemory => self.process_action_group(block), - _ => todo!("Need to raise a error from here since non other supported") - } - } - BlockKind::Reference => { - match block.type_field { - BlockType::ActionGroup => self.process_action_group(block), - BlockType::Assertion => self.process_action_group(block), - _ => todo!("Need to raise a error from here since non other supported") - } + BlockKind::Loop => match block.type_field { + BlockType::InMemory => self.process_action_group(block), + BlockType::DataTable => self.process_action_group(block), + _ => todo!("Need to raise a error from here since non other supported"), }, - }.await?; + BlockKind::Condition => match block.type_field { + BlockType::InMemory => self.process_action_group(block), + _ => todo!("Need to raise a error from here since non other supported"), + }, + BlockKind::Reference => match block.type_field { + BlockType::ActionGroup => self.process_action_group(block), + BlockType::Assertion => self.process_action_group(block), + _ => todo!("Need to raise a error from here since non other supported"), + }, + } + .await?; Ok(()) } @@ -78,18 +79,14 @@ impl<'ccl> CaseController<'ccl> { () } - async fn process_datatable_loop(&self, block: &case_block::Model){ + async fn process_datatable_loop(&self, block: &case_block::Model) {} - } - - async fn process_condition(&self, block: &case_block::Model){ - - } + async fn process_condition(&self, block: &case_block::Model) {} async fn process_action_group(&self, block: &case_block::Model) -> EngineResult<()> { - info!("Starting processing {block_id}", block_id=block.id); + info!("Starting processing {block_id}", block_id = block.id); Ok(ActionController::new(self.db, self.drive.clone()) - .execute(block.reference.unwrap()).await?) + .execute(block.reference.unwrap()) + .await?) } } - diff --git a/crates/services/engine/src/controller/mod.rs b/crates/services/engine/src/controller/mod.rs index ba204e6..eeb163c 100644 --- a/crates/services/engine/src/controller/mod.rs +++ b/crates/services/engine/src/controller/mod.rs @@ -1,3 +1,3 @@ -pub mod suite; -pub mod case; pub mod action; +pub mod case; +pub mod suite; diff --git a/crates/services/engine/src/controller/suite.rs b/crates/services/engine/src/controller/suite.rs index e69de29..8b13789 100644 --- a/crates/services/engine/src/controller/suite.rs +++ b/crates/services/engine/src/controller/suite.rs @@ -0,0 +1 @@ + diff --git a/crates/services/engine/src/error.rs b/crates/services/engine/src/error.rs index cf80d64..d4bef67 100644 --- a/crates/services/engine/src/error.rs +++ b/crates/services/engine/src/error.rs @@ -1,12 +1,11 @@ +use cerium::error::CeriumError; use sea_orm::DbErr; use serde_json::Error as SerdeJsonError; use thirtyfour::error::WebDriverError; use thiserror::Error; -use cerium::error::CeriumError; pub type EngineResult = Result; - /// EngineError - will have all the error raised from Cerium system #[derive(Error, Debug)] pub enum EngineError { @@ -21,6 +20,5 @@ pub enum EngineError { #[error("Json Serialization error: {0}")] SerializerError(#[from] SerdeJsonError), #[error("CeriumError: {0}")] - CeriumError(#[from] CeriumError) + CeriumError(#[from] CeriumError), } - diff --git a/crates/services/engine/src/lib.rs b/crates/services/engine/src/lib.rs index e06a8e7..cec297a 100644 --- a/crates/services/engine/src/lib.rs +++ b/crates/services/engine/src/lib.rs @@ -1,7 +1,6 @@ extern crate entity; -pub mod ui; pub mod controller; -pub mod server; pub mod error; - +pub mod server; +pub mod ui; diff --git a/crates/services/engine/src/server/mod.rs b/crates/services/engine/src/server/mod.rs index e69de29..8b13789 100644 --- a/crates/services/engine/src/server/mod.rs +++ b/crates/services/engine/src/server/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/services/engine/src/ui/mod.rs b/crates/services/engine/src/ui/mod.rs index 1120fc7..80aa5fd 100644 --- a/crates/services/engine/src/ui/mod.rs +++ b/crates/services/engine/src/ui/mod.rs @@ -1,3 +1 @@ pub mod step; - - diff --git a/crates/services/engine/src/ui/step.rs b/crates/services/engine/src/ui/step.rs index 001a7d1..66f5b39 100644 --- a/crates/services/engine/src/ui/step.rs +++ b/crates/services/engine/src/ui/step.rs @@ -1,5 +1,3 @@ - - // pub struct Step { // pub description: Option, // #[serde(rename(serialize = "type"))] diff --git a/crates/services/engine/tests/controller.rs b/crates/services/engine/tests/controller.rs index 78aa60e..0964589 100644 --- a/crates/services/engine/tests/controller.rs +++ b/crates/services/engine/tests/controller.rs @@ -1,16 +1,12 @@ - - - - #[cfg(test)] mod tests { use std::str::FromStr; - use sea_orm::{Database, TransactionTrait}; + use cerium::client::driver::web::WebDriver; use sea_orm::prelude::Uuid; + use sea_orm::{Database, TransactionTrait}; use tracing::{info, Level}; use tracing_subscriber::fmt; - use cerium::client::driver::web::WebDriver; use engine::controller::case::CaseController; @@ -22,14 +18,19 @@ mod tests { let uri = Some("postgres://root:root@localhost:5432/orca".to_string()); - let db = Database::connect(uri.unwrap()).await.expect("Error unable to connect DB"); + let db = Database::connect(uri.unwrap()) + .await + .expect("Error unable to connect DB"); let trx = db.begin().await.expect("Error unable to connect DB"); info!("got the db"); let ui_driver = WebDriver::default().await.expect("error"); info!("got the driver"); let controller = CaseController::new(&trx, ui_driver.clone()); info!("got the controller"); - controller.run_case(Uuid::from_str(case_id.as_str()).expect("")).await.expect("error"); + controller + .run_case(Uuid::from_str(case_id.as_str()).expect("")) + .await + .expect("error"); ui_driver.driver.quit().await; } From 48a196a403624c693900448d1946ed710d3b76aa Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Mon, 1 Jan 2024 08:40:16 +0530 Subject: [PATCH 7/8] Fixed lint for cargo project --- crates/libs/cerium/src/client/mod.rs | 2 +- crates/libs/cerium/src/server/mod.rs | 17 ++++++++--------- crates/services/engine/src/controller/action.rs | 11 ++++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/libs/cerium/src/client/mod.rs b/crates/libs/cerium/src/client/mod.rs index b8de7e3..c3468d5 100644 --- a/crates/libs/cerium/src/client/mod.rs +++ b/crates/libs/cerium/src/client/mod.rs @@ -12,7 +12,7 @@ pub struct Client { } impl Client { - pub async fn new(db_uri: Option, redis_uri: Option) -> Self { + pub async fn new(db_uri: Option, _redis_uri: Option) -> Self { Client { db: Self::db_client(db_uri).await, } diff --git a/crates/libs/cerium/src/server/mod.rs b/crates/libs/cerium/src/server/mod.rs index 92f4ba4..379a1d5 100644 --- a/crates/libs/cerium/src/server/mod.rs +++ b/crates/libs/cerium/src/server/mod.rs @@ -1,22 +1,21 @@ -use crate::client::Client; +use std::sync::{Arc, Mutex}; + +use axum::{Router, serve}; use axum::http::{HeaderName, Method}; -use axum::{serve, Router}; -use chrono::Duration; use sea_orm::DatabaseConnection; -use std::sync::{Arc, Mutex}; use tokio::net::TcpListener; -use tower_http::catch_panic::CatchPanicLayer; -use tower_http::classify::ServerErrorsFailureClass; -use tower_http::request_id::{PropagateRequestIdLayer, SetRequestIdLayer}; -use tower_http::trace::TraceLayer; use tower_http::{ compression::CompressionLayer, cors::{Any, CorsLayer}, }; -use tracing::{error, info, Level, Span}; +use tower_http::catch_panic::CatchPanicLayer; +use tower_http::request_id::{PropagateRequestIdLayer, SetRequestIdLayer}; +use tower_http::trace::TraceLayer; +use tracing::{info, Level}; use tracing_subscriber::fmt; use tracing_subscriber::layer::SubscriberExt; +use crate::client::Client; use crate::server::request_id::OrcaRequestId; mod request_id; diff --git a/crates/services/engine/src/controller/action.rs b/crates/services/engine/src/controller/action.rs index 6691816..7129c37 100644 --- a/crates/services/engine/src/controller/action.rs +++ b/crates/services/engine/src/controller/action.rs @@ -1,14 +1,15 @@ -use cerium::client::driver::web::WebDriver; -use sea_orm::prelude::Uuid; +use std::fs; +use std::io::Write; + use sea_orm::{ - ColumnTrait, DatabaseConnection, DatabaseTransaction, EntityTrait, ModelTrait, PaginatorTrait, + ColumnTrait, DatabaseTransaction, EntityTrait, ModelTrait, PaginatorTrait, QueryFilter, QueryOrder, }; -use std::fs; -use std::io::Write; +use sea_orm::prelude::Uuid; use thirtyfour::By; use tracing::info; +use cerium::client::driver::web::WebDriver; use entity::prelude::target::ActionTargetKind; use entity::test::ui::action::action; use entity::test::ui::action::action::ActionKind; From a4863ab20d212a0451fdea6b47f25d54de8309dd Mon Sep 17 00:00:00 2001 From: Vasanth kumar Kalaiselvan Date: Mon, 1 Jan 2024 14:59:07 +0530 Subject: [PATCH 8/8] Fixed the new env config --- .cargo/config.example.toml | 29 +++++++--------------------- .cargo/config.local.toml | 19 ++++++++++++++++++ crates/libs/cerium/src/client/mod.rs | 2 +- crates/libs/cerium/src/config.rs | 2 +- crates/libs/cerium/src/env.rs | 27 ++++++++++++-------------- crates/services/api/src/main.rs | 15 +++++++++----- 6 files changed, 50 insertions(+), 44 deletions(-) create mode 100644 .cargo/config.local.toml diff --git a/.cargo/config.example.toml b/.cargo/config.example.toml index ecb7a17..517baea 100644 --- a/.cargo/config.example.toml +++ b/.cargo/config.example.toml @@ -5,28 +5,13 @@ [env] # Scope down tracing, to filter out external lib tracing. -RUST_LOG="web_server=debug,lib_core=debug,lib_auth=debug,lib_utils=debug" +RUST_LOG="cerium=debug,entity=debug,migration=info,api=debug" -# -- Service Environment Variables -# IMPORTANT: -# For cargo commands only. -# For deployed env, should be managed by container -# (e.g., Kubernetes). +## -- Database Url +DATABASE_URI="" +SELENIUM_URI="" -## -- Secrets -# Keys and passwords below are for localhost dev ONLY. -# e.g., "welcome" type of passwords. -# i.e., Encryption not needed. +# -- Encryption salt used for JWT token and other secret keys +ENCRYPTION_SALT="" -SERVICE_DB_URL="postgres://app_user:dev_only_pwd@localhost/app_db" - -SERVICE_PWD_KEY="" - -SERVICE_TOKEN_KEY="" -SERVICE_TOKEN_DURATION_SEC="1800" # 30 minutes - -## -- ConfigMap - -# This will be relative to Cargo.toml -# In deployed images, probably use absolute path. -SERVICE_WEB_FOLDER="web-folder/" \ No newline at end of file +DEBUG=false \ No newline at end of file diff --git a/.cargo/config.local.toml b/.cargo/config.local.toml new file mode 100644 index 0000000..1734ac7 --- /dev/null +++ b/.cargo/config.local.toml @@ -0,0 +1,19 @@ +# Cargo config file. +# See: https://doc.rust-lang.org/cargo/reference/config.html + +# Environments variables set for all `cargo ...` commands. +[env] + +DEBUG=false + +# Scope down tracing, to filter out external lib tracing. +RUST_LOG="cerium=debug,entity=debug,migration=info,api=debug" + +## -- Database Url +DATABASE_URI="postgres://root:root@localhost:5432/orca" +SELENIUM_URI="http://localhost:4444/wd/hub/session" + +# -- Encryption salt used for JWT token and other secret keys +ENCRYPTION_SALT="strongencryption" + + diff --git a/crates/libs/cerium/src/client/mod.rs b/crates/libs/cerium/src/client/mod.rs index c3468d5..f182577 100644 --- a/crates/libs/cerium/src/client/mod.rs +++ b/crates/libs/cerium/src/client/mod.rs @@ -25,7 +25,7 @@ impl Client { /// db_uri will give the default uri if there is not config setup async fn db_client(mut uri: Option) -> DatabaseConnection { if uri.is_none() { - uri = Some(std::env::var("DATABASE_URL").expect("DATABASE_URL must be set.")); + uri = Some(std::env::var("DATABASE_URI").expect("DATABASE_URL must be set.")); } let mut opt = ConnectOptions::new(uri.unwrap()); opt.max_connections(10) diff --git a/crates/libs/cerium/src/config.rs b/crates/libs/cerium/src/config.rs index 0b031fd..eeb780c 100644 --- a/crates/libs/cerium/src/config.rs +++ b/crates/libs/cerium/src/config.rs @@ -11,7 +11,7 @@ pub struct Config { impl Config { pub fn new() -> Self { - let env = Environment::new(); + let env = Environment::default(); let config = Config { env, db: None }; config } diff --git a/crates/libs/cerium/src/env.rs b/crates/libs/cerium/src/env.rs index 9ceb958..33f7c95 100644 --- a/crates/libs/cerium/src/env.rs +++ b/crates/libs/cerium/src/env.rs @@ -7,24 +7,21 @@ use serde::Deserialize; #[allow(unused)] pub struct Environment { pub debug: bool, - pub connection: Connection, + pub database_uri: String, + pub redis_uri: String, + pub selenium_uri: String, + pub encryption_salt: String } -#[derive(Debug, Deserialize, Clone)] -#[allow(unused)] -pub struct Connection { - pub database: String, - pub selenium: String, -} impl Environment { - pub fn new() -> Self { - let run_mode = env::var("RUN_MODE").unwrap_or_else(|_| "development".into()); - let result_config = CConfig::builder() - .add_source(File::with_name("./config/default")) - .add_source(File::with_name(&format!("./config/{}", run_mode)).required(false)) - .build(); - let _new = result_config.expect("Error from Environment"); - _new.try_deserialize().expect("Error from Environment") + pub fn default() -> Self { + Environment { + debug: env::var("DEBUG").unwrap_or("false".to_string()).parse().unwrap(), + database_uri: env::var("DATABASE_URI").unwrap_or("".to_string()), + redis_uri: env::var("REDIS_URI").unwrap_or("".to_string()), + selenium_uri: env::var("SELENIUM_URI").unwrap_or("".to_string()), + encryption_salt: env::var("ENCRYPTION_SALT").unwrap_or("".to_string()), + } } } diff --git a/crates/services/api/src/main.rs b/crates/services/api/src/main.rs index 609e029..5be654c 100644 --- a/crates/services/api/src/main.rs +++ b/crates/services/api/src/main.rs @@ -1,9 +1,11 @@ +use std::env; use std::sync::Arc; use sea_orm::{DatabaseConnection, DbErr}; use tracing::Level; use cerium::client::Client; +use cerium::env::Environment; use cerium::server::App; use migration::MigratorTrait; @@ -22,14 +24,17 @@ pub(crate) async fn run_migration(db: &DatabaseConnection) -> Result<(), DbErr> .expect("TODO: panic message"); Ok(()) } +pub(crate) async fn get_config() -> Client { + let env = Environment::default(); + Client::new( + Some(env.database_uri), + Some(env.redis_uri), + ).await +} #[tokio::main] async fn main() { - let cli = Client::new( - Some("postgres://root:root@localhost:5432/orca".to_string()), - None, - ) - .await; + let cli = get_config().await; let mut app = App::new("OrcaWeb", cli.clone()); app.set_logger(Level::DEBUG); app.set_port(8080);