2024-11-26 12:19:57 +08:00
|
|
|
use crate::security;
|
|
|
|
use crate::storage::sql::builder;
|
|
|
|
use crate::common::error::{AppResult, AppResultInto};
|
2024-11-25 03:36:24 +08:00
|
|
|
use crate::AppState;
|
2024-11-22 13:13:04 +08:00
|
|
|
use chrono::Duration;
|
2024-11-25 03:36:24 +08:00
|
|
|
use rocket::{
|
|
|
|
http::Status,
|
|
|
|
post,
|
|
|
|
response::status,
|
|
|
|
serde::json::{Json, Value},
|
|
|
|
State,
|
|
|
|
};
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use serde_json::json;
|
|
|
|
use std::sync::Arc;
|
|
|
|
#[derive(Deserialize, Serialize)]
|
|
|
|
pub struct TokenSystemData {
|
2024-11-26 12:19:57 +08:00
|
|
|
username: String,
|
2024-11-25 03:36:24 +08:00
|
|
|
password: String,
|
|
|
|
}
|
|
|
|
#[post("/system", format = "application/json", data = "<data>")]
|
|
|
|
pub async fn token_system(
|
|
|
|
state: &State<Arc<AppState>>,
|
|
|
|
data: Json<TokenSystemData>,
|
|
|
|
) -> AppResult<String> {
|
|
|
|
let mut builder =
|
2024-11-26 12:19:57 +08:00
|
|
|
builder::QueryBuilder::new(builder::SqlOperation::Select, "users".to_string())
|
2024-11-25 03:36:24 +08:00
|
|
|
.into_app_result()?;
|
2024-11-25 22:43:24 +08:00
|
|
|
builder
|
2024-11-26 12:19:57 +08:00
|
|
|
.add_field("password_hash".to_string())
|
2024-11-25 22:43:24 +08:00
|
|
|
.into_app_result()?
|
|
|
|
.add_condition(builder::WhereClause::And(vec![
|
|
|
|
builder::WhereClause::Condition(
|
|
|
|
builder::Condition::new(
|
2024-11-26 12:19:57 +08:00
|
|
|
"username".to_string(),
|
2024-11-25 22:43:24 +08:00
|
|
|
builder::Operator::Eq,
|
|
|
|
Some(builder::SafeValue::Text(
|
2024-11-26 12:19:57 +08:00
|
|
|
data.username.clone(),
|
2024-11-25 22:43:24 +08:00
|
|
|
builder::ValidationLevel::Relaxed,
|
|
|
|
)),
|
|
|
|
)
|
|
|
|
.into_app_result()?,
|
|
|
|
),
|
|
|
|
builder::WhereClause::Condition(
|
|
|
|
builder::Condition::new(
|
2024-11-26 12:19:57 +08:00
|
|
|
"email".to_string(),
|
2024-11-25 22:43:24 +08:00
|
|
|
builder::Operator::Eq,
|
|
|
|
Some(builder::SafeValue::Text(
|
|
|
|
"author@lsy22.com".into(),
|
|
|
|
builder::ValidationLevel::Relaxed,
|
|
|
|
)),
|
|
|
|
)
|
|
|
|
.into_app_result()?,
|
|
|
|
),
|
|
|
|
builder::WhereClause::Condition(
|
|
|
|
builder::Condition::new(
|
2024-11-26 12:19:57 +08:00
|
|
|
"role".to_string(),
|
2024-11-25 22:43:24 +08:00
|
|
|
builder::Operator::Eq,
|
|
|
|
Some(builder::SafeValue::Enum(
|
2024-11-26 12:19:57 +08:00
|
|
|
"administrator".into(),
|
|
|
|
"user_role".into(),
|
2024-11-25 22:43:24 +08:00
|
|
|
builder::ValidationLevel::Standard,
|
|
|
|
)),
|
|
|
|
)
|
|
|
|
.into_app_result()?,
|
|
|
|
),
|
|
|
|
]));
|
2024-11-25 03:36:24 +08:00
|
|
|
|
|
|
|
let values = state
|
|
|
|
.sql_get()
|
|
|
|
.await
|
|
|
|
.into_app_result()?
|
|
|
|
.get_db()
|
2024-11-25 22:43:24 +08:00
|
|
|
.execute_query(&builder)
|
2024-11-25 03:36:24 +08:00
|
|
|
.await
|
|
|
|
.into_app_result()?;
|
|
|
|
|
|
|
|
let password = values
|
|
|
|
.first()
|
2024-11-26 12:19:57 +08:00
|
|
|
.and_then(|row| row.get("password_hash"))
|
2024-11-25 22:43:24 +08:00
|
|
|
.and_then(|val| val.as_str())
|
|
|
|
.ok_or_else(|| {
|
|
|
|
status::Custom(Status::NotFound, "Invalid system user or password".into())
|
|
|
|
})?;
|
2024-11-22 13:13:04 +08:00
|
|
|
|
2024-11-26 12:19:57 +08:00
|
|
|
security::bcrypt::verify_hash(&data.password, password)
|
2024-11-25 22:43:24 +08:00
|
|
|
.map_err(|_| status::Custom(Status::Forbidden, "Invalid password".into()))?;
|
2024-11-22 13:13:04 +08:00
|
|
|
|
2024-11-26 12:19:57 +08:00
|
|
|
Ok(security::jwt::generate_jwt(
|
|
|
|
security::jwt::CustomClaims {
|
2024-11-25 22:43:24 +08:00
|
|
|
name: "system".into(),
|
|
|
|
},
|
|
|
|
Duration::minutes(1),
|
|
|
|
)
|
|
|
|
.into_app_result()?)
|
2024-11-22 13:13:04 +08:00
|
|
|
}
|