feat: add key context for graphql permission error

This commit is contained in:
master 2025-02-23 00:46:03 +08:00
parent 4f9e74ceb4
commit 7adc0582aa
2 changed files with 98 additions and 13 deletions

View File

@ -1,5 +1,6 @@
use std::fmt; use std::fmt;
use async_graphql::dynamic::ResolverContext;
use axum::{ use axum::{
Json, Json,
http::StatusCode, http::StatusCode,
@ -75,14 +76,48 @@ pub enum AuthError {
#[error("Subject missing")] #[error("Subject missing")]
OidcSubMissingError, OidcSubMissingError,
#[error(fmt = display_graphql_permission_error)] #[error(fmt = display_graphql_permission_error)]
GraphQLPermissionError(async_graphql::Error), GraphQLPermissionError {
inner_error: async_graphql::Error,
field: String,
column: String,
context_path: String,
},
}
impl AuthError {
pub fn from_graphql_subscribe_id_guard(
inner_error: async_graphql::Error,
context: &ResolverContext,
field_name: &str,
column_name: &str,
) -> AuthError {
AuthError::GraphQLPermissionError {
inner_error,
field: field_name.to_string(),
column: column_name.to_string(),
context_path: context
.ctx
.path_node
.map(|p| p.to_string_vec().join(""))
.unwrap_or_default(),
}
}
} }
fn display_graphql_permission_error( fn display_graphql_permission_error(
error: &async_graphql::Error, inner_error: &async_graphql::Error,
field: &String,
column: &String,
context_path: &String,
formatter: &mut fmt::Formatter<'_>, formatter: &mut fmt::Formatter<'_>,
) -> fmt::Result { ) -> fmt::Result {
write!(formatter, "GraphQL permission denied: {}", error.message) write!(
formatter,
"GraphQL permission denied since {context_path}{}{field}{}{column}: {}",
(if field.is_empty() { "" } else { "." }),
(if column.is_empty() { "" } else { "." }),
inner_error.message
)
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]

View File

@ -24,7 +24,7 @@ fn guard_data_object_accessor_with_subscriber_id(
if id == subscriber_id as i64 { if id == subscriber_id as i64 {
Ok(()) Ok(())
} else { } else {
Err(async_graphql::Error::new("subscriber permission denied")) Err(async_graphql::Error::new("subscriber not match"))
} }
} }
@ -43,7 +43,7 @@ fn guard_data_object_accessor_with_optional_subscriber_id(
if id == subscriber_id as i64 { if id == subscriber_id as i64 {
Ok(()) Ok(())
} else { } else {
Err(async_graphql::Error::new("subscriber permission denied")) Err(async_graphql::Error::new("subscriber not match"))
} }
} else { } else {
Ok(()) Ok(())
@ -66,7 +66,7 @@ fn guard_filter_object_accessor_with_subscriber_id(
if id == subscriber_id as i64 { if id == subscriber_id as i64 {
Ok(()) Ok(())
} else { } else {
Err(async_graphql::Error::new("subscriber permission denied")) Err(async_graphql::Error::new("subscriber not match"))
} }
} }
@ -100,7 +100,7 @@ where
entity_name, entity_name,
context.entity_delete_mutation.mutation_suffix.clone() context.entity_delete_mutation.mutation_suffix.clone()
)); ));
let entity_delete_filter_field_name = let entity_delete_mutation_filter_field_name =
Arc::new(context.entity_delete_mutation.filter_field.clone()); Arc::new(context.entity_delete_mutation.filter_field.clone());
let entity_update_mutation_field_name = Arc::new(format!( let entity_update_mutation_field_name = Arc::new(format!(
"{}{}", "{}{}",
@ -126,6 +126,14 @@ where
&column_name, &column_name,
subscriber_id, subscriber_id,
) )
})
.map_err(|inner_error| {
AuthError::from_graphql_subscribe_id_guard(
inner_error,
context,
&entity_create_one_mutation_data_field_name,
&column_name,
)
}), }),
field if field == entity_create_batch_mutation_field_name.as_str() => context field if field == entity_create_batch_mutation_field_name.as_str() => context
.args .args
@ -140,16 +148,32 @@ where
) )
}) })
}) })
})
.map_err(|inner_error| {
AuthError::from_graphql_subscribe_id_guard(
inner_error,
context,
&entity_create_batch_mutation_data_field_name,
&column_name,
)
}), }),
field if field == entity_delete_mutation_field_name.as_str() => context field if field == entity_delete_mutation_field_name.as_str() => context
.args .args
.try_get(&entity_delete_filter_field_name) .try_get(&entity_delete_mutation_filter_field_name)
.and_then(|filter_value| { .and_then(|filter_value| {
guard_filter_object_accessor_with_subscriber_id( guard_filter_object_accessor_with_subscriber_id(
filter_value, filter_value,
&column_name, &column_name,
subscriber_id, subscriber_id,
) )
})
.map_err(|inner_error| {
AuthError::from_graphql_subscribe_id_guard(
inner_error,
context,
&entity_delete_mutation_filter_field_name,
&column_name,
)
}), }),
field if field == entity_update_mutation_field_name.as_str() => context field if field == entity_update_mutation_field_name.as_str() => context
.args .args
@ -161,6 +185,14 @@ where
subscriber_id, subscriber_id,
) )
}) })
.map_err(|inner_error| {
AuthError::from_graphql_subscribe_id_guard(
inner_error,
context,
&entity_update_mutation_filter_field_name,
&column_name,
)
})
.and_then(|_| { .and_then(|_| {
match context.args.get(&entity_update_mutation_data_field_name) { match context.args.get(&entity_update_mutation_data_field_name) {
Some(data_value) => { Some(data_value) => {
@ -169,6 +201,14 @@ where
&column_name, &column_name,
subscriber_id, subscriber_id,
) )
.map_err(|inner_error| {
AuthError::from_graphql_subscribe_id_guard(
inner_error,
context,
&entity_update_mutation_data_field_name,
&column_name,
)
})
} }
None => Ok(()), None => Ok(()),
} }
@ -182,13 +222,23 @@ where
&column_name, &column_name,
subscriber_id, subscriber_id,
) )
})
.map_err(|inner_error| {
AuthError::from_graphql_subscribe_id_guard(
inner_error,
context,
&entity_query_filter_field_name,
&column_name,
)
}), }),
field => Err(async_graphql::Error::new(format!( field => Err(AuthError::from_graphql_subscribe_id_guard(
"unsupport graphql field {}", async_graphql::Error::new("unsupport graphql field"),
field context,
))), field,
"",
)),
}; };
match validation_result.map_err(AuthError::GraphQLPermissionError) { match validation_result {
Ok(_) => GuardAction::Allow, Ok(_) => GuardAction::Allow,
Err(err) => GuardAction::Block(Some(err.to_string())), Err(err) => GuardAction::Block(Some(err.to_string())),
} }