From 4ec01dbeb5308c796e19299a0b569527235e83f7 Mon Sep 17 00:00:00 2001 From: Fankai Liu Date: Thu, 26 Oct 2023 22:46:26 +0800 Subject: [PATCH 1/3] refactor code --- src/template/src/app_error.hbs | 4 + src/template/src/db.hbs | 42 +++++- src/utils/create_project.rs | 258 +++++++++++++++++---------------- src/utils/get_selection.rs | 8 +- 4 files changed, 177 insertions(+), 135 deletions(-) diff --git a/src/template/src/app_error.hbs b/src/template/src/app_error.hbs index 87e318e..a6050f7 100644 --- a/src/template/src/app_error.hbs +++ b/src/template/src/app_error.hbs @@ -35,6 +35,10 @@ pub enum AppError { #[error("diesel::result::Error:`{0}`")] DieselErr(#[from] diesel::result::Error), {{/if}} + {{#if is_rbatis}} + #[error("rbatis::Error:`{0}`")] + RbatisErr(#[from] rbatis::Error), + {{/if}} } pub type AppResult = Result; diff --git a/src/template/src/db.hbs b/src/template/src/db.hbs index a76085e..00c0179 100644 --- a/src/template/src/db.hbs +++ b/src/template/src/db.hbs @@ -89,4 +89,44 @@ pub async fn init_db_conn() { }) .await; } -{{/if}} \ No newline at end of file +{{/if}} + +{{#if is_rbatis}} +use tokio::sync::OnceCell; +use rbatis::rbatis::RBatis; +pub static DB: OnceCell = OnceCell::const_new(); + +pub async fn init_db_conn() { + DB.get_or_init(|| async { + let rb = RBatis::new(); + + {{#if is_pg}} + // PostgreSQL + rb.init(rbdc_pg::driver::PgDriver {}, &CFG.database.database_url).unwrap(); + {{else if is_mysql}} + // MySQL + rb.init(rbdc_mysql::driver::MysqlDriver {}, &CFG.database.database_url).unwrap(); + {{else if is_sqlite}} + // SQLite + rb.init(rbdc_sqlite::driver::SqliteDriver {}, &CFG.database.database_url).unwrap(); + {{else if is_mssql}} + // MS SQL + rb.init(rbdc_mssql::driver::MssqlDriver {}, &CFG.database.database_url).unwrap(); + {{/if}} + + let sql_file = match rb.driver_type().unwrap() { + "sqlite" => "./data/table_sqlite.sql", + "postgres" => "./data/table_postgres.sql", + "mysql" => "./data/table_mysql.sql", + "mssql" => "./data/table_mssql.sql", + _ => { "" } + }; + if sql_file != "" { + let sql = std::fs::read_to_string(sql_file).unwrap(); + let _ = rb.exec(&sql, vec![]).await; + } + return rb; + }) + .await; +} +{{/if}} diff --git a/src/utils/create_project.rs b/src/utils/create_project.rs index 5513dab..7d98421 100644 --- a/src/utils/create_project.rs +++ b/src/utils/create_project.rs @@ -9,7 +9,7 @@ use std::{ ffi::{OsStr, OsString}, fs::{self, File}, io::Write, - path::Path, + path::{Path, PathBuf}, slice, }; @@ -81,6 +81,7 @@ fn write_project_file( let is_mysql = user_selected.db_type == DbType::Mysql; let is_postgres = user_selected.db_type == DbType::Postgres; let is_sqlite = user_selected.db_type == DbType::Sqlite; + let is_mssql = user_selected.db_type == DbType::Mssql; let is_sea_orm_or_sqlx = is_sea_orm || is_sqlx; let mut data = json!({ "project_name": project.project_name, @@ -109,6 +110,7 @@ fn write_project_file( "is_mysql":is_mysql, "is_postgres":is_postgres, "is_sqlite":is_sqlite, + "is_mssql":is_mssql, "is_sea_orm":is_sea_orm, "is_sea_orm_or_sqlx":is_sea_orm_or_sqlx, "is_diesel":is_diesel, @@ -139,90 +141,15 @@ fn write_project_file( }); let mut dependencies = data["dependencies"].clone(); handle_dependencies( - &mut dependencies, + &mut dependencies, need_db_conn, user_selected.db_type, user_selected.db_conn_type, ); data["dependencies"] = dependencies; - - std::fs::create_dir_all(project_path)?; - - let src_path = project_path.join("src"); - //src - std::fs::create_dir_all(&src_path)?; - //src/main.rs - let main_file_path = src_path.join("main.rs"); - let main_template = include_str!("../template/src/main_template.hbs"); - let main_rendered = handlebars.render_template(main_template, &data)?; - let mut main_file = File::create(main_file_path)?; - main_file.write_all(main_rendered.as_bytes())?; - //src/Cargo.toml - let cargo_file_path = project_path.join("Cargo.toml"); - let cargo_template = include_str!("../template/src/cargo_template.hbs"); - let cargo_rendered = handlebars.render_template(cargo_template, &data)?; - let mut cargo_file = File::create(cargo_file_path)?; - cargo_file.write_all(cargo_rendered.as_bytes())?; - //src/config.rs - let config_template = include_str!("../template/src/config_template.hbs"); - let config_rendered = handlebars.render_template(config_template, &data)?; - let mut config_file = File::create(src_path.join("config.rs"))?; - config_file.write_all(config_rendered.as_bytes())?; - //src/app_error.rs - let app_error_template = include_str!("../template/src/app_error.hbs"); - let app_error_rendered = handlebars.render_template(app_error_template, &data)?; - let mut app_error_file = File::create(src_path.join("app_error.rs"))?; - app_error_file.write_all(app_error_rendered.as_bytes())?; - if need_db_conn { - //src/db.rs - let db_template = include_str!("../template/src/db.hbs"); - let db_rendered = handlebars.render_template(db_template, &data)?; - let mut db_file = File::create(src_path.join("db.rs"))?; - db_file.write_all(db_rendered.as_bytes())?; - } - //src/app_response.rs - let app_response_template = include_str!("../template/src/app_response.hbs"); - let app_response_rendered = handlebars.render_template(app_response_template, &data)?; - let mut app_response_file = File::create(src_path.join("app_response.rs"))?; - app_response_file.write_all(app_response_rendered.as_bytes())?; + let (src_path, router_path) = create_basic_file(project_path, &handlebars, &data)?; - //src/middleware - let middleware_path = src_path.join("middleware"); - std::fs::create_dir_all(&middleware_path)?; - let jwt_bytes = include_bytes!("../template/src/middleware/jwt.rs"); - let mut jwt_file = File::create(middleware_path.join("jwt.rs"))?; - jwt_file.write_all(jwt_bytes)?; - //src/middleware/mod.rs - let mod_bytes = include_bytes!("../template/src/middleware/mod.rs"); - let mut mod_file = File::create(middleware_path.join("mod.rs"))?; - mod_file.write_all(mod_bytes)?; - //src/middleware/handle404.rs - let handle404_template = include_str!("../template/src/middleware/handle_404.hbs"); - let handle404_rendered = handlebars.render_template(handle404_template, &data)?; - let mut handle404_file = File::create(middleware_path.join("handle_404.rs"))?; - handle404_file.write_all(handle404_rendered.as_bytes())?; - - //config - let config_path = project_path.join("config"); - std::fs::create_dir_all(&config_path)?; - //config/config.toml - let config_template = include_str!("../template/config/config.hbs"); - let config_toml_rendered = handlebars.render_template(config_template, &data)?; - let mut config_file = File::create(config_path.join("config.toml"))?; - config_file.write_all(config_toml_rendered.as_bytes())?; - //config/certs - let cert_path = config_path.join("certs"); - std::fs::create_dir_all(&cert_path)?; - //config/certs/cert.pem - let cert_template = include_str!("../template/config/certs/cert.pem"); - let mut cert_file = File::create(cert_path.join("cert.pem"))?; - cert_file.write_all(cert_template.as_bytes())?; - //config/certs/key.pem - let key_path = cert_path.join("key.pem"); - let key_template = include_str!("../template/config/certs/key.pem"); - let mut key_file = File::create(key_path)?; - key_file.write_all(key_template.as_bytes())?; if is_web_site { //templates let template_path = project_path.join("templates"); @@ -241,6 +168,12 @@ fn write_project_file( handle_404_file.write_all(handle_404_template_rendered.as_bytes())?; if need_db_conn { + //src/db.rs + let db_template = include_str!("../template/src/db.hbs"); + let db_rendered = handlebars.render_template(db_template, &data)?; + let mut db_file = File::create(src_path.join("db.rs"))?; + db_file.write_all(db_rendered.as_bytes())?; + //template/login.html let login_template = include_str!("../template/templates/login.hbs"); let login_template_rendered = handlebars.render_template(login_template, &data)?; @@ -267,28 +200,12 @@ fn write_project_file( user_list_page_file.write_all(user_list_page_template_rendered.as_bytes())?; } } - //src/router - let router_path = src_path.join("routers"); - std::fs::create_dir_all(&router_path)?; - //src/router/mod.rs - let router_mod_template = include_str!("../template/src/routers/mod.hbs"); - let router_mod_rendered = handlebars.render_template(router_mod_template, &data)?; - let mut router_mod_file = File::create(router_path.join("mod.rs"))?; - router_mod_file.write_all(router_mod_rendered.as_bytes())?; - //src/router/demo.rs - let router_demo_template = include_str!("../template/src/routers/demo.hbs"); - let router_demo_rendered = handlebars.render_template(router_demo_template, &data)?; - let mut router_demo_file = File::create(router_path.join("demo.rs"))?; - router_demo_file.write_all(router_demo_rendered.as_bytes())?; if need_db_conn { //src/router/user.rs let router_user_template = include_str!("../template/src/routers/user.hbs"); let router_user_rendered = handlebars.render_template(router_user_template, &data)?; let mut router_user_file = File::create(router_path.join("user.rs"))?; router_user_file.write_all(router_user_rendered.as_bytes())?; - } - - if need_db_conn { //src/services let services_path = src_path.join("services"); std::fs::create_dir_all(&services_path)?; @@ -522,47 +439,96 @@ fn write_project_file( Ok(()) } -fn check_name(name: &str) -> Result<()> { - restricted_names::validate_package_name(name, "package name")?; +fn create_basic_file( + project_path: &Path, + handlebars: &Handlebars<'_>, + data: &serde_json::Value, +) -> Result<(PathBuf, PathBuf)> { + std::fs::create_dir_all(project_path)?; + let src_path = project_path.join("src"); + std::fs::create_dir_all(&src_path)?; + let main_file_path = src_path.join("main.rs"); + let main_template = include_str!("../template/src/main_template.hbs"); + let main_rendered = handlebars.render_template(main_template, data)?; + let mut main_file = File::create(main_file_path)?; + main_file.write_all(main_rendered.as_bytes())?; + let cargo_file_path = project_path.join("Cargo.toml"); + let cargo_template = include_str!("../template/src/cargo_template.hbs"); + let cargo_rendered = handlebars.render_template(cargo_template, data)?; + let mut cargo_file = File::create(cargo_file_path)?; + cargo_file.write_all(cargo_rendered.as_bytes())?; + let config_template = include_str!("../template/src/config_template.hbs"); + let config_rendered = handlebars.render_template(config_template, data)?; + let mut config_file = File::create(src_path.join("config.rs"))?; + config_file.write_all(config_rendered.as_bytes())?; + let app_error_template = include_str!("../template/src/app_error.hbs"); + let app_error_rendered = handlebars.render_template(app_error_template, data)?; + let mut app_error_file = File::create(src_path.join("app_error.rs"))?; + app_error_file.write_all(app_error_rendered.as_bytes())?; + //src/app_response.rs + let app_response_template = include_str!("../template/src/app_response.hbs"); + let app_response_rendered = handlebars.render_template(app_response_template, &data)?; + let mut app_response_file = File::create(src_path.join("app_response.rs"))?; + app_response_file.write_all(app_response_rendered.as_bytes())?; - if restricted_names::is_keyword(name) { - anyhow::bail!(t!("error_is_keyword", name = name)); - } - if restricted_names::is_conflicting_artifact_name(name) { - warning(t!("error_is_conflicting_artifact_name", name = name).replace(r"\n", "\n")); - } - if name == "test" { - anyhow::bail!(t!("error_equal_test").replace(r"\n", "\n")) - } - if ["core", "std", "alloc", "proc_macro", "proc-macro"].contains(&name) { - warning(t!("error_part_of_standard_library", name = name,).replace(r"\n", "\n")); - } - if restricted_names::is_windows_reserved(name) { - if cfg!(windows) { - anyhow::bail!(t!("error_is_windows_reserved", name = name),); - } else { - warning(t!("warning_is_windows_reserved", name = name).replace(r"\n", "\n")); - } - } - if restricted_names::is_non_ascii_name(name) { - warning(t!("warning_is_non_ascii_name", name = name).replace(r"\n", "\n")); - } - Ok(()) -} -fn check_path(path: &Path) -> Result<()> { - // warn if the path contains characters that will break `env::join_paths` - if join_paths(slice::from_ref(&OsStr::new(path)), "").is_err() { - let path = path.to_string_lossy(); - print_util::warning(t!("warning_invalid_path", path = path)); - } - Ok(()) + //src/middleware + let middleware_path = src_path.join("middleware"); + std::fs::create_dir_all(&middleware_path)?; + let jwt_bytes = include_bytes!("../template/src/middleware/jwt.rs"); + let mut jwt_file = File::create(middleware_path.join("jwt.rs"))?; + jwt_file.write_all(jwt_bytes)?; + //src/middleware/mod.rs + let mod_bytes = include_bytes!("../template/src/middleware/mod.rs"); + let mut mod_file = File::create(middleware_path.join("mod.rs"))?; + mod_file.write_all(mod_bytes)?; + //src/middleware/handle404.rs + let handle404_template = include_str!("../template/src/middleware/handle_404.hbs"); + let handle404_rendered = handlebars.render_template(handle404_template, &data)?; + let mut handle404_file = File::create(middleware_path.join("handle_404.rs"))?; + handle404_file.write_all(handle404_rendered.as_bytes())?; + + //config + let config_path = project_path.join("config"); + std::fs::create_dir_all(&config_path)?; + //config/config.toml + let config_template = include_str!("../template/config/config.hbs"); + let config_toml_rendered = handlebars.render_template(config_template, &data)?; + let mut config_file = File::create(config_path.join("config.toml"))?; + config_file.write_all(config_toml_rendered.as_bytes())?; + //config/certs + let cert_path = config_path.join("certs"); + std::fs::create_dir_all(&cert_path)?; + //config/certs/cert.pem + let cert_template = include_str!("../template/config/certs/cert.pem"); + let mut cert_file = File::create(cert_path.join("cert.pem"))?; + cert_file.write_all(cert_template.as_bytes())?; + //config/certs/key.pem + let key_path = cert_path.join("key.pem"); + let key_template = include_str!("../template/config/certs/key.pem"); + let mut key_file = File::create(key_path)?; + key_file.write_all(key_template.as_bytes())?; + //src/router + let router_path = src_path.join("routers"); + std::fs::create_dir_all(&router_path)?; + //src/router/mod.rs + let router_mod_template = include_str!("../template/src/routers/mod.hbs"); + let router_mod_rendered = handlebars.render_template(router_mod_template, &data)?; + let mut router_mod_file = File::create(router_path.join("mod.rs"))?; + router_mod_file.write_all(router_mod_rendered.as_bytes())?; + //src/router/demo.rs + let router_demo_template = include_str!("../template/src/routers/demo.hbs"); + let router_demo_rendered = handlebars.render_template(router_demo_template, &data)?; + let mut router_demo_file = File::create(router_path.join("demo.rs"))?; + router_demo_file.write_all(router_demo_rendered.as_bytes())?; + + Ok((src_path, router_path)) } fn handle_dependencies( dependencies: &mut serde_json::Value, need_db_conn: bool, db_type: DbType, - conn_type: DbConnectionType + conn_type: DbConnectionType, ) { if need_db_conn { match (conn_type, db_type) { @@ -674,6 +640,42 @@ fn handle_dependencies( } } +fn check_name(name: &str) -> Result<()> { + restricted_names::validate_package_name(name, "package name")?; + + if restricted_names::is_keyword(name) { + anyhow::bail!(t!("error_is_keyword", name = name)); + } + if restricted_names::is_conflicting_artifact_name(name) { + warning(t!("error_is_conflicting_artifact_name", name = name).replace(r"\n", "\n")); + } + if name == "test" { + anyhow::bail!(t!("error_equal_test").replace(r"\n", "\n")) + } + if ["core", "std", "alloc", "proc_macro", "proc-macro"].contains(&name) { + warning(t!("error_part_of_standard_library", name = name,).replace(r"\n", "\n")); + } + if restricted_names::is_windows_reserved(name) { + if cfg!(windows) { + anyhow::bail!(t!("error_is_windows_reserved", name = name),); + } else { + warning(t!("warning_is_windows_reserved", name = name).replace(r"\n", "\n")); + } + } + if restricted_names::is_non_ascii_name(name) { + warning(t!("warning_is_non_ascii_name", name = name).replace(r"\n", "\n")); + } + Ok(()) +} +fn check_path(path: &Path) -> Result<()> { + // warn if the path contains characters that will break `env::join_paths` + if join_paths(slice::from_ref(&OsStr::new(path)), "").is_err() { + let path = path.to_string_lossy(); + print_util::warning(t!("warning_invalid_path", path = path)); + } + Ok(()) +} + pub fn join_paths>(paths: &[T], env: &str) -> Result { env::join_paths(paths.iter()).with_context(|| { let mut message = t!("erroe_join_paths", env = env).replace(r"\n", "\n"); diff --git a/src/utils/get_selection.rs b/src/utils/get_selection.rs index fc434b2..002dfc8 100644 --- a/src/utils/get_selection.rs +++ b/src/utils/get_selection.rs @@ -61,13 +61,9 @@ pub fn get_user_selected() -> Result> { db_conn_type, })); } - let mut db_types: Vec<&str> = vec![ - "sqlite", "mysql", "postgres", - ]; + let mut db_types: Vec<&str> = vec!["sqlite", "mysql", "postgres"]; if db_conn_type == DbConnectionType::Rbatis { - db_types = vec![ - "sqlite", "mysql", "postgres", "mssql", - ]; + db_types = vec!["sqlite", "mysql", "postgres", "mssql"]; } let db_type_selection = Select::with_theme(&theme) .with_prompt(t!("select_db_type").replace(r"\n", "\n")) From c39a31b0e1662678fb48fa08fa130a403214ae4b Mon Sep 17 00:00:00 2001 From: Fankai Liu Date: Thu, 26 Oct 2023 23:07:28 +0800 Subject: [PATCH 2/3] add rbatis template --- src/template/data/table_mssql.sql | 15 ++++++ src/template/data/table_mysql.sql | 9 ++++ src/template/data/table_postgres.sql | 9 ++++ src/template/data/table_sqlite.sql | 9 ++++ src/template/src/entities/mod.hbs | 3 ++ src/template/src/entities/user.hbs | 11 ++++ src/template/src/services/user.hbs | 80 ++++++++++++++++++++++++++++ src/utils/create_project.rs | 12 ++--- 8 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 src/template/data/table_mssql.sql create mode 100644 src/template/data/table_mysql.sql create mode 100644 src/template/data/table_postgres.sql create mode 100644 src/template/data/table_sqlite.sql diff --git a/src/template/data/table_mssql.sql b/src/template/data/table_mssql.sql new file mode 100644 index 0000000..5a4821f --- /dev/null +++ b/src/template/data/table_mssql.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS users +( +id TEXT PRIMARY KEY NOT NULL, +username VARCHAR(255) NOT NULL UNIQUE, +password VARCHAR(511) NOT NULL +); +BEGIN; +MERGE INTO users AS target +USING (VALUES ('cdd0e080-5bb1-4442-b6f7-2ba60dbd0555', 'zhangsan', '$argon2id$v=19$m=19456,t=2,p=1$rcosL5pOPdA2c7i4ZuLA4Q$s0JGh78UzMmu1qZMpVUA3b8kWYLXcZhw7uBfwhYDJ4A')) +AS source (id, username, password) +ON (target.id = source.id) +WHEN NOT MATCHED THEN +INSERT (id, username, password) +VALUES (source.id, source.username, source.password); +COMMIT; \ No newline at end of file diff --git a/src/template/data/table_mysql.sql b/src/template/data/table_mysql.sql new file mode 100644 index 0000000..6465896 --- /dev/null +++ b/src/template/data/table_mysql.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS users +( +id TEXT PRIMARY KEY NOT NULL, +username VARCHAR(255) NOT NULL UNIQUE, +password VARCHAR(511) NOT NULL +); +BEGIN; +INSERT IGNORE INTO "users" ("id", "username", "password") VALUES ('cdd0e080-5bb1-4442-b6f7-2ba60dbd0555', 'zhangsan', '$argon2id$v=19$m=19456,t=2,p=1$rcosL5pOPdA2c7i4ZuLA4Q$s0JGh78UzMmu1qZMpVUA3b8kWYLXcZhw7uBfwhYDJ4A'); +COMMIT; \ No newline at end of file diff --git a/src/template/data/table_postgres.sql b/src/template/data/table_postgres.sql new file mode 100644 index 0000000..fde43c2 --- /dev/null +++ b/src/template/data/table_postgres.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS users +( +id TEXT PRIMARY KEY NOT NULL, +username VARCHAR(255) NOT NULL UNIQUE, +password VARCHAR(511) NOT NULL +); +BEGIN; +INSERT INTO "users" ("id", "username", "password") VALUES ('cdd0e080-5bb1-4442-b6f7-2ba60dbd0555', 'zhangsan', '$argon2id$v=19$m=19456,t=2,p=1$rcosL5pOPdA2c7i4ZuLA4Q$s0JGh78UzMmu1qZMpVUA3b8kWYLXcZhw7uBfwhYDJ4A') ON CONFLICT DO NOTHING; +COMMIT; diff --git a/src/template/data/table_sqlite.sql b/src/template/data/table_sqlite.sql new file mode 100644 index 0000000..b59335a --- /dev/null +++ b/src/template/data/table_sqlite.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS users +( +id TEXT PRIMARY KEY NOT NULL, +username VARCHAR(255) NOT NULL UNIQUE, +password VARCHAR(511) NOT NULL +); +BEGIN; +INSERT OR IGNORE INTO "users" ("id", "username", "password") VALUES ('cdd0e080-5bb1-4442-b6f7-2ba60dbd0555', 'zhangsan', '$argon2id$v=19$m=19456,t=2,p=1$rcosL5pOPdA2c7i4ZuLA4Q$s0JGh78UzMmu1qZMpVUA3b8kWYLXcZhw7uBfwhYDJ4A'); +COMMIT; diff --git a/src/template/src/entities/mod.hbs b/src/template/src/entities/mod.hbs index 2fff605..169dff8 100644 --- a/src/template/src/entities/mod.hbs +++ b/src/template/src/entities/mod.hbs @@ -8,3 +8,6 @@ pub mod prelude; pub mod user; {{/if}} +{{#if is_rbatis}} +pub mod user; +{{/if}} \ No newline at end of file diff --git a/src/template/src/entities/user.hbs b/src/template/src/entities/user.hbs index 218a0aa..3392071 100644 --- a/src/template/src/entities/user.hbs +++ b/src/template/src/entities/user.hbs @@ -29,4 +29,15 @@ pub struct Model { pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} +{{/if}} +{{#if is_rbatis}} +use rbatis::crud; +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +pub struct Users{ + pub id: String, + pub username: String, + pub password: String, +} + +crud!(Users {}); {{/if}} \ No newline at end of file diff --git a/src/template/src/services/user.hbs b/src/template/src/services/user.hbs index 64b6796..92330ad 100644 --- a/src/template/src/services/user.hbs +++ b/src/template/src/services/user.hbs @@ -350,4 +350,84 @@ pub async fn users() -> AppResult> { Ok(res) } +{{/if}} +{{#if is_rbatis}} +use uuid::Uuid; + +use crate::{ + app_error::AppResult, + dtos::user::{ + UserAddRequest, UserLoginRequest, UserLoginResponse, UserResponse, UserUpdateRequest, + }, + middleware::jwt::get_token, + utils::rand_utils, db::DB, entity::user::Users, +}; + +pub async fn add_user(req: UserAddRequest) -> AppResult { + let db = DB.get().ok_or(anyhow::anyhow!("数据库连接失败"))?; + let user = Users { + id: Uuid::new_v4().to_string(), + username: req.username.clone(), + password: rand_utils::hash_password(req.password).await?, + }; + Users::insert(db,&user).await?; + + Ok(UserResponse { + id: user.id, + username: user.username, + }) +} + +pub async fn login(req: UserLoginRequest) -> AppResult { + let db = DB.get().ok_or(anyhow::anyhow!("数据库连接失败"))?; + let user = Users::select_by_column(db,"username",&req.username).await?; + if user.len()==0 { + return Err(anyhow::anyhow!("用户不存在").into()); + } + if rand_utils::verify_password(req.password, user[0].password.clone()).await.is_err() { + return Err(anyhow::anyhow!("密码不正确").into()); + } + let (token, exp) = get_token(user[0].username.clone(), user[0].id.clone())?; + let res = UserLoginResponse { + id: user[0].id.clone(), + username: user[0].username.clone(), + token, + exp, + }; + Ok(res) +} + +pub async fn update_user(req: UserUpdateRequest) -> AppResult { + let db = DB.get().ok_or(anyhow::anyhow!("数据库连接失败"))?; + let user = Users::select_by_column(db,"id",&req.id).await?; + if user.len()==0 { + return Err(anyhow::anyhow!("用户不存在").into()); + } + Users::update_by_column(db,&user[0],"id").await?; + + Ok(UserResponse { + id: user[0].id.clone(), + username: user[0].username.clone(), + }) +} + +pub async fn delete_user(req: String) -> AppResult<()> { + let db = DB.get().ok_or(anyhow::anyhow!("数据库连接失败"))?; + Users::delete_by_column(db, "id",&req).await?; + Ok(()) +} + +pub async fn users() -> AppResult> { + let db = DB.get().ok_or(anyhow::anyhow!("数据库连接失败"))?; + let users=Users::select_all(db).await?; + + let res = users + .into_iter() + .map(|user| UserResponse { + id: user.id, + username: user.username, + }) + .collect::>(); + Ok(res) +} {{/if}} \ No newline at end of file diff --git a/src/utils/create_project.rs b/src/utils/create_project.rs index 7d98421..233383d 100644 --- a/src/utils/create_project.rs +++ b/src/utils/create_project.rs @@ -168,12 +168,6 @@ fn write_project_file( handle_404_file.write_all(handle_404_template_rendered.as_bytes())?; if need_db_conn { - //src/db.rs - let db_template = include_str!("../template/src/db.hbs"); - let db_rendered = handlebars.render_template(db_template, &data)?; - let mut db_file = File::create(src_path.join("db.rs"))?; - db_file.write_all(db_rendered.as_bytes())?; - //template/login.html let login_template = include_str!("../template/templates/login.hbs"); let login_template_rendered = handlebars.render_template(login_template, &data)?; @@ -201,6 +195,12 @@ fn write_project_file( } } if need_db_conn { + //src/db.rs + let db_template = include_str!("../template/src/db.hbs"); + let db_rendered = handlebars.render_template(db_template, &data)?; + let mut db_file = File::create(src_path.join("db.rs"))?; + db_file.write_all(db_rendered.as_bytes())?; + //src/router/user.rs let router_user_template = include_str!("../template/src/routers/user.hbs"); let router_user_rendered = handlebars.render_template(router_user_template, &data)?; From c9f0a0ae3b70dfa2286ae94692ae98452fb8ecfe Mon Sep 17 00:00:00 2001 From: Fankai Liu Date: Fri, 27 Oct 2023 20:44:45 +0800 Subject: [PATCH 3/3] add rbatis template --- locales/code_comment.yml | 18 +++++++++ src/template/config/config.hbs | 17 ++++++++- src/template/src/db.hbs | 11 ++++-- src/template/src/main_template.hbs | 9 +++++ src/template/src/services/user.hbs | 2 +- src/utils/create_project.rs | 60 +++++++++++++++++++++++++++++- src/utils/get_selection.rs | 8 ++-- 7 files changed, 114 insertions(+), 11 deletions(-) diff --git a/locales/code_comment.yml b/locales/code_comment.yml index b3626ba..605811b 100644 --- a/locales/code_comment.yml +++ b/locales/code_comment.yml @@ -544,3 +544,21 @@ create_success_diesel__mysql_or_pgsql_fist_use: th: -- ขอโทษที่ทำให้คุณสับสน ข้างล่างนี้คือคำอธิบายในภาษาไทย:คุณต้องเปลี่ยนสตริงการเชื่อมต่อฐานข้อมูลใน .env และ config/config.toml ก่อนตรวจสอบว่าฐานข้อมูลมีอยู่จริง จากนั้นรันการย้ายของ diesel เพื่อคืนค่าฐานข้อมูล และรัน SQL ด้านล่างในฐานข้อมูลเพื่อเพิ่มข้อมูลเริ่มต้นหลังจากรัน คุณสามารถใช้ชื่อผู้ใช้เริ่มต้น:zhangsan และรหัสผ่าน:123 เพื่อเข้าถึง /loginสำหรับฟังก์ชันเพิ่มเติมของ diesel-cli โปรดดูที่ /migration/README.md. el: -- Παρακαλώ αλλάξτε πρώτα τη συμβολοσειρά σύνδεσης στη βάση δεδομένων στο .env και config/config.toml \n -- Βεβαιωθείτε ότι η βάση δεδομένων υπάρχει, στη συνέχεια εκτελέστε τη μετεγκατάσταση diesel για να επαναφέρετε τη βάση δεδομένων, και εκτελέστε το παρακάτω SQL στη βάση δεδομένων για να προσθέσετε τα προεπιλεγμένα δεδομένα. \n -- Μετά την εκτέλεση, μπορείτε να χρησιμοποιήσετε το προεπιλεγμένο όνομα χρήστη:zhangsan και τον κωδικό:123 για να έχετε πρόσβαση στο /login. \n -- Για περισσότερες λειτουργίες του diesel-cli, παρακαλώ δείτε το /migration/README.md. da: -- Ændre først forbindelsesstrengen til databasen i .env og config/config.toml \n -- Sørg for, at databasen eksisterer, kør derefter diesel migration run for at gendanne databasen, og kør den følgende SQL i databasen for at tilføje standarddataene. \n -- Efter kørsel, kan du bruge standard brugernavnet:zhangsan og adgangskoden:123 for at få adgang til /login. \n -- For mere funktionalitet fra diesel-cli, se venligst /migration/README.md. +create_success_rbatis: + en: 🎯 Reminder:Please modify the database connection string in the /config/config.toml file before running it + zh_CN: 🎯 提醒:在运行之前,请在 /config/config.toml 文件中修改数据库连接字符串 + zh_TW: 🎯 提醒:在運行之前,請在 /config/config.toml 文件中修改數據庫連接字符串 + fr: 🎯 Rappel:Veuillez modifier la chaîne de connexion à la base de données dans le fichier /config/config.toml avant de l'exécuter + ja: 🎯 リマインダー:実行する前に、/config/config.toml ファイル内のデータベース接続文字列を変更してください + es: 🎯 Recordatorio:Por favor modifique la cadena de conexión de la base de datos en el archivo /config/config.toml antes de ejecutarlo + de: 🎯 Erinnerung:Bitte ändern Sie die Datenbankverbindungszeichenfolge in der /config/config.toml-Datei, bevor Sie sie ausführen + ru: 🎯 Напоминание:Перед запуском измените строку подключения к базе данных в файле /config/config.toml + it: 🎯 Promemoria:Modificare la stringa di connessione al database nel file /config/config.toml prima di eseguirlo + pt: 🎯 Lembrete:Por favor, modifique a string de conexão do banco de dados no arquivo /config/config.toml antes de executá-lo + ko: 🎯 알림:실행하기 전에 /config/config.toml 파일에서 데이터베이스 연결 문자열을 수정하세요 + no: 🎯 Påminnelse:Vennligst endre databaseforbindelsesstrengen i /config/config.toml-filen før du kjører den + is: 🎯 Áminning:Vinsamlegast breyttu gagnagrunnstengistrenginu í /config/config.toml skránni áður en þú keyrir það + uk: 🎯 Нагадування:Будь ласка, змініть рядок підключення до бази даних у файлі /config/config.toml перед його запуском + th: 🎯 แจ้งเตือน:โปรดแก้ไขสตริงการเชื่อมต่อฐานข้อมูลในไฟล์ /config/config.toml ก่อนที่จะทำการรัน + el: 🎯 Υπενθύμιση:Παρακαλώ τροποποιήστε τη συμβολοσειρά σύνδεσης βάσης δεδομένων στο αρχείο /config/config.toml πριν το τρέξετε + da: 🎯 Påmindelse:Ændr venligst databaseforbindelsesstrengen i /config/config.toml-filen, før du kører den \ No newline at end of file diff --git a/src/template/config/config.hbs b/src/template/config/config.hbs index 4dc65a6..c0e6625 100644 --- a/src/template/config/config.hbs +++ b/src/template/config/config.hbs @@ -25,7 +25,22 @@ database_url="file:data/test.db" {{#if is_mysql}} database_url="mysql://root:123@127.0.0.1:3306/diesel_example" {{/if}} -{{/if}}{{/if}} +{{/if}} +{{#if is_rbatis}} +{{#if is_postgres}} +database_url=postgres://liufankai:1@localhost/rbatis_example +{{/if}} +{{#if is_sqlite}} +database_url="data/rbatis_sqlite.db" +{{/if}} +{{#if is_mysql}} +database_url="mysql://root:123@127.0.0.1:3306/rbatis_example" +{{/if}} +{{#if is_mssql}} +database_url="mssql://SA:TestPass!123456@localhost:1433/rbatis_example" +{{/if}} +{{/if}} +{{/if}} [jwt] jwt_secret = "secret" jwt_exp = 6000 diff --git a/src/template/src/db.hbs b/src/template/src/db.hbs index 00c0179..a0048b0 100644 --- a/src/template/src/db.hbs +++ b/src/template/src/db.hbs @@ -100,16 +100,19 @@ pub async fn init_db_conn() { DB.get_or_init(|| async { let rb = RBatis::new(); - {{#if is_pg}} + {{#if is_postgres}} // PostgreSQL rb.init(rbdc_pg::driver::PgDriver {}, &CFG.database.database_url).unwrap(); - {{else if is_mysql}} + {{/if}} + {{#if is_mysql}} // MySQL rb.init(rbdc_mysql::driver::MysqlDriver {}, &CFG.database.database_url).unwrap(); - {{else if is_sqlite}} + {{/if}} + {{#if is_sqlite}} // SQLite rb.init(rbdc_sqlite::driver::SqliteDriver {}, &CFG.database.database_url).unwrap(); - {{else if is_mssql}} + {{/if}} + {{#if is_mssql}} // MS SQL rb.init(rbdc_mssql::driver::MssqlDriver {}, &CFG.database.database_url).unwrap(); {{/if}} diff --git a/src/template/src/main_template.hbs b/src/template/src/main_template.hbs index a74eacc..92c9939 100644 --- a/src/template/src/main_template.hbs +++ b/src/template/src/main_template.hbs @@ -1,6 +1,9 @@ {{#if is_sea_orm_or_sqlx}} use crate::db::init_db_conn; {{/if}} +{{#if is_rbatis}} +use crate::db::init_db_conn; +{{/if}} use crate::middleware::handle_404::handle_404; use crate::routers::router; use config::{CERT_KEY, CFG}; @@ -28,6 +31,9 @@ mod entities; mod models; mod schema; {{/if}} +{{#if is_rbatis}} +mod entities; +{{/if}} mod middleware; mod routers; @@ -38,6 +44,9 @@ async fn main() { {{#if is_sea_orm_or_sqlx}} init_db_conn().await; {{/if}} + {{#if is_rbatis}} + init_db_conn().await; + {{/if}} let (tx, rx) = oneshot::channel(); let router = router(); let service: Service = router.into(); diff --git a/src/template/src/services/user.hbs b/src/template/src/services/user.hbs index 92330ad..4860e36 100644 --- a/src/template/src/services/user.hbs +++ b/src/template/src/services/user.hbs @@ -360,7 +360,7 @@ use crate::{ UserAddRequest, UserLoginRequest, UserLoginResponse, UserResponse, UserUpdateRequest, }, middleware::jwt::get_token, - utils::rand_utils, db::DB, entity::user::Users, + utils::rand_utils, db::DB, entities::user::Users, }; pub async fn add_user(req: UserAddRequest) -> AppResult { diff --git a/src/utils/create_project.rs b/src/utils/create_project.rs index 233383d..af1a340 100644 --- a/src/utils/create_project.rs +++ b/src/utils/create_project.rs @@ -59,10 +59,15 @@ pub fn create_project(project: Project) -> Result<()> { success(t!("create_success_mysql_or_pgsql").replace(r"\n", "\n")); } } + match (config.db_conn_type, config.db_type) { + (DbConnectionType::Rbatis, DbType::Mysql | DbType::Postgres | DbType::Mssql) => { + success(t!("create_success_rbatis")); + } + (_, _) => {} + } } None => anyhow::bail!("cli quit!"), } - Ok(()) } @@ -435,6 +440,55 @@ fn write_project_file( test_db_file.write_all(demo_db_bytes)?; } } + if is_rbatis { + //src/entities + let entities_path = src_path.join("entities"); + std::fs::create_dir_all(&entities_path)?; + //src/entities/mod.rs + let entities_mod_template = include_str!("../template/src/entities/mod.hbs"); + let entities_mod_rendered = handlebars.render_template(entities_mod_template, &data)?; + let mut entities_mod_file = File::create(entities_path.join("mod.rs"))?; + entities_mod_file.write_all(entities_mod_rendered.as_bytes())?; + + //src/entities/user.rs + let entities_user_template = include_str!("../template/src/entities/user.hbs"); + let entities_user_rendered = + handlebars.render_template(entities_user_template, &data)?; + let mut entities_user_file = File::create(entities_path.join("user.rs"))?; + entities_user_file.write_all(entities_user_rendered.as_bytes())?; + + //data + let data_path = project_path.join("data"); + std::fs::create_dir_all(&data_path)?; + match user_selected.db_type { + DbType::Sqlite => { + //data/table_sqlite.sql + let table_sqlite_template = include_bytes!("../template/data/table_sqlite.sql"); + let mut table_sqlite_file = File::create(data_path.join("table_sqlite.sql"))?; + table_sqlite_file.write_all(table_sqlite_template)?; + } + DbType::Mysql => { + //data/table_mysql.sql + let table_mysql_template = include_bytes!("../template/data/table_mysql.sql"); + let mut table_mysql_file = File::create(data_path.join("table_mysql.sql"))?; + table_mysql_file.write_all(table_mysql_template)?; + } + DbType::Postgres => { + //data/table_postgres.sql + let table_postgres_template = + include_bytes!("../template/data/table_postgres.sql"); + let mut table_postgres_file = + File::create(data_path.join("table_postgres.sql"))?; + table_postgres_file.write_all(table_postgres_template)?; + } + DbType::Mssql => { + //data/table_mssql.sql + let table_mssql_template = include_bytes!("../template/data/table_mssql.sql"); + let mut table_mssql_file = File::create(data_path.join("table_mssql.sql"))?; + table_mssql_file.write_all(table_mssql_template)?; + } + } + } } Ok(()) } @@ -587,6 +641,7 @@ fn handle_dependencies( }); } (DbConnectionType::Rbatis, DbType::Mysql) => { + dependencies["rbs"] = json!({"version":"4.4"}); dependencies["rbdc-mysql"] = json!({ "version": "4.4" }); @@ -596,6 +651,7 @@ fn handle_dependencies( }); } (DbConnectionType::Rbatis, DbType::Postgres) => { + dependencies["rbs"] = json!({"version":"4.4"}); dependencies["rbdc-pg"] = json!({ "version": "4.4" }); @@ -605,6 +661,7 @@ fn handle_dependencies( }); } (DbConnectionType::Rbatis, DbType::Sqlite) => { + dependencies["rbs"] = json!({"version":"4.4"}); dependencies["rbdc-sqlite"] = json!({ "version": "4.4" }); @@ -614,6 +671,7 @@ fn handle_dependencies( }); } (DbConnectionType::Rbatis, DbType::Mssql) => { + dependencies["rbs"] = json!({"version":"4.4"}); dependencies["rbdc-mssql"] = json!({ "version": "4.4" }); diff --git a/src/utils/get_selection.rs b/src/utils/get_selection.rs index 002dfc8..8517102 100644 --- a/src/utils/get_selection.rs +++ b/src/utils/get_selection.rs @@ -2,7 +2,7 @@ use anyhow::Result; use dialoguer::{console::Style, theme::ColorfulTheme, Select}; use rust_i18n::t; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct UserSelected { pub template_type: TemplateType, pub db_type: DbType, @@ -84,13 +84,13 @@ pub fn get_user_selected() -> Result> { db_conn_type, })) } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum TemplateType { SalvoWebSite, SalvoWebApi, } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum DbType { Sqlite, Mysql, @@ -98,7 +98,7 @@ pub enum DbType { Mssql, } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum DbConnectionType { Sqlx, SeaOrm,