feat: add key context for graphql permission error
This commit is contained in:
parent
4f9e74ceb4
commit
7adc0582aa
@ -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)]
|
||||||
|
@ -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())),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user