diff --git a/apps/recorder/Cargo.toml b/apps/recorder/Cargo.toml index 0ca9d80..a7b1167 100644 --- a/apps/recorder/Cargo.toml +++ b/apps/recorder/Cargo.toml @@ -91,7 +91,7 @@ bollard = { version = "0.18", optional = true } async-graphql = { version = "7.0.15", features = [] } async-graphql-axum = "7.0.15" fastrand = "2.3.0" -seaography = "1.1" +seaography = { version = "1.1" } quirks_path = "0.1.1" base64 = "0.22.1" tower = "0.5.2" diff --git a/apps/recorder/src/graphql/extention.rs b/apps/recorder/src/graphql/extention.rs deleted file mode 100644 index 4fb80c8..0000000 --- a/apps/recorder/src/graphql/extention.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::sync::Arc; - -use async_graphql::{ - ServerResult, Value, - extensions::{Extension, ExtensionContext, ExtensionFactory, NextResolve, ResolveInfo}, -}; - -pub struct GraphqlAuthExtension; - -#[async_trait::async_trait] -impl Extension for GraphqlAuthExtension { - async fn resolve( - &self, - ctx: &ExtensionContext<'_>, - info: ResolveInfo<'_>, - next: NextResolve<'_>, - ) -> ServerResult> { - dbg!(info.field); - next.run(ctx, info).await - } -} - -impl ExtensionFactory for GraphqlAuthExtension { - fn create(&self) -> Arc { - Arc::new(GraphqlAuthExtension) - } -} diff --git a/apps/recorder/src/graphql/filter.rs b/apps/recorder/src/graphql/filter.rs new file mode 100644 index 0000000..6ca5720 --- /dev/null +++ b/apps/recorder/src/graphql/filter.rs @@ -0,0 +1,46 @@ +use async_graphql::dynamic::{ObjectAccessor, TypeRef}; +use maplit::btreeset; +use once_cell::sync::OnceCell; +use sea_orm::{ColumnTrait, Condition, EntityTrait, Value}; +use seaography::{BuilderContext, FilterInfo, FilterOperation, SeaResult}; + +pub static SUBSCRIBER_ID_FILTER_INFO: OnceCell = OnceCell::new(); + +pub fn init_custom_filter_info() { + SUBSCRIBER_ID_FILTER_INFO.get_or_init(|| FilterInfo { + type_name: String::from("SubscriberIdFilterInput"), + base_type: TypeRef::INT.into(), + supported_operations: btreeset! { FilterOperation::Equals }, + }); +} + +pub type FnFilterCondition = + Box SeaResult + Send + Sync>; + +pub fn subscriber_id_condition_function( + _context: &BuilderContext, + column: &T::Column, +) -> FnFilterCondition +where + T: EntityTrait, + ::Model: Sync, +{ + let column = *column; + Box::new(move |mut condition, filter| { + let subscriber_id_filter_info = SUBSCRIBER_ID_FILTER_INFO.get().unwrap(); + let operations = &subscriber_id_filter_info.supported_operations; + for operation in operations { + match operation { + FilterOperation::Equals => { + if let Some(value) = filter.get("eq") { + let value: i32 = value.i64()?.try_into()?; + let value = Value::Int(Some(value)); + condition = condition.add(column.eq(value)); + } + } + _ => unreachable!("unreachable filter operation for subscriber_id"), + } + } + Ok(condition) + }) +} diff --git a/apps/recorder/src/graphql/mod.rs b/apps/recorder/src/graphql/mod.rs index e840e1f..d5336d6 100644 --- a/apps/recorder/src/graphql/mod.rs +++ b/apps/recorder/src/graphql/mod.rs @@ -1,8 +1,8 @@ pub mod config; -pub mod extention; pub mod guard; pub mod schema_root; pub mod service; pub mod util; +pub mod filter; pub use schema_root::schema; diff --git a/apps/recorder/src/graphql/schema_root.rs b/apps/recorder/src/graphql/schema_root.rs index a692fc6..77658eb 100644 --- a/apps/recorder/src/graphql/schema_root.rs +++ b/apps/recorder/src/graphql/schema_root.rs @@ -1,10 +1,13 @@ use async_graphql::dynamic::*; use once_cell::sync::OnceCell; use sea_orm::{DatabaseConnection, EntityTrait, Iterable}; -use seaography::{Builder, BuilderContext, FilterType, FnGuard}; +use seaography::{Builder, BuilderContext, FilterType, FilterTypesMapHelper}; -use super::util::{get_entity_column_key, get_entity_key}; -use crate::graphql::guard::guard_entity_with_subscriber_id; +use super::{ + filter::{SUBSCRIBER_ID_FILTER_INFO, subscriber_id_condition_function}, + util::{get_entity_column_key, get_entity_key}, +}; +use crate::graphql::{filter::init_custom_filter_info, guard::guard_entity_with_subscriber_id}; static CONTEXT: OnceCell = OnceCell::new(); @@ -20,19 +23,27 @@ fn restrict_filter_input_for_entity( context.filter_types.overwrites.insert(key, filter_type); } -fn restrict_subscriber_for_entity( - context: &mut BuilderContext, - column: &T::Column, - entity_guard: impl FnOnce(&BuilderContext, &T::Column) -> FnGuard, -) where +fn restrict_subscriber_for_entity(context: &mut BuilderContext, column: &T::Column) +where T: EntityTrait, ::Model: Sync, { let entity_key = get_entity_key::(context); - context - .guards - .entity_guards - .insert(entity_key, entity_guard(context, column)); + let entity_column_key = get_entity_column_key::(context, column); + context.guards.entity_guards.insert( + entity_key, + guard_entity_with_subscriber_id::(context, column), + ); + context.filter_types.overwrites.insert( + entity_column_key.clone(), + Some(FilterType::Custom( + SUBSCRIBER_ID_FILTER_INFO.get().unwrap().type_name.clone(), + )), + ); + context.filter_types.condition_functions.insert( + entity_column_key, + subscriber_id_condition_function::(context, column), + ); } pub fn schema( @@ -41,47 +52,41 @@ pub fn schema( complexity: Option, ) -> Result { use crate::models::*; + init_custom_filter_info(); let context = CONTEXT.get_or_init(|| { let mut context = BuilderContext::default(); + restrict_subscriber_for_entity::( &mut context, &bangumi::Column::SubscriberId, - guard_entity_with_subscriber_id::, ); restrict_subscriber_for_entity::( &mut context, &downloaders::Column::SubscriberId, - guard_entity_with_subscriber_id::, ); restrict_subscriber_for_entity::( &mut context, &downloads::Column::SubscriberId, - guard_entity_with_subscriber_id::, ); restrict_subscriber_for_entity::( &mut context, &episodes::Column::SubscriberId, - guard_entity_with_subscriber_id::, ); restrict_subscriber_for_entity::( &mut context, &subscriptions::Column::SubscriberId, - guard_entity_with_subscriber_id::, ); restrict_subscriber_for_entity::( &mut context, &subscribers::Column::Id, - guard_entity_with_subscriber_id::, ); restrict_subscriber_for_entity::( &mut context, &subscription_bangumi::Column::SubscriberId, - guard_entity_with_subscriber_id::, ); restrict_subscriber_for_entity::( &mut context, &subscription_episode::Column::SubscriberId, - guard_entity_with_subscriber_id::, ); for column in subscribers::Column::iter() { if !matches!(column, subscribers::Column::Id) { @@ -96,6 +101,14 @@ pub fn schema( }); let mut builder = Builder::new(context, database.clone()); + { + let filter_types_map_helper = FilterTypesMapHelper { context }; + + builder.schema = builder.schema.register( + filter_types_map_helper.generate_filter_input(SUBSCRIBER_ID_FILTER_INFO.get().unwrap()), + ); + } + { builder.register_entity::( ::iter()