fix: fix credential3rd graphql

This commit is contained in:
2025-05-24 02:32:02 +08:00
parent 0fcbc6bbe9
commit 66413f92e3
23 changed files with 837 additions and 1009 deletions

View File

@@ -1,3 +1,6 @@
use async_graphql::Error as AsyncGraphQLError;
use seaography::SeaographyError;
#[derive(Debug, snafu::Snafu)]
pub enum CryptoError {
#[snafu(transparent)]
@@ -9,3 +12,9 @@ pub enum CryptoError {
#[snafu(transparent)]
SerdeJsonError { source: serde_json::Error },
}
impl From<CryptoError> for SeaographyError {
fn from(error: CryptoError) -> Self {
SeaographyError::AsyncGraphQLError(AsyncGraphQLError::new(error.to_string()))
}
}

View File

@@ -1,13 +1,15 @@
use std::{collections::BTreeMap, sync::Arc};
use async_graphql::dynamic::ResolverContext;
use sea_orm::{ColumnTrait, Condition, EntityTrait, Value};
use seaography::{BuilderContext, FnFilterConditionsTransformer, FnMutationInputObjectTransformer};
use async_graphql::dynamic::{ResolverContext, ValueAccessor};
use sea_orm::{ColumnTrait, Condition, EntityTrait, Value as SeaValue};
use seaography::{
BuilderContext, FnFilterConditionsTransformer, FnMutationInputObjectTransformer, SeaResult,
};
use super::util::{get_column_key, get_entity_key};
use crate::auth::AuthUserInfo;
use crate::{app::AppContextTrait, auth::AuthUserInfo, models::credential_3rd};
pub fn filter_condition_transformer<T>(
pub fn build_filter_condition_transformer<T>(
_context: &BuilderContext,
column: &T::Column,
) -> FnFilterConditionsTransformer
@@ -29,7 +31,7 @@ where
)
}
pub fn mutation_input_object_transformer<T>(
pub fn build_mutation_input_object_transformer<T>(
context: &BuilderContext,
column: &T::Column,
) -> FnMutationInputObjectTransformer
@@ -55,8 +57,8 @@ where
));
Box::new(
move |context: &ResolverContext,
mut input: BTreeMap<String, Value>|
-> BTreeMap<String, Value> {
mut input: BTreeMap<String, SeaValue>|
-> BTreeMap<String, SeaValue> {
let field_name = context.field().name();
if field_name == entity_create_one_mutation_field_name.as_str()
|| field_name == entity_create_batch_mutation_field_name.as_str()
@@ -68,7 +70,7 @@ where
if value.is_none() {
input.insert(
column_name.as_str().to_string(),
Value::Int(Some(subscriber_id)),
SeaValue::Int(Some(subscriber_id)),
);
}
input
@@ -81,3 +83,91 @@ where
},
)
}
fn add_crypto_column_input_conversion<T>(
context: &mut BuilderContext,
ctx: Arc<dyn AppContextTrait>,
column: &T::Column,
) where
T: EntityTrait,
<T as EntityTrait>::Model: Sync,
{
let entity_key = get_entity_key::<T>(context);
let column_name = get_column_key::<T>(context, column);
let entity_name = context.entity_object.type_name.as_ref()(&entity_key);
let column_name = context.entity_object.column_name.as_ref()(&entity_key, &column_name);
context.types.input_conversions.insert(
format!("{entity_name}.{column_name}"),
Box::new(move |value: &ValueAccessor| -> SeaResult<sea_orm::Value> {
let source = value.string()?;
let encrypted = ctx.crypto().encrypt_string(source.into())?;
Ok(encrypted.into())
}),
);
}
fn add_crypto_column_output_conversion<T>(
context: &mut BuilderContext,
ctx: Arc<dyn AppContextTrait>,
column: &T::Column,
) where
T: EntityTrait,
<T as EntityTrait>::Model: Sync,
{
let entity_key = get_entity_key::<T>(context);
let column_name = get_column_key::<T>(context, column);
let entity_name = context.entity_object.type_name.as_ref()(&entity_key);
let column_name = context.entity_object.column_name.as_ref()(&entity_key, &column_name);
context.types.output_conversions.insert(
format!("{entity_name}.{column_name}"),
Box::new(
move |value: &sea_orm::Value| -> SeaResult<async_graphql::Value> {
if let SeaValue::String(s) = value {
if let Some(s) = s {
let decrypted = ctx.crypto().decrypt_string(s)?;
Ok(async_graphql::Value::String(decrypted))
} else {
Ok(async_graphql::Value::Null)
}
} else {
Err(async_graphql::Error::new("crypto column must be string column").into())
}
},
),
);
}
pub fn crypto_transformer(context: &mut BuilderContext, ctx: Arc<dyn AppContextTrait>) {
add_crypto_column_input_conversion::<credential_3rd::Entity>(
context,
ctx.clone(),
&credential_3rd::Column::Cookies,
);
add_crypto_column_input_conversion::<credential_3rd::Entity>(
context,
ctx.clone(),
&credential_3rd::Column::Username,
);
add_crypto_column_output_conversion::<credential_3rd::Entity>(
context,
ctx.clone(),
&credential_3rd::Column::Password,
);
add_crypto_column_output_conversion::<credential_3rd::Entity>(
context,
ctx.clone(),
&credential_3rd::Column::Cookies,
);
add_crypto_column_output_conversion::<credential_3rd::Entity>(
context,
ctx.clone(),
&credential_3rd::Column::Username,
);
add_crypto_column_output_conversion::<credential_3rd::Entity>(
context,
ctx,
&credential_3rd::Column::Password,
);
}

View File

@@ -1,9 +1,9 @@
pub mod config;
pub mod infra;
pub mod schema_root;
mod schema;
pub mod service;
pub mod views;
pub use config::GraphQLConfig;
pub use schema_root::schema;
pub use schema::build_schema;
pub use service::GraphQLService;

View File

@@ -10,7 +10,9 @@ use crate::graphql::{
register_jsonb_input_filter_to_dynamic_schema, subscriber_id_condition_function,
},
guard::{guard_entity_with_subscriber_id, guard_field_with_subscriber_id},
transformer::{filter_condition_transformer, mutation_input_object_transformer},
transformer::{
build_filter_condition_transformer, build_mutation_input_object_transformer,
},
util::{get_entity_column_key, get_entity_key},
},
views::register_subscriptions_to_schema,
@@ -69,14 +71,14 @@ where
);
context.transformers.filter_conditions_transformers.insert(
entity_key.clone(),
filter_condition_transformer::<T>(context, column),
build_filter_condition_transformer::<T>(context, column),
);
context
.transformers
.mutation_input_object_transformers
.insert(
entity_key,
mutation_input_object_transformer::<T>(context, column),
build_mutation_input_object_transformer::<T>(context, column),
);
context
.entity_input
@@ -85,7 +87,7 @@ where
context.entity_input.update_skips.push(entity_column_key);
}
pub fn schema(
pub fn build_schema(
database: DatabaseConnection,
depth: Option<usize>,
complexity: Option<usize>,
@@ -138,6 +140,10 @@ pub fn schema(
&mut context,
&subscriber_tasks::Column::SubscriberId,
);
restrict_subscriber_for_entity::<credential_3rd::Entity>(
&mut context,
&credential_3rd::Column::SubscriberId,
);
restrict_jsonb_filter_input_for_entity::<subscriber_tasks::Entity>(
&mut context,
&subscriber_tasks::Column::Job,
@@ -185,6 +191,7 @@ pub fn schema(
subscription_episode,
subscriptions,
subscriber_tasks,
credential_3rd
]
);
@@ -193,6 +200,7 @@ pub fn schema(
builder.register_enumeration::<subscriptions::SubscriptionCategory>();
builder.register_enumeration::<downloaders::DownloaderCategory>();
builder.register_enumeration::<downloads::DownloadMime>();
builder.register_enumeration::<credential_3rd::Credential3rdType>();
}
{

View File

@@ -1,7 +1,7 @@
use async_graphql::dynamic::Schema;
use sea_orm::DatabaseConnection;
use super::{config::GraphQLConfig, schema_root};
use super::{build_schema, config::GraphQLConfig};
use crate::errors::RecorderResult;
#[derive(Debug)]
@@ -14,7 +14,7 @@ impl GraphQLService {
config: GraphQLConfig,
db: DatabaseConnection,
) -> RecorderResult<Self> {
let schema = schema_root::schema(
let schema = build_schema(
db,
config.depth_limit.and_then(|l| l.into()),
config.complexity_limit.and_then(|l| l.into()),

View File

@@ -66,6 +66,14 @@ impl Related<super::subscriptions::Entity> for Entity {
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelatedEntity)]
pub enum RelatedEntity {
#[sea_orm(entity = "super::subscribers::Entity")]
Subscriber,
#[sea_orm(entity = "super::subscriptions::Entity")]
Subscription,
}
#[async_trait]
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -39,6 +39,8 @@ pub enum Relation {
Episode,
#[sea_orm(has_many = "super::auth::Entity")]
Auth,
#[sea_orm(has_many = "super::credential_3rd::Entity")]
Credential3rd,
}
impl Related<super::subscriptions::Entity> for Entity {
@@ -71,6 +73,12 @@ impl Related<super::auth::Entity> for Entity {
}
}
impl Related<super::credential_3rd::Entity> for Entity {
fn to() -> RelationDef {
Relation::Credential3rd.def()
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelatedEntity)]
pub enum RelatedEntity {
#[sea_orm(entity = "super::subscriptions::Entity")]
@@ -81,6 +89,8 @@ pub enum RelatedEntity {
Bangumi,
#[sea_orm(entity = "super::episodes::Entity")]
Episode,
#[sea_orm(entity = "super::credential_3rd::Entity")]
Credential3rd,
}
#[derive(Debug, Deserialize, Serialize)]
@@ -103,7 +113,7 @@ impl Model {
let subscriber = Entity::find_by_id(id)
.one(db)
.await?
.ok_or_else(|| RecorderError::from_db_record_not_found("subscriptions::find_by_id"))?;
.ok_or_else(|| RecorderError::from_db_record_not_found("subscribers::find_by_id"))?;
Ok(subscriber)
}

View File

@@ -141,6 +141,8 @@ pub enum RelatedEntity {
SubscriptionEpisode,
#[sea_orm(entity = "super::subscription_bangumi::Entity")]
SubscriptionBangumi,
#[sea_orm(entity = "super::credential_3rd::Entity")]
Credential3rd,
}
#[async_trait]