This commit is contained in:
parent
8791aee96c
commit
7a64171b96
@ -62,8 +62,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_md5() {
|
fn test_md5() {
|
||||||
let input = "hello";
|
// let input = "hello";
|
||||||
|
let input = "joylink0503";
|
||||||
let output = md5(input);
|
let output = md5(input);
|
||||||
assert_eq!(output, "5d41402abc4b2a76b9719d911017c592");
|
println!("{}", output);
|
||||||
|
// assert_eq!(output, "5d41402abc4b2a76b9719d911017c592");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,10 @@ fn main() {
|
|||||||
"common.DataType",
|
"common.DataType",
|
||||||
"#[derive(sqlx::Type, async_graphql::Enum, serde::Serialize, serde::Deserialize)]",
|
"#[derive(sqlx::Type, async_graphql::Enum, serde::Serialize, serde::Deserialize)]",
|
||||||
)
|
)
|
||||||
|
.type_attribute(
|
||||||
|
"common.LineType",
|
||||||
|
"#[derive(async_graphql::Enum, serde::Serialize, serde::Deserialize)]",
|
||||||
|
)
|
||||||
.type_attribute(
|
.type_attribute(
|
||||||
"common.IscsStyle",
|
"common.IscsStyle",
|
||||||
"#[derive(async_graphql::Enum, serde::Serialize, serde::Deserialize)]",
|
"#[derive(async_graphql::Enum, serde::Serialize, serde::Deserialize)]",
|
||||||
|
@ -199,6 +199,56 @@ impl DataType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// 线路类型
|
||||||
|
#[derive(
|
||||||
|
async_graphql::Enum,
|
||||||
|
serde::Serialize,
|
||||||
|
serde::Deserialize,
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
::prost::Enumeration,
|
||||||
|
)]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum LineType {
|
||||||
|
/// 未知
|
||||||
|
Unknown = 0,
|
||||||
|
/// 城市轨道交通
|
||||||
|
Ur = 1,
|
||||||
|
/// 城际轨道交通
|
||||||
|
Ir = 2,
|
||||||
|
/// 市域轨道交通
|
||||||
|
Cr = 3,
|
||||||
|
}
|
||||||
|
impl LineType {
|
||||||
|
/// String value of the enum field names used in the ProtoBuf definition.
|
||||||
|
///
|
||||||
|
/// The values are not transformed in any way and thus are considered stable
|
||||||
|
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||||
|
pub fn as_str_name(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
LineType::Unknown => "LineType_Unknown",
|
||||||
|
LineType::Ur => "LineType_Ur",
|
||||||
|
LineType::Ir => "LineType_Ir",
|
||||||
|
LineType::Cr => "LineType_Cr",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
|
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||||
|
match value {
|
||||||
|
"LineType_Unknown" => Some(Self::Unknown),
|
||||||
|
"LineType_Ur" => Some(Self::Ur),
|
||||||
|
"LineType_Ir" => Some(Self::Ir),
|
||||||
|
"LineType_Cr" => Some(Self::Cr),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(
|
#[derive(
|
||||||
async_graphql::Enum,
|
async_graphql::Enum,
|
||||||
serde::Serialize,
|
serde::Serialize,
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
use async_graphql::{InputObject, InputType, OutputType, SimpleObject};
|
use async_graphql::{InputObject, InputType, OutputType, SimpleObject};
|
||||||
use rtsa_db::{common::TableColumn, model::DraftDataColumn};
|
use rtsa_db::{common::TableColumn, model::DraftDataColumn};
|
||||||
use rtsa_dto::common::IscsStyle;
|
use rtsa_dto::common::{IscsStyle, LineType};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
pub trait DataOptions: InputType + OutputType + Serialize + DeserializeOwned {
|
pub trait DataOptions: InputType + OutputType + Serialize + DeserializeOwned {
|
||||||
fn to_data_options_filter_clause(&self) -> String;
|
fn to_data_options_filter_clause(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DataOptions for Value {
|
// impl DataOptions for Value {
|
||||||
|
// fn to_data_options_filter_clause(&self) -> String {
|
||||||
|
// format!("{} @> '{}'", DraftDataColumn::Options.name(), self)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<T> DataOptions for T
|
||||||
|
where
|
||||||
|
T: ?Sized + Serialize + DeserializeOwned + OutputType + InputType,
|
||||||
|
{
|
||||||
fn to_data_options_filter_clause(&self) -> String {
|
fn to_data_options_filter_clause(&self) -> String {
|
||||||
format!("{} @> '{}'", DraftDataColumn::Options.name(), self)
|
format!(
|
||||||
|
"{} @> '{}'",
|
||||||
|
DraftDataColumn::Options.name(),
|
||||||
|
serde_json::to_string(self).unwrap()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,14 +32,14 @@ pub struct IscsDataOptions {
|
|||||||
pub style: IscsStyle,
|
pub style: IscsStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DataOptions for IscsDataOptions {
|
#[derive(Debug, Clone, InputObject, SimpleObject, Serialize, Deserialize)]
|
||||||
fn to_data_options_filter_clause(&self) -> String {
|
#[graphql(input_name = "LineInfoOptionsInput")]
|
||||||
let options_column = DraftDataColumn::Options.name();
|
pub struct LineInfoOptions {
|
||||||
format!(
|
pub line_type: LineType,
|
||||||
"{options_column} @> '{}'",
|
/// 城轨线路所属城市
|
||||||
serde_json::to_string(self).unwrap()
|
pub city: Option<String>,
|
||||||
)
|
/// 城轨线路编号
|
||||||
}
|
pub line_code: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -11,7 +11,7 @@ use serde_json::Value;
|
|||||||
use crate::apis::{PageDto, PageQueryDto};
|
use crate::apis::{PageDto, PageQueryDto};
|
||||||
use crate::loader::RtsaDbLoader;
|
use crate::loader::RtsaDbLoader;
|
||||||
|
|
||||||
use super::data_options_def::{DataOptions, IscsDataOptions};
|
use super::data_options_def::{DataOptions, IscsDataOptions, LineInfoOptions};
|
||||||
use super::release_data::ReleaseDataId;
|
use super::release_data::ReleaseDataId;
|
||||||
use super::user::UserId;
|
use super::user::UserId;
|
||||||
|
|
||||||
@ -39,6 +39,37 @@ impl DraftDataQuery {
|
|||||||
.await?;
|
.await?;
|
||||||
Ok(paging_result.into())
|
Ok(paging_result.into())
|
||||||
}
|
}
|
||||||
|
/// 分页查询用户电子地图草稿数据
|
||||||
|
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||||
|
async fn user_draft_em_data_paging<'ctx>(
|
||||||
|
&self,
|
||||||
|
ctx: &Context<'ctx>,
|
||||||
|
paging: PageQueryDto,
|
||||||
|
mut query: UserDraftDataFilterDto<LineInfoOptions>,
|
||||||
|
) -> async_graphql::Result<PageDto<DraftEmDataDto>> {
|
||||||
|
let claims = ctx.data::<Jwt>()?.decode()?;
|
||||||
|
query = query.with_data_type_and_user_id(DataType::Em, claims.uid);
|
||||||
|
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
|
||||||
|
let paging_result = db_accessor
|
||||||
|
.paging_query_draft_data(query.into(), paging.into())
|
||||||
|
.await?;
|
||||||
|
Ok(paging_result.into())
|
||||||
|
}
|
||||||
|
/// 分页查询共享的草稿电子地图数据
|
||||||
|
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||||
|
async fn shared_draft_em_data_paging<'ctx>(
|
||||||
|
&self,
|
||||||
|
ctx: &Context<'ctx>,
|
||||||
|
paging: PageQueryDto,
|
||||||
|
mut query: DraftDataFilterDto<LineInfoOptions>,
|
||||||
|
) -> async_graphql::Result<PageDto<DraftEmDataDto>> {
|
||||||
|
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
|
||||||
|
query.data_type = Some(DataType::Em);
|
||||||
|
let paging_result = db_accessor
|
||||||
|
.paging_query_draft_data(query.into(), paging.into())
|
||||||
|
.await?;
|
||||||
|
Ok(paging_result.into())
|
||||||
|
}
|
||||||
/// 分页查询用户的草稿ISCS数据
|
/// 分页查询用户的草稿ISCS数据
|
||||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||||
async fn user_draft_iscs_data_paging<'ctx>(
|
async fn user_draft_iscs_data_paging<'ctx>(
|
||||||
@ -48,8 +79,7 @@ impl DraftDataQuery {
|
|||||||
mut query: UserDraftDataFilterDto<IscsDataOptions>,
|
mut query: UserDraftDataFilterDto<IscsDataOptions>,
|
||||||
) -> async_graphql::Result<PageDto<DraftIscsDataDto>> {
|
) -> async_graphql::Result<PageDto<DraftIscsDataDto>> {
|
||||||
let claims = ctx.data::<Jwt>()?.decode()?;
|
let claims = ctx.data::<Jwt>()?.decode()?;
|
||||||
query.user_id = claims.uid;
|
query = query.with_data_type_and_user_id(DataType::Iscs, claims.uid);
|
||||||
query.data_type = Some(DataType::Iscs);
|
|
||||||
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
|
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
|
||||||
let paging_result = db_accessor
|
let paging_result = db_accessor
|
||||||
.paging_query_draft_data(query.into(), paging.into())
|
.paging_query_draft_data(query.into(), paging.into())
|
||||||
@ -98,6 +128,20 @@ impl DraftDataQuery {
|
|||||||
|
|
||||||
#[Object]
|
#[Object]
|
||||||
impl DraftDataMutation {
|
impl DraftDataMutation {
|
||||||
|
/// 创建电子地图草稿数据
|
||||||
|
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||||
|
async fn create_draft_em_data(
|
||||||
|
&self,
|
||||||
|
ctx: &Context<'_>,
|
||||||
|
mut input: CreateDraftDataDto<LineInfoOptions>,
|
||||||
|
) -> async_graphql::Result<DraftDataDto> {
|
||||||
|
let claims = ctx.data::<Jwt>()?.decode()?;
|
||||||
|
input = input.with_data_type_and_user_id(DataType::Em, claims.uid);
|
||||||
|
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
|
||||||
|
let draft_data = db_accessor.create_draft_data(input.into()).await?;
|
||||||
|
Ok(draft_data.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// 创建草稿ISCS数据
|
/// 创建草稿ISCS数据
|
||||||
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
#[graphql(guard = "RoleGuard::new(Role::User)")]
|
||||||
async fn create_draft_iscs_data(
|
async fn create_draft_iscs_data(
|
||||||
@ -194,6 +238,7 @@ impl DraftDataMutation {
|
|||||||
|
|
||||||
#[derive(Debug, InputObject)]
|
#[derive(Debug, InputObject)]
|
||||||
#[graphql(concrete(name = "CreateDraftIscsDto", params(IscsDataOptions)))]
|
#[graphql(concrete(name = "CreateDraftIscsDto", params(IscsDataOptions)))]
|
||||||
|
#[graphql(concrete(name = "CreateDraftEmDto", params(LineInfoOptions)))]
|
||||||
pub struct CreateDraftDataDto<T: DataOptions> {
|
pub struct CreateDraftDataDto<T: DataOptions> {
|
||||||
#[graphql(skip)]
|
#[graphql(skip)]
|
||||||
pub data_type: Option<DataType>,
|
pub data_type: Option<DataType>,
|
||||||
@ -228,6 +273,7 @@ impl<T: DataOptions> From<CreateDraftDataDto<T>> for rtsa_db::CreateDraftData {
|
|||||||
|
|
||||||
/// 用户的草稿数据查询条件
|
/// 用户的草稿数据查询条件
|
||||||
#[derive(Debug, InputObject)]
|
#[derive(Debug, InputObject)]
|
||||||
|
#[graphql(concrete(name = "UserDraftEmDataFilterDto", params(LineInfoOptions)))]
|
||||||
#[graphql(concrete(name = "UserDraftIscsDataFilterDto", params(IscsDataOptions)))]
|
#[graphql(concrete(name = "UserDraftIscsDataFilterDto", params(IscsDataOptions)))]
|
||||||
pub struct UserDraftDataFilterDto<T: DataOptions> {
|
pub struct UserDraftDataFilterDto<T: DataOptions> {
|
||||||
#[graphql(skip)]
|
#[graphql(skip)]
|
||||||
@ -239,6 +285,14 @@ pub struct UserDraftDataFilterDto<T: DataOptions> {
|
|||||||
pub is_shared: Option<bool>,
|
pub is_shared: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: DataOptions> UserDraftDataFilterDto<T> {
|
||||||
|
pub fn with_data_type_and_user_id(mut self, data_type: DataType, id: i32) -> Self {
|
||||||
|
self.data_type = Some(data_type);
|
||||||
|
self.user_id = id;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtsa_db::DraftDataQuery {
|
impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtsa_db::DraftDataQuery {
|
||||||
fn from(value: UserDraftDataFilterDto<T>) -> Self {
|
fn from(value: UserDraftDataFilterDto<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -254,6 +308,7 @@ impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtsa_db::DraftDataQuery
|
|||||||
/// 共享的草稿数据查询条件
|
/// 共享的草稿数据查询条件
|
||||||
#[derive(Debug, InputObject)]
|
#[derive(Debug, InputObject)]
|
||||||
#[graphql(concrete(name = "DraftDataFilterDto", params(Value)))]
|
#[graphql(concrete(name = "DraftDataFilterDto", params(Value)))]
|
||||||
|
#[graphql(concrete(name = "SharedDraftEmDataFilterDto", params(LineInfoOptions)))]
|
||||||
#[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))]
|
#[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))]
|
||||||
|
|
||||||
pub struct DraftDataFilterDto<T: DataOptions> {
|
pub struct DraftDataFilterDto<T: DataOptions> {
|
||||||
@ -336,6 +391,26 @@ impl From<rtsa_db::model::DraftDataModel> for DraftDataDto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 草稿电子地图数据
|
||||||
|
#[derive(Debug, SimpleObject)]
|
||||||
|
pub struct DraftEmDataDto {
|
||||||
|
pub draft_data: DraftDataDto,
|
||||||
|
pub options: Option<LineInfoOptions>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<rtsa_db::model::DraftDataModel> for DraftEmDataDto {
|
||||||
|
fn from(value: rtsa_db::model::DraftDataModel) -> Self {
|
||||||
|
Self {
|
||||||
|
options: value
|
||||||
|
.options
|
||||||
|
.clone()
|
||||||
|
.map(|o| serde_json::from_value(o).unwrap()),
|
||||||
|
draft_data: value.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ISCS草稿数据
|
||||||
#[derive(Debug, SimpleObject)]
|
#[derive(Debug, SimpleObject)]
|
||||||
pub struct DraftIscsDataDto {
|
pub struct DraftIscsDataDto {
|
||||||
pub draft_data: DraftDataDto,
|
pub draft_data: DraftDataDto,
|
||||||
|
@ -67,6 +67,7 @@ impl From<PageQueryDto> for rtsa_db::common::PageQuery {
|
|||||||
#[derive(Debug, SimpleObject)]
|
#[derive(Debug, SimpleObject)]
|
||||||
#[graphql(concrete(name = "UserPageDto", params(user::UserDto)))]
|
#[graphql(concrete(name = "UserPageDto", params(user::UserDto)))]
|
||||||
#[graphql(concrete(name = "DraftDataPageDto", params(draft_data::DraftDataDto)))]
|
#[graphql(concrete(name = "DraftDataPageDto", params(draft_data::DraftDataDto)))]
|
||||||
|
#[graphql(concrete(name = "DraftEmDataPageDto", params(draft_data::DraftEmDataDto)))]
|
||||||
#[graphql(concrete(name = "DraftIscsDataPageDto", params(draft_data::DraftIscsDataDto)))]
|
#[graphql(concrete(name = "DraftIscsDataPageDto", params(draft_data::DraftIscsDataDto)))]
|
||||||
#[graphql(concrete(name = "ReleaseDataPageDto", params(release_data::ReleaseDataDto)))]
|
#[graphql(concrete(name = "ReleaseDataPageDto", params(release_data::ReleaseDataDto)))]
|
||||||
#[graphql(concrete(
|
#[graphql(concrete(
|
||||||
|
@ -72,6 +72,13 @@ mod tests {
|
|||||||
assert_eq!(org.name, DEFAULT_ORG_NAME);
|
assert_eq!(org.name, DEFAULT_ORG_NAME);
|
||||||
assert_eq!(org.creator_id, user.id);
|
assert_eq!(org.creator_id, user.id);
|
||||||
|
|
||||||
|
let user = db_accessor
|
||||||
|
.query_user_login(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
|
||||||
|
.await?;
|
||||||
|
assert_eq!(user.username, ADMIN_USER_NAME);
|
||||||
|
assert_eq!(user.nickname, ADMIN_USER_NAME);
|
||||||
|
assert_eq!(user.roles, json!([Role::Admin]));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use async_graphql::Guard;
|
use async_graphql::Guard;
|
||||||
use rtsa_db::prelude::*;
|
use rtsa_db::prelude::*;
|
||||||
use rtsa_dto::common::Role;
|
use rtsa_dto::common::Role;
|
||||||
use rtsa_log::tracing::{info, warn};
|
use rtsa_log::tracing::{error, info, warn};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
mod jwt_auth;
|
mod jwt_auth;
|
||||||
@ -113,9 +113,24 @@ pub(crate) async fn handle_login(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(BusinessError::AuthError(
|
DbAccessError::PasswordNotMatch => {
|
||||||
"用户不存在或密码不正确".to_string(),
|
warn!(
|
||||||
)),
|
"密码不匹配: username={}, password={}, org_id={}",
|
||||||
|
user_login_dto.username, user_login_dto.password, org_id
|
||||||
|
);
|
||||||
|
Err(BusinessError::AuthError(
|
||||||
|
"用户不存在或密码不正确".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!(
|
||||||
|
"查询用户登录验证错误: username={}, org_id={}, error={:?}",
|
||||||
|
user_login_dto.username, org_id, e
|
||||||
|
);
|
||||||
|
Err(BusinessError::AuthError(
|
||||||
|
"用户不存在或密码不正确".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 867c075833ffbe64b0291db921adddc9d5d5a7a3
|
Subproject commit a30bf52339620075e8d666be363eb3d93d532656
|
Loading…
Reference in New Issue
Block a user