use async_graphql::{EmptySubscription, Object as GQLObject, ObjectType, Schema, SubscriptionType};
use std::any::Any;
use std::sync::Mutex;
use crate::errors::*;
use crate::graphql_utils::{get_auth_data_from_ctx, get_pubsub_from_ctx};
use crate::is_authed;
use crate::pubsub::{PubSub, Publisher};
#[derive(Default, Clone)]
pub struct SubscriptionQuery;
#[GQLObject]
impl SubscriptionQuery {
async fn _query(&self) -> String {
"This is a meaningless endpoint needed only for initialisation.".to_string()
}
}
#[derive(Default, Clone)]
pub struct PublishMutation;
#[GQLObject]
impl PublishMutation {
async fn publish(
&self,
raw_ctx: &async_graphql::Context<'_>,
channel: String,
data: String,
) -> Result<bool> {
if is_authed!(
get_auth_data_from_ctx(raw_ctx)?,
{
"role" => "graphql_server"
}
) {
let mut pubsub = get_pubsub_from_ctx(raw_ctx)?;
pubsub.publish(&channel, data);
Ok(true)
} else {
bail!(ErrorKind::Unauthorised)
}
}
}
#[derive(Clone)]
pub struct SubscriptionsServerInformation {
pub hostname: String,
pub port: String, pub endpoint: String,
pub jwt_to_connect: String, }
#[derive(Clone)]
pub struct UserSchema<Q, M, S>
where
Q: ObjectType + 'static,
M: ObjectType + 'static,
S: SubscriptionType + 'static,
{
pub query_root: Q,
pub mutation_root: M,
pub subscription_root: S,
}
pub fn get_schema_without_subscriptions<C, Q, M, S>(
user_schema: UserSchema<Q, M, S>,
subscription_server_info: Option<SubscriptionsServerInformation>,
user_ctx: C,
) -> Result<Schema<Q, M, EmptySubscription>>
where
C: Any + Send + Sync,
Q: ObjectType + 'static,
M: ObjectType + 'static,
S: SubscriptionType + 'static,
{
let schema = Schema::build(
user_schema.query_root,
user_schema.mutation_root,
EmptySubscription,
)
.data(user_ctx);
let schema = match subscription_server_info {
Some(subscription_server_info) => schema
.data(Publisher::new(
subscription_server_info.hostname,
subscription_server_info.port,
subscription_server_info.endpoint,
subscription_server_info.jwt_to_connect,
)?)
.finish(),
None => schema.finish(),
};
Ok(schema)
}
pub fn get_schema_for_subscriptions<C, Q, M, S>(
user_schema: UserSchema<Q, M, S>,
user_ctx: C,
) -> Schema<SubscriptionQuery, PublishMutation, S>
where
C: Any + Send + Sync,
Q: ObjectType + 'static,
M: ObjectType + 'static,
S: SubscriptionType + 'static,
{
Schema::build(
SubscriptionQuery,
PublishMutation,
user_schema.subscription_root,
)
.data(user_ctx)
.data(Mutex::new(PubSub::default())) .finish()
}