use std::sync::Arc; use async_graphql::dynamic::{ResolverContext, ValueAccessor}; use sea_orm::EntityTrait; use seaography::{BuilderContext, FnGuard, GuardAction}; use super::util::{get_column_key, get_entity_key}; use crate::auth::{AuthError, AuthUserInfo}; fn guard_data_object_accessor_with_subscriber_id( value: ValueAccessor<'_>, column_name: &str, subscriber_id: i32, ) -> async_graphql::Result<()> { let obj = value.object()?; let subscriber_id_value = obj.try_get(column_name)?; let id = subscriber_id_value.i64()?; if id == subscriber_id as i64 { Ok(()) } else { Err(async_graphql::Error::new("subscriber not match")) } } fn guard_data_object_accessor_with_optional_subscriber_id( value: ValueAccessor<'_>, column_name: &str, subscriber_id: i32, ) -> async_graphql::Result<()> { if value.is_null() { return Ok(()); } let obj = value.object()?; if let Some(subscriber_id_value) = obj.get(column_name) { let id = subscriber_id_value.i64()?; if id == subscriber_id as i64 { Ok(()) } else { Err(async_graphql::Error::new("subscriber not match")) } } else { Ok(()) } } pub fn guard_entity_with_subscriber_id(_context: &BuilderContext, _column: &T::Column) -> FnGuard where T: EntityTrait, ::Model: Sync, { Box::new(move |context: &ResolverContext| -> GuardAction { match context.ctx.data::() { Ok(_) => GuardAction::Allow, Err(err) => GuardAction::Block(Some(err.message)), } }) } pub fn guard_field_with_subscriber_id(context: &BuilderContext, column: &T::Column) -> FnGuard where T: EntityTrait, ::Model: Sync, { let entity_key = get_entity_key::(context); let entity_name = context.entity_query_field.type_name.as_ref()(&entity_key); let column_key = get_column_key::(context, column); let column_name = Arc::new(context.entity_object.column_name.as_ref()( &entity_key, &column_key, )); let entity_create_one_mutation_field_name = Arc::new(format!( "{}{}", entity_name, context.entity_create_one_mutation.mutation_suffix )); let entity_create_one_mutation_data_field_name = Arc::new(context.entity_create_one_mutation.data_field.clone()); let entity_create_batch_mutation_field_name = Arc::new(format!( "{}{}", entity_name, context.entity_create_batch_mutation.mutation_suffix.clone() )); let entity_create_batch_mutation_data_field_name = Arc::new(context.entity_create_batch_mutation.data_field.clone()); let entity_update_mutation_field_name = Arc::new(format!( "{}{}", entity_name, context.entity_update_mutation.mutation_suffix )); let entity_update_mutation_data_field_name = Arc::new(context.entity_update_mutation.data_field.clone()); Box::new(move |context: &ResolverContext| -> GuardAction { match context.ctx.data::() { Ok(user_info) => { let subscriber_id = user_info.subscriber_auth.subscriber_id; let validation_result = match context.field().name() { field if field == entity_create_one_mutation_field_name.as_str() => { if let Some(data_value) = context .args .get(&entity_create_one_mutation_data_field_name) { guard_data_object_accessor_with_subscriber_id( data_value, &column_name, subscriber_id, ) .map_err(|inner_error| { AuthError::from_graphql_subscribe_id_guard( inner_error, context, &entity_create_one_mutation_data_field_name, &column_name, ) }) } else { Ok(()) } } field if field == entity_create_batch_mutation_field_name.as_str() => { if let Some(data_value) = context .args .get(&entity_create_batch_mutation_data_field_name) { data_value .list() .and_then(|data_list| { data_list.iter().try_for_each(|data_item_value| { guard_data_object_accessor_with_optional_subscriber_id( data_item_value, &column_name, subscriber_id, ) }) }) .map_err(|inner_error| { AuthError::from_graphql_subscribe_id_guard( inner_error, context, &entity_create_batch_mutation_data_field_name, &column_name, ) }) } else { Ok(()) } } field if field == entity_update_mutation_field_name.as_str() => { if let Some(data_value) = context.args.get(&entity_update_mutation_data_field_name) { guard_data_object_accessor_with_optional_subscriber_id( data_value, &column_name, subscriber_id, ) .map_err(|inner_error| { AuthError::from_graphql_subscribe_id_guard( inner_error, context, &entity_update_mutation_data_field_name, &column_name, ) }) } else { Ok(()) } } _ => Ok(()), }; match validation_result { Ok(_) => GuardAction::Allow, Err(err) => GuardAction::Block(Some(err.to_string())), } } Err(err) => GuardAction::Block(Some(err.message)), } }) }