后端:精简JWT声明结构,优化用户注册功能,优化查询构建器
This commit is contained in:
parent
8071a16510
commit
33b53b3663
@ -16,3 +16,4 @@ ed25519-dalek = "2.1.1"
|
||||
rand = "0.8.5"
|
||||
chrono = "0.4"
|
||||
regex = "1.11.1"
|
||||
bcrypt = "0.16"
|
||||
|
@ -10,8 +10,7 @@ use rand::{SeedableRng, RngCore};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct CustomClaims {
|
||||
pub user_id: String,
|
||||
pub device_ua: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub enum SecretKey {
|
||||
|
@ -276,4 +276,28 @@ impl QueryBuilder {
|
||||
|
||||
Ok((sql, values))
|
||||
}
|
||||
pub fn fields(mut self, fields: Vec<ValidatedValue>) -> Self {
|
||||
self.fields = fields;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn params(mut self, params: HashMap<ValidatedValue, ValidatedValue>) -> Self {
|
||||
self.params = params;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn where_clause(mut self, clause: WhereClause) -> Self {
|
||||
self.where_clause = Some(clause);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn order_by(mut self, order: ValidatedValue) -> Self {
|
||||
self.order_by = Some(order);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn limit(mut self, limit: i32) -> Self {
|
||||
self.limit = Some(limit);
|
||||
self
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ impl Error for DatabaseError {}
|
||||
|
||||
#[async_trait]
|
||||
pub trait DatabaseTrait: Send + Sync {
|
||||
async fn connect(database: config::SqlConfig) -> Result<Self, Box<dyn Error>>
|
||||
async fn connect(database: &config::SqlConfig) -> Result<Self, Box<dyn Error>>
|
||||
where
|
||||
Self: Sized;
|
||||
async fn execute_query<'a>(
|
||||
@ -53,7 +53,7 @@ impl Database {
|
||||
&self.db
|
||||
}
|
||||
|
||||
pub async fn link(database: config::SqlConfig) -> Result<Self, Box<dyn Error>> {
|
||||
pub async fn link(database: &config::SqlConfig) -> Result<Self, Box<dyn Error>> {
|
||||
let db = match database.db_type.as_str() {
|
||||
"postgresql" => postgresql::Postgresql::connect(database).await?,
|
||||
_ => return Err("unknown database type".into()),
|
||||
|
@ -34,7 +34,7 @@ impl DatabaseTrait for Postgresql {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn connect(db_config: config::SqlConfig) -> Result<Self, Box<dyn Error>> {
|
||||
async fn connect(db_config: &config::SqlConfig) -> Result<Self, Box<dyn Error>> {
|
||||
let connection_str = format!(
|
||||
"postgres://{}:{}@{}:{}/{}",
|
||||
db_config.user, db_config.password, db_config.address, db_config.port, db_config.db_name
|
||||
|
0
backend/src/database/relational/uilts.rs
Normal file
0
backend/src/database/relational/uilts.rs
Normal file
@ -49,7 +49,7 @@ impl AppState {
|
||||
}
|
||||
|
||||
async fn link_sql(&self, config: config::SqlConfig) -> AppResult<()> {
|
||||
let database = relational::Database::link(config)
|
||||
let database = relational::Database::link(&config)
|
||||
.await
|
||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||
*self.db.lock().await = Some(database);
|
||||
@ -63,8 +63,7 @@ impl AppState {
|
||||
#[get("/system")]
|
||||
async fn token_system(_state: &State<AppState>) -> Result<status::Custom<String>, status::Custom<String>> {
|
||||
let claims = auth::jwt::CustomClaims {
|
||||
user_id: "system".into(),
|
||||
device_ua: "system".into(),
|
||||
name: "system".into(),
|
||||
};
|
||||
|
||||
auth::jwt::generate_jwt(claims, Duration::seconds(1))
|
||||
@ -73,6 +72,7 @@ async fn token_system(_state: &State<AppState>) -> Result<status::Custom<String>
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[launch]
|
||||
async fn rocket() -> _ {
|
||||
let config = config::Config::read().expect("Failed to read config");
|
||||
@ -94,11 +94,28 @@ async fn rocket() -> _ {
|
||||
|
||||
if ! config.info.install {
|
||||
rocket_builder = rocket_builder
|
||||
.mount("/", rocket::routes![routes::install]);
|
||||
.mount("/", rocket::routes![routes::intsall::install]);
|
||||
}
|
||||
|
||||
rocket_builder = rocket_builder
|
||||
.mount("/auth/token", routes![token_system]);
|
||||
.mount("/auth/token", rocket::routes![token_system])
|
||||
.mount("/", rocket::routes![routes::intsall::test]);
|
||||
|
||||
rocket_builder
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_placeholder() {
|
||||
let config = config::Config::read().expect("Failed to read config");
|
||||
|
||||
let state = AppState {
|
||||
db: Arc::new(Mutex::new(None)),
|
||||
configure: Arc::new(Mutex::new(config.clone())),
|
||||
};
|
||||
state.link_sql(config.sql_config.clone())
|
||||
.await
|
||||
.expect("Failed to connect to database");
|
||||
let sql=state.get_sql().await.expect("Failed to get sql");
|
||||
let _=routes::person::insert(&sql,routes::person::RegisterData{ name: String::from("test"), email: String::from("lsy22@vip.qq.com"), password:String::from("test") }).await.unwrap();
|
||||
}
|
||||
|
||||
|
@ -1,71 +1,93 @@
|
||||
use serde::{Deserialize,Serialize};
|
||||
use crate::{config,utils};
|
||||
use crate::database::{relational,relational::builder};
|
||||
use crate::database::relational;
|
||||
use crate::{AppState,AppError,AppResult};
|
||||
use rocket::{
|
||||
get, post,
|
||||
post,
|
||||
http::Status,
|
||||
response::status,
|
||||
serde::json::Json,
|
||||
State,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use crate::routes::person;
|
||||
use crate::auth;
|
||||
use chrono::Duration;
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct InstallData{
|
||||
pub struct InstallData{
|
||||
name:String,
|
||||
email:String,
|
||||
password:String,
|
||||
sql_config: config::SqlConfig
|
||||
|
||||
}
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct InstallReplyData{
|
||||
pub struct InstallReplyData{
|
||||
token:String,
|
||||
name:String,
|
||||
password:String,
|
||||
}
|
||||
|
||||
|
||||
#[post("/install", format = "application/json", data = "<data>")]
|
||||
async fn install(
|
||||
#[post("/test", format = "application/json", data = "<data>")]
|
||||
pub async fn test(
|
||||
data: Json<InstallData>,
|
||||
state: &State<AppState>
|
||||
) -> AppResult<status::Custom<Json<InstallReplyData>>, AppError> {
|
||||
) -> Result<status::Custom<String>, status::Custom<String>> {
|
||||
let data=data.into_inner();
|
||||
|
||||
|
||||
let sql= state.get_sql().await.map_err(|e| e)?;
|
||||
|
||||
let _ = person::insert(&sql,person::RegisterData{ name: data.name.clone(), email: data.email, password:data.password });
|
||||
Ok(status::Custom(Status::Ok, "Installation successful".to_string()))
|
||||
|
||||
}
|
||||
|
||||
#[post("/install", format = "application/json", data = "<data>")]
|
||||
pub async fn install(
|
||||
data: Json<InstallData>,
|
||||
state: &State<AppState>
|
||||
) -> Result<status::Custom<Json<InstallReplyData>>, status::Custom<String>> {
|
||||
let mut config = state.configure.lock().await;
|
||||
if config.info.install {
|
||||
return Err(AppError::Database("Database already initialized".to_string()));
|
||||
return Err(status::Custom(Status::BadRequest, "Database already initialized".to_string()));
|
||||
}
|
||||
|
||||
let data=data.into_inner();
|
||||
|
||||
relational::Database::initial_setup(data.sql_config.clone())
|
||||
.await
|
||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||
.map_err(|e| status::Custom(Status::InternalServerError, e.to_string()))?;
|
||||
|
||||
config.info.install = true;
|
||||
|
||||
state.link_sql(data.sql_config.clone());
|
||||
let sql= state.get_sql()
|
||||
.await?
|
||||
.get_db();
|
||||
state.link_sql(data.sql_config.clone()).await?;
|
||||
let sql= state.get_sql().await?;
|
||||
|
||||
|
||||
let system_name=utils::generate_random_string(20);
|
||||
let system_password=utils::generate_random_string(20);
|
||||
|
||||
let mut builder = builder::QueryBuilder::new(builder::SqlOperation::Insert,String::from("persons"))?;
|
||||
|
||||
let user_params=HashMap::new();
|
||||
user_params.insert("person_name", data.name);
|
||||
user_params.insert("person_email", data.email);
|
||||
user_params.insert("person_password", data.password);
|
||||
user_params.insert("person_role", data.name);
|
||||
let _ = person::insert(&sql,person::RegisterData{ name: data.name.clone(), email: data.email, password:data.password }).await?;
|
||||
let _ = person::insert(&sql,person::RegisterData{ name: system_name.clone(), email: String::from("author@lsy22.com"), password:system_name.clone() }).await?;
|
||||
let token = auth::jwt::generate_jwt(
|
||||
auth::jwt::CustomClaims{name:data.name.clone()},
|
||||
Duration::days(7)
|
||||
).map_err(|e| status::Custom(Status::Unauthorized, e.to_string()))?;
|
||||
|
||||
|
||||
|
||||
config::Config::write(config.clone())
|
||||
.map_err(|e| AppError::Config(e.to_string()))?;
|
||||
Ok()
|
||||
.map_err(|e| status::Custom(Status::InternalServerError, e.to_string()))?;
|
||||
Ok(
|
||||
status::Custom(
|
||||
Status::Ok,
|
||||
Json(InstallReplyData{
|
||||
token:token,
|
||||
name: system_name,
|
||||
password: system_password
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
mod intsall;
|
||||
pub mod intsall;
|
||||
pub mod person;
|
||||
use rocket::routes;
|
||||
|
||||
pub fn create_routes() -> routes {
|
||||
routes!["/", intsall::install]
|
||||
}
|
||||
// pub fn create_routes() -> Vec<rocket::Route> {
|
||||
|
||||
// }
|
||||
|
||||
|
68
backend/src/routes/person.rs
Normal file
68
backend/src/routes/person.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use serde::{Deserialize,Serialize};
|
||||
use crate::{config,utils};
|
||||
use crate::database::{relational,relational::builder};
|
||||
use crate::{AppError,AppResult};
|
||||
use rocket::{
|
||||
get, post,
|
||||
http::Status,
|
||||
response::status,
|
||||
serde::json::Json,
|
||||
State,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use bcrypt::{hash, verify, DEFAULT_COST};
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct LoginData{
|
||||
pub name:String,
|
||||
pub password:String
|
||||
}
|
||||
|
||||
pub struct RegisterData{
|
||||
pub name:String,
|
||||
pub email:String,
|
||||
pub password:String
|
||||
}
|
||||
|
||||
pub async fn insert(sql:&relational::Database,data:RegisterData) -> AppResult<()>{
|
||||
let hashed_password = hash(data.password, DEFAULT_COST).expect("Failed to hash password");
|
||||
|
||||
|
||||
let mut user_params=HashMap::new();
|
||||
user_params.insert(
|
||||
builder::ValidatedValue::Identifier(String::from("person_name"))
|
||||
,
|
||||
builder::ValidatedValue::PlainText(data.name)
|
||||
);
|
||||
user_params.insert(
|
||||
builder::ValidatedValue::Identifier(String::from("person_email"))
|
||||
,
|
||||
builder::ValidatedValue::PlainText(data.email)
|
||||
);
|
||||
user_params.insert(
|
||||
builder::ValidatedValue::Identifier(String::from("person_password"))
|
||||
,
|
||||
builder::ValidatedValue::PlainText(hashed_password)
|
||||
);
|
||||
|
||||
let builder = builder::QueryBuilder::new(builder::SqlOperation::Insert,String::from("persons"))
|
||||
.map_err(|e|{
|
||||
AppError::Database(format!("Error while building query: {}", e.to_string()))
|
||||
})?
|
||||
.params(user_params)
|
||||
;
|
||||
|
||||
let _= sql.get_db().execute_query(&builder).await.map_err(|e|{
|
||||
AppError::Database(format!("Travel during execution: {}", e.to_string()))
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete(){}
|
||||
|
||||
pub fn update(){}
|
||||
|
||||
pub fn select(){}
|
||||
|
||||
pub fn check(){}
|
Loading…
Reference in New Issue
Block a user